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..bbb718c8bf43e --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/debuginfo.rs @@ -0,0 +1,12 @@ +use rustc_hir::attrs::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 f7946ade6d2b2..a59ecd44b187c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -31,6 +31,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 911d2e133107d..4f7d29db317f4 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::{ TargetFeatureParser, TrackCallerParser, 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}; @@ -186,6 +187,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..4b5780738126f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -9,8 +9,10 @@ use libc::{c_longlong, c_uint}; use rustc_abi::{Align, Size}; use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; use rustc_codegen_ssa::traits::*; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::find_attr; use rustc_middle::bug; use rustc_middle::ty::layout::{ HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA, @@ -1070,6 +1072,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 5c63d4808db2f..a412ddb0b50d5 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -667,6 +667,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 1303b3317e05a..65d6858f1fbe3 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -460,6 +460,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_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index d9d2ec48948e7..6ee43520518e7 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -303,6 +303,9 @@ pub enum AttributeKind { /// Represents `#[coverage(..)]`. Coverage(Span, CoverageAttrKind), + /// Represents `#[debuginfo_transparent]`. + DebuginfoTransparent(Span), + ///Represents `#[rustc_deny_explicit_impl]`. DenyExplicitImpl(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b66e5bbeabe73..d07ae4636a2b7 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -30,6 +30,7 @@ impl AttributeKind { ConstTrait(..) => No, Coroutine(..) => No, Coverage(..) => No, + DebuginfoTransparent { .. } => Yes, DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, DoNotImplementViaObject(..) => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 890028d977d30..7870a23384d9d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -184,6 +184,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 d54175548e30e..bc88839ff7fcc 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 3c33f4b136844..99d1d6a800911 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 d57b1d433e51c..0b74f874dd335 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 e9e13f9e97f84..3d295d353a274 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] pub struct Unique { pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index c8f4a32cb17e2..005c9957eb3a1 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,9 @@ 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 +436,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 392cf697e110b..bac75dbc60872 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -8,7 +8,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" @@ -20,7 +20,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 @@ -39,7 +39,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)] pub struct Foo<'a> {