Skip to content

Add debuginfo_transparent attribute for structs #144223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ pub enum AttributeKind {
/// Represents `#[coverage]`.
Coverage(Span, CoverageStatus),

/// Represents `#[debuginfo_transparent]`.
DebuginfoTransparent(Span),

///Represents `#[rustc_deny_explicit_impl]`.
DenyExplicitImpl(Span),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ impl AttributeKind {
ConstStabilityIndirect => No,
ConstTrait(..) => No,
Coverage(..) => No,
DebuginfoTransparent { .. } => Yes,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
DoNotImplementViaObject(..) => No,
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/debuginfo.rs
Original file line number Diff line number Diff line change
@@ -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<S: Stage> NoArgsAttributeParser<S> for DebuginfoTransparentParser {
const PATH: &[Symbol] = &[sym::debuginfo_transparent];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DebuginfoTransparent;
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -167,6 +168,7 @@ attribute_parsers!(
Single<WithoutArgs<ConstContinueParser>>,
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<ConstTraitParser>>,
Single<WithoutArgs<DebuginfoTransparentParser>>,
Single<WithoutArgs<DenyExplicitImplParser>>,
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
Single<WithoutArgs<ExportStableParser>>,
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to ensure that #[debuginfo_transparent] can only be used when #[repr(transparent)] is also used? And how should I handle the case where all fields are 1zst's?


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(
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
// ==========================================================================
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@
(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),

Check failure on line 466 in compiler/rustc_feature/src/unstable.rs

View workflow job for this annotation

GitHub Actions / PR - tidy

no tracking issue for feature debuginfo_attrs

Check failure on line 466 in compiler/rustc_feature/src/unstable.rs

View workflow job for this annotation

GitHub Actions / PR - aarch64-gnu-llvm-19-2

no tracking issue for feature debuginfo_attrs
/// 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
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_parse/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ pub fn check_builtin_meta_item(
| sym::no_implicit_prelude
| sym::automatically_derived
| sym::coverage
| sym::debuginfo_transparent
) {
return;
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,8 @@ symbols! {
debug_tuple,
debug_tuple_fields_finish,
debugger_visualizer,
debuginfo_attrs,
debuginfo_transparent,
decl_macro,
declare_lint_pass,
decode,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
1 change: 1 addition & 0 deletions library/core/src/num/niche_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: PointeeSized> {
// Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
Expand Down
1 change: 1 addition & 0 deletions library/core/src/ptr/unique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: PointeeSized> {
Expand Down
33 changes: 21 additions & 12 deletions src/etc/gdb_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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()
Expand Down
1 change: 1 addition & 0 deletions src/tools/tidy/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
39 changes: 39 additions & 0 deletions tests/debuginfo/debuginfo-attrs.rs
Original file line number Diff line number Diff line change
@@ -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: [<Raw View>] [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() {}
5 changes: 2 additions & 3 deletions tests/debuginfo/strings-and-strs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// gdb-command:run

// gdb-command:print plain_string
// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {inner: alloc::raw_vec::RawVecInner<alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x[...]}, _marker: core::marker::PhantomData<u8>}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData<u8>}, len: 5}}
// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {inner: alloc::raw_vec::RawVecInner<alloc::alloc::Global> {ptr: 0x[...], cap: 5, alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData<u8>}, len: 5}}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the improvement this PR causes. Further improvements could be made using future #[debuginfo_flatten] and #[debuginfo_hidden] attributes on RawVec/RawVecInner and the _marker field, which would result in

alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {ptr: 0x[...], cap: 5, alloc: alloc::alloc::Global, len: 5}}


// gdb-command:print plain_str
// gdb-check:$2 = "Hello"
Expand All @@ -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<alloc::rc::RcInner<&str>> {pointer: 0x[...]}, phantom: core::marker::PhantomData<alloc::rc::RcInner<&str>>, 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
Expand All @@ -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]
Expand Down
Loading