diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 3157b18b63515..b55b9981b0050 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -293,6 +293,9 @@ pub enum AttributeKind { /// Represents `#[coverage]`. Coverage(Span, CoverageStatus), + /// Represents `#[debuginfo_transparent]`. + DebuginfoTransparent(Span), + ///Represents `#[rustc_deny_explicit_impl]`. DenyExplicitImpl(Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 86d9ddba4d230..ff9fed4dc13c7 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -29,6 +29,7 @@ impl AttributeKind { ConstStabilityIndirect => No, ConstTrait(..) => No, Coverage(..) => No, + DebuginfoTransparent { .. } => Yes, DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, DoNotImplementViaObject(..) => No, diff --git a/compiler/rustc_attr_parsing/src/attributes/debuginfo.rs b/compiler/rustc_attr_parsing/src/attributes/debuginfo.rs new file mode 100644 index 0000000000000..2b5e20d9d3365 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/debuginfo.rs @@ -0,0 +1,12 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_span::{Span, Symbol, sym}; + +use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; +use crate::context::Stage; + +pub(crate) struct DebuginfoTransparentParser; +impl NoArgsAttributeParser for DebuginfoTransparentParser { + const PATH: &[Symbol] = &[sym::debuginfo_transparent]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::DebuginfoTransparent; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 200f138196029..b5af104e2a4d8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -30,6 +30,7 @@ pub(crate) mod cfg; pub(crate) mod cfg_old; pub(crate) mod codegen_attrs; pub(crate) mod confusables; +pub(crate) mod debuginfo; pub(crate) mod deprecation; pub(crate) mod dummy; pub(crate) mod inline; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 4d692d9562c1e..69f7cbd61b28a 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -22,6 +22,7 @@ use crate::attributes::codegen_attrs::{ UsedParser, }; use crate::attributes::confusables::ConfusablesParser; +use crate::attributes::debuginfo::DebuginfoTransparentParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; @@ -167,6 +168,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 0e9dbfba658d2..e55f7849af6d8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -7,6 +7,7 @@ use std::{iter, ptr}; use libc::{c_longlong, c_uint}; use rustc_abi::{Align, Size}; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; @@ -1070,6 +1071,16 @@ fn build_struct_type_di_node<'ll, 'tcx>( None }; + if find_attr!(cx.tcx.get_all_attrs(adt_def.did()), AttributeKind::DebuginfoTransparent(..)) { + let ty = struct_type_and_layout.non_1zst_field(cx).unwrap().1.ty; + + let di_node = type_di_node(cx, ty); + + return_if_di_node_created_in_meantime!(cx, unique_type_id); + + return DINodeCreationResult::new(di_node, false); + } + type_map::build_type_with_children( cx, type_map::stub( diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 74872504b79f9..6e2bcd7926735 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -666,6 +666,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, loop_match, experimental!(loop_match) ), + gated!( + debuginfo_transparent, Normal, template!(Word), WarnFollowing, + EncodeCrossCrate::Yes, debuginfo_attrs, experimental!(debuginfo_transparent) + ), + // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e985e04ba3307..5d4ff2dc4012a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -462,6 +462,8 @@ declare_features! ( (unstable, custom_inner_attributes, "1.30.0", Some(54726)), /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. (unstable, custom_test_frameworks, "1.30.0", Some(50297)), + /// Allows `debuginfo_*` attributes. + (unstable, debuginfo_attrs, "CURRENT_RUSTC_VERSION", None), /// Allows declarative macros 2.0 (`macro`). (unstable, decl_macro, "1.17.0", Some(39412)), /// Allows the use of default values on struct definitions and the construction of struct diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index a476f0db37e0d..26431dba970a5 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -319,6 +319,7 @@ pub fn check_builtin_meta_item( | sym::no_implicit_prelude | sym::automatically_derived | sym::coverage + | sym::debuginfo_transparent ) { return; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3ec6a1124a620..c1e88dc3aed5d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -170,6 +170,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target, Target::Impl { of_trait: true }, ), + Attribute::Parsed(AttributeKind::DebuginfoTransparent(attr_span)) => self + .check_generic_attr( + hir_id, + sym::debuginfo_transparent, + *attr_span, + target, + Target::Struct, + ), Attribute::Parsed( AttributeKind::Stability { span: attr_span, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d28a73bc13978..35439eae8e55c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -805,6 +805,8 @@ symbols! { debug_tuple, debug_tuple_fields_finish, debugger_visualizer, + debuginfo_attrs, + debuginfo_transparent, decl_macro, declare_lint_pass, decode, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 729de5ffc8f6e..d3aa7a76b334d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -108,6 +108,7 @@ #![feature(const_eval_select)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] +#![feature(debuginfo_attrs)] #![feature(disjoint_bitor)] #![feature(internal_impls_macro)] #![feature(ip)] diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index b92561c9e356d..95a6c93a41e18 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -18,6 +18,7 @@ macro_rules! define_valid_range_type { #[repr(transparent)] #[rustc_layout_scalar_valid_range_start($low)] #[rustc_layout_scalar_valid_range_end($high)] + #[debuginfo_transparent] $(#[$m])* $vis struct $name($int); diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 62da6567cca75..48d515b6641ac 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -72,6 +72,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonNull"] +#[debuginfo_transparent] pub struct NonNull { // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to // this is banned by . diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index c069314ff7d23..ddf03f6fb79f6 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -32,6 +32,7 @@ use crate::ptr::NonNull; )] #[doc(hidden)] #[repr(transparent)] +#[debuginfo_transparent] // Lang item used experimentally by Miri to define the semantics of `Unique`. #[lang = "ptr_unique"] pub struct Unique { diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index c8f4a32cb17e2..bd8897188b2a7 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -10,12 +10,15 @@ def unwrap_unique_or_non_null(unique_or_nonnull): - # BACKCOMPAT: rust 1.32 - # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067 - # BACKCOMPAT: rust 1.60 - # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f - ptr = unique_or_nonnull["pointer"] - return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]] + if unique_or_nonnull.type.code != gdb.TYPE_CODE_PTR: + # BACKCOMPAT: rust 1.32 + # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067 + # BACKCOMPAT: rust 1.60 + # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f + # BACKCOMPAT: rust 1.89 + ptr = unique_or_nonnull["pointer"] + return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]] + return unique_or_nonnull # GDB 14 has a tag class that indicates that extension methods are ok @@ -255,12 +258,16 @@ def __init__(self, valobj): field = list(fields)[0] inner_valobj = valobj[field.name] + if inner_valobj.type.code != gdb.TYPE_CODE_INT: + # BACKCOMPAT: rust 1.89 + inner_fields = inner_valobj.type.fields() + assert len(inner_fields) == 1 + inner_field = list(inner_fields)[0] - inner_fields = inner_valobj.type.fields() - assert len(inner_fields) == 1 - inner_field = list(inner_fields)[0] + self._value = str(inner_valobj[inner_field.name]) + return - self._value = str(inner_valobj[inner_field.name]) + self._value = inner_valobj def to_string(self): return self._value @@ -277,7 +284,8 @@ def cast_to_internal(node): internal_type = gdb.lookup_type(internal_type_name) return node.cast(internal_type.pointer()) - if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"): + if node_ptr.type.name is not None and \ + node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"): # BACKCOMPAT: rust 1.49 node_ptr = node_ptr["ptr"] node_ptr = unwrap_unique_or_non_null(node_ptr) @@ -427,7 +435,8 @@ def __init__(self, valobj, show_values=True): table = self._table() table_inner = table["table"] capacity = int(table_inner["bucket_mask"]) + 1 - ctrl = table_inner["ctrl"]["pointer"] + # BACKCOMPAT: rust 1.89 + ctrl = unwrap_unique_or_non_null(table_inner["ctrl"]) self._size = int(table_inner["items"]) self._pair_type = table.type.template_argument(0).strip_typedefs() diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index fb00b3a943f87..c17762c9eceb6 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -100,6 +100,7 @@ pub fn check( walk_many( &[ + &tests_path.join("debuginfo"), &tests_path.join("ui"), &tests_path.join("ui-fulldeps"), &tests_path.join("rustdoc-ui"), diff --git a/tests/debuginfo/debuginfo-attrs.rs b/tests/debuginfo/debuginfo-attrs.rs new file mode 100644 index 0000000000000..a309e38571d29 --- /dev/null +++ b/tests/debuginfo/debuginfo-attrs.rs @@ -0,0 +1,39 @@ +//@ compile-flags:-g + +// gate-test-debuginfo_attrs +// Tests the `#[debuginfo_transparent]` attribute. + +// === CDB TESTS ================================================================================== +// cdb-command: g + +// cdb-command: dx transparent +// cdb-check:transparent : 1 [Type: u32] +// cdb-check: [] [Type: u32] + +// === GDB TESTS =================================================================================== + +// gdb-command:run + +// gdb-command:print transparent +// gdb-check:[...]$1 = 1 + +// === LLDB TESTS ================================================================================== + +// lldb-command:run + +// lldb-command:v transparent +// lldb-check:[...] 1 + +#![feature(debuginfo_attrs)] + +#[repr(transparent)] +#[debuginfo_transparent] +struct Transparent(u32); + +fn main() { + let transparent = Transparent(1); + + zzz(); // #break +} + +fn zzz() {} diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 7d550408bec37..9c5ac4eefe203 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -7,7 +7,7 @@ // gdb-command:run // gdb-command:print plain_string -// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} +// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: 0x[...], cap: 5, alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} // gdb-command:print plain_str // gdb-check:$2 = "Hello" @@ -19,7 +19,7 @@ // gdb-check:$4 = ("Hello", "World") // gdb-command:print str_in_rc -// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: 0x[...], alloc: alloc::alloc::Global} // === LLDB TESTS ================================================================================== // lldb-command:run @@ -38,7 +38,6 @@ // lldb-command:v str_in_rc // lldb-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } - #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section]