Rename #[rustc_layout] to #[rustc_dump_layout]

This commit is contained in:
León Orell Valerian Liehr
2026-04-09 18:37:36 +02:00
committed by Jonathan Brouwer
parent 7659cec4ed
commit 357f670fde
37 changed files with 238 additions and 302 deletions
@@ -1,9 +1,8 @@
use rustc_hir::attrs::AttributeKind;
use rustc_hir::attrs::{AttributeKind, RustcDumpLayoutKind};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use crate::attributes::prelude::Allow;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use super::prelude::*;
use crate::context::Stage;
use crate::target_checking::AllowedTargets;
@@ -48,6 +47,64 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds;
}
pub(crate) struct RustcDumpLayoutParser;
impl<S: Stage> CombineAttributeParser<S> for RustcDumpLayoutParser {
const PATH: &[Symbol] = &[sym::rustc_dump_layout];
type Item = RustcDumpLayoutKind;
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcDumpLayout(items);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::Union),
Allow(Target::TyAlias),
]);
const TEMPLATE: AttributeTemplate =
template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]);
fn extend(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let ArgParser::List(items) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return vec![];
};
let mut result = Vec::new();
for item in items.mixed() {
let Some(arg) = item.meta_item() else {
cx.adcx().expected_not_literal(item.span());
continue;
};
let Some(ident) = arg.ident() else {
cx.adcx().expected_identifier(arg.span());
return vec![];
};
let kind = match ident.name {
sym::abi => RustcDumpLayoutKind::Abi,
sym::align => RustcDumpLayoutKind::Align,
sym::size => RustcDumpLayoutKind::Size,
sym::homogeneous_aggregate => RustcDumpLayoutKind::HomogenousAggregate,
sym::debug => RustcDumpLayoutKind::Debug,
_ => {
cx.adcx().expected_specific_argument(
ident.span,
&[sym::abi, sym::align, sym::size, sym::homogeneous_aggregate, sym::debug],
);
continue;
}
};
result.push(kind);
}
result
}
}
pub(crate) struct RustcDumpObjectLifetimeDefaultsParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpObjectLifetimeDefaultsParser {
@@ -4,8 +4,7 @@
use rustc_hir::LangItem;
use rustc_hir::attrs::{
BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,
DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType,
RustcMirKind,
DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcMirKind,
};
use rustc_session::errors;
use rustc_span::Symbol;
@@ -713,64 +712,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcOffloadKernelParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
}
pub(crate) struct RustcLayoutParser;
impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser {
const PATH: &[Symbol] = &[sym::rustc_layout];
type Item = RustcLayoutType;
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcLayout(items);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::Union),
Allow(Target::TyAlias),
]);
const TEMPLATE: AttributeTemplate =
template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]);
fn extend(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let ArgParser::List(items) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return vec![];
};
let mut result = Vec::new();
for item in items.mixed() {
let Some(arg) = item.meta_item() else {
cx.adcx().expected_not_literal(item.span());
continue;
};
let Some(ident) = arg.ident() else {
cx.adcx().expected_identifier(arg.span());
return vec![];
};
let ty = match ident.name {
sym::abi => RustcLayoutType::Abi,
sym::align => RustcLayoutType::Align,
sym::size => RustcLayoutType::Size,
sym::homogeneous_aggregate => RustcLayoutType::HomogenousAggregate,
sym::debug => RustcLayoutType::Debug,
_ => {
cx.adcx().expected_specific_argument(
ident.span,
&[sym::abi, sym::align, sym::size, sym::homogeneous_aggregate, sym::debug],
);
continue;
}
};
result.push(ty);
}
result
}
}
pub(crate) struct RustcMirParser;
impl<S: Stage> CombineAttributeParser<S> for RustcMirParser {
+1 -1
View File
@@ -172,7 +172,7 @@ mod late {
Combine<ReprParser>,
Combine<RustcAllowConstFnUnstableParser>,
Combine<RustcCleanParser>,
Combine<RustcLayoutParser>,
Combine<RustcDumpLayoutParser>,
Combine<RustcMirParser>,
Combine<RustcThenThisWouldNeedParser>,
Combine<TargetFeatureParser>,
+1 -1
View File
@@ -1453,7 +1453,7 @@ pub struct BuiltinAttribute {
WarnFollowing, EncodeCrossCrate::No
),
rustc_attr!(
TEST, rustc_layout, Normal, template!(List: &["field1, field2, ..."]),
TEST, rustc_dump_layout, Normal, template!(List: &["field1, field2, ..."]),
WarnFollowing, EncodeCrossCrate::Yes
),
rustc_attr!(
@@ -757,7 +757,7 @@ fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
}
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub enum RustcLayoutType {
pub enum RustcDumpLayoutKind {
Abi,
Align,
Size,
@@ -1377,6 +1377,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_dump_item_bounds]`
RustcDumpItemBounds,
/// Represents `#[rustc_dump_layout]`
RustcDumpLayout(ThinVec<RustcDumpLayoutKind>),
/// Represents `#[rustc_dump_object_lifetime_defaults]`.
RustcDumpObjectLifetimeDefaults,
@@ -1427,9 +1430,6 @@ pub enum AttributeKind {
/// Represents `#[rustc_intrinsic_const_stable_indirect]`
RustcIntrinsicConstStableIndirect,
/// Represents `#[rustc_layout]`
RustcLayout(ThinVec<RustcLayoutType>),
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
@@ -127,6 +127,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
RustcDumpDefParents => No,
RustcDumpInferredOutlives => No,
RustcDumpItemBounds => No,
RustcDumpLayout(..) => No,
RustcDumpObjectLifetimeDefaults => No,
RustcDumpPredicates => No,
RustcDumpUserArgs => No,
@@ -144,7 +145,6 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
RustcInsignificantDtor => Yes,
RustcIntrinsic => Yes,
RustcIntrinsicConstStableIndirect => No,
RustcLayout(..) => No,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcLegacyConstGenerics { .. } => Yes,
+1 -1
View File
@@ -313,6 +313,7 @@ fn check_attributes(
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpInferredOutlives
| AttributeKind::RustcDumpItemBounds
| AttributeKind::RustcDumpLayout(..)
| AttributeKind::RustcDumpPredicates
| AttributeKind::RustcDumpUserArgs
| AttributeKind::RustcDumpVariances
@@ -329,7 +330,6 @@ fn check_attributes(
| AttributeKind::RustcInsignificantDtor
| AttributeKind::RustcIntrinsic
| AttributeKind::RustcIntrinsicConstStableIndirect
| AttributeKind::RustcLayout(..)
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
| AttributeKind::RustcLintOptDenyFieldAccess { .. }
-41
View File
@@ -460,47 +460,6 @@ pub(crate) struct DuplicateDiagnosticItemInCrate {
pub name: Symbol,
}
#[derive(Diagnostic)]
#[diag("abi: {$abi}")]
pub(crate) struct LayoutAbi {
#[primary_span]
pub span: Span,
pub abi: String,
}
#[derive(Diagnostic)]
#[diag("align: {$align}")]
pub(crate) struct LayoutAlign {
#[primary_span]
pub span: Span,
pub align: String,
}
#[derive(Diagnostic)]
#[diag("size: {$size}")]
pub(crate) struct LayoutSize {
#[primary_span]
pub span: Span,
pub size: String,
}
#[derive(Diagnostic)]
#[diag("homogeneous_aggregate: {$homogeneous_aggregate}")]
pub(crate) struct LayoutHomogeneousAggregate {
#[primary_span]
pub span: Span,
pub homogeneous_aggregate: String,
}
#[derive(Diagnostic)]
#[diag("layout_of({$normalized_ty}) = {$ty_layout}")]
pub(crate) struct LayoutOf<'tcx> {
#[primary_span]
pub span: Span,
pub normalized_ty: Ty<'tcx>,
pub ty_layout: String,
}
#[derive(Diagnostic)]
#[diag("fn_abi_of({$fn_name}) = {$fn_abi}")]
pub(crate) struct AbiOf {
+24 -46
View File
@@ -1,5 +1,5 @@
use rustc_abi::{HasDataLayout, TargetDataLayout};
use rustc_hir::attrs::RustcLayoutType;
use rustc_hir::attrs::RustcDumpLayoutKind;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::find_attr;
@@ -11,21 +11,18 @@
use rustc_trait_selection::infer::TyCtxtInferExt;
use rustc_trait_selection::traits;
use crate::errors::{LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutOf, LayoutSize};
pub fn test_layout(tcx: TyCtxt<'_>) {
if !tcx.features().rustc_attrs() {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
return;
}
for id in tcx.hir_crate_items(()).definitions() {
if let Some(attrs) = find_attr!(tcx, id, RustcLayout(attrs) => attrs) {
if let Some(kinds) = find_attr!(tcx, id, RustcDumpLayout(kinds) => kinds) {
// Attribute parsing handles error reporting
if matches!(
tcx.def_kind(id),
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union
) {
dump_layout_of(tcx, id, attrs);
if let DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union =
tcx.def_kind(id)
{
dump_layout_of(tcx, id, kinds);
}
}
}
@@ -62,7 +59,7 @@ pub fn ensure_wf<'tcx>(
}
}
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayoutType]) {
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, kinds: &[RustcDumpLayoutKind]) {
let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
let ty = tcx.type_of(item_def_id).instantiate_identity();
let span = tcx.def_span(item_def_id.to_def_id());
@@ -71,46 +68,24 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayout
}
match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(ty_layout) => {
for attr in attrs {
match attr {
for kind in kinds {
let message = match kind {
// FIXME: this never was about ABI and now this dump arg is confusing
RustcLayoutType::Abi => {
tcx.dcx().emit_err(LayoutAbi {
span,
abi: format!("{:?}", ty_layout.backend_repr),
});
RustcDumpLayoutKind::Abi => format!("abi: {:?}", ty_layout.backend_repr),
RustcDumpLayoutKind::Align => format!("align: {:?}", ty_layout.align),
RustcDumpLayoutKind::Size => format!("size: {:?}", ty_layout.size),
RustcDumpLayoutKind::HomogenousAggregate => {
let data =
ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, typing_env });
format!("homogeneous_aggregate: {data:?}")
}
RustcLayoutType::Align => {
tcx.dcx().emit_err(LayoutAlign {
span,
align: format!("{:?}", ty_layout.align),
});
}
RustcLayoutType::Size => {
tcx.dcx()
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
}
RustcLayoutType::HomogenousAggregate => {
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
span,
homogeneous_aggregate: format!(
"{:?}",
ty_layout
.homogeneous_aggregate(&UnwrapLayoutCx { tcx, typing_env })
),
});
}
RustcLayoutType::Debug => {
RustcDumpLayoutKind::Debug => {
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
// FIXME: using the `Debug` impl here isn't ideal.
let ty_layout = format!("{:#?}", *ty_layout);
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
format!("layout_of({normalized_ty}) = {:#?}", *ty_layout)
}
}
};
tcx.dcx().span_err(span, message);
}
}
@@ -127,7 +102,10 @@ struct UnwrapLayoutCx<'tcx> {
impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
span_bug!(span, "`#[rustc_layout(..)]` test resulted in `layout_of({ty}) = Err({err})`",);
span_bug!(
span,
"`#[rustc_dump_layout(..)]` test resulted in `layout_of({ty}) = Err({err})`",
);
}
}
+1 -1
View File
@@ -1722,6 +1722,7 @@
rustc_dump_def_parents,
rustc_dump_inferred_outlives,
rustc_dump_item_bounds,
rustc_dump_layout,
rustc_dump_object_lifetime_defaults,
rustc_dump_predicates,
rustc_dump_user_args,
@@ -1741,7 +1742,6 @@
rustc_insignificant_dtor,
rustc_intrinsic,
rustc_intrinsic_const_stable_indirect,
rustc_layout,
rustc_layout_scalar_valid_range_end,
rustc_layout_scalar_valid_range_start,
rustc_legacy_const_generics,
@@ -277,12 +277,12 @@ Here are some notable ones:
| `rustc_dump_def_parents` | Dumps the chain of `DefId` parents of certain definitions. |
| `rustc_dump_inferred_outlives` | Dumps implied bounds of an item. More precisely, the [`inferred_outlives_of`] an item. |
| `rustc_dump_item_bounds` | Dumps the [`item_bounds`] of an item. |
| `rustc_dump_layout` | [See this section](#debugging-type-layouts). |
| `rustc_dump_object_lifetime_defaults` | Dumps the [object lifetime defaults] of an item. |
| `rustc_dump_predicates` | Dumps the [`predicates_of`] an item. |
| `rustc_dump_variances` | Dumps the [variances] of an item. |
| `rustc_dump_vtable` | Dumps the vtable layout of an impl, or a type alias of a dyn type. |
| `rustc_hidden_type_of_opaques` | Dumps the [hidden type of each opaque types][opaq] in the crate. |
| `rustc_layout` | [See this section](#debugging-type-layouts). |
| `rustc_regions` | Dumps NLL closure region requirements. |
| `rustc_symbol_name` | Dumps the mangled & demangled [`symbol_name`] of an item. |
@@ -316,54 +316,55 @@ $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer
### Debugging type layouts
The internal attribute `#[rustc_layout]` can be used to dump the [`Layout`] of
the type it is attached to.
The internal attribute `#[rustc_dump_layout(...)]` can be used to dump the
[`Layout`] of the type it is attached to.
For example:
```rust
#![feature(rustc_attrs)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type T<'a> = &'a u32;
```
Will emit the following:
```text
error: layout_of(&'a u32) = Layout {
fields: Primitive,
variants: Single {
index: 0,
},
abi: Scalar(
Scalar {
value: Pointer,
valid_range: 1..=18446744073709551615,
},
),
largest_niche: Some(
Niche {
offset: Size {
raw: 0,
},
scalar: Scalar {
value: Pointer,
valid_range: 1..=18446744073709551615,
},
},
),
align: AbiAndPrefAlign {
abi: Align {
pow2: 3,
},
pref: Align {
pow2: 3,
},
},
size: Size {
raw: 8,
},
}
error: layout_of(&u32) = Layout {
size: Size(8 bytes),
align: AbiAlign {
abi: Align(8 bytes),
},
backend_repr: Scalar(
Initialized {
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
fields: Primitive,
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(8 bytes),
randomization_seed: 281492156579847,
}
--> src/lib.rs:4:1
|
4 | type T<'a> = &'a u32;
@@ -9,19 +9,20 @@ only discuss a few of them.
------------------------
The `rustc_attrs` feature allows debugging rustc type layouts by using
`#[rustc_layout(...)]` to debug layout at compile time (it even works
`#[rustc_dump_layout(...)]` to debug layout at compile time (it even works
with `cargo check`) as an alternative to `rustc -Z print-type-sizes`
that is way more verbose.
Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `align`,
`abi`. Note that it only works on sized types without generics.
Options provided by `#[rustc_dump_layout(...)]` are `abi`, `align`, `debug`,
`homogeneous_aggregate` and `size`.
Note that it only works on sized types without generics.
## Examples
```rust,compile_fail
#![feature(rustc_attrs)]
#[rustc_layout(abi, size)]
#[rustc_dump_layout(abi, size)]
pub enum X {
Y(u8, u8, u8),
Z(isize),
-1
View File
@@ -275,7 +275,6 @@ enum NicheLayoutWithFields3 {
#[repr(transparent)]
struct Wrapping128(u128);
// #[rustc_layout(debug)]
enum Wrapping128Niche {
X(Wrapping128),
Y,
@@ -2,7 +2,7 @@
use std::borrow::Cow;
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Edges<'a, E> = Cow<'a, [E]>;
//~^ ERROR the trait bound `[E]: ToOwned` is not satisfied
+2 -2
View File
@@ -4,7 +4,7 @@
#![feature(rustc_attrs)]
#[repr(u16)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum UnsignedAroundZero {
//~^ ERROR: layout_of
A = 65535,
@@ -13,7 +13,7 @@ enum UnsignedAroundZero {
}
#[repr(i16)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum SignedAroundZero {
//~^ ERROR: layout_of
A = -1,
+19 -19
View File
@@ -3,49 +3,49 @@
#![feature(never_type, rustc_attrs, type_alias_impl_trait, repr_simd)]
#![crate_type = "lib"]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[derive(Copy, Clone)]
enum E { Foo, Bar(!, i32, i32) } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
struct S { f1: i32, f2: (), f3: i32 } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
union U { f1: (i32, i32), f3: i32 } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Test = Result<i32, i32>; //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type T = impl std::fmt::Debug; //~ ERROR: layout_of
#[define_opaque(T)]
fn f() -> T {
0i32
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub union V { //~ ERROR: layout_of
a: [u16; 0],
b: u8,
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub union W { //~ ERROR: layout_of
b: u8,
a: [u16; 0],
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub union Y { //~ ERROR: layout_of
b: [u8; 0],
a: [u16; 0],
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(packed(1))]
union P1 { x: u32 } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(packed(1))]
union P2 { x: (u32, u32) } //~ ERROR: layout_of
@@ -53,38 +53,38 @@ union P2 { x: (u32, u32) } //~ ERROR: layout_of
#[derive(Copy, Clone)]
struct F32x4([f32; 4]);
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(packed(1))]
union P3 { x: F32x4 } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(packed(1))]
union P4 { x: E } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(packed(1))]
union P5 { zst: [u16; 0], byte: u8 } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type X = std::mem::MaybeUninit<u8>; //~ ERROR: layout_of
#[rustc_layout(debug)] //~ ERROR: cannot be used on constants
#[rustc_dump_layout(debug)] //~ ERROR: cannot be used on constants
const C: () = ();
impl S {
#[rustc_layout(debug)] //~ ERROR: cannot be used on associated consts
#[rustc_dump_layout(debug)] //~ ERROR: cannot be used on associated consts
const C: () = ();
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Impossible = (str, str); //~ ERROR: cannot be known at compilation time
// Test that computing the layout of an empty union doesn't ICE.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
union EmptyUnion {} //~ ERROR: has an unknown layout
//~^ ERROR: unions cannot have zero fields
// Test the error message of `LayoutError::TooGeneric`
// (this error is never emitted to users).
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type TooGeneric<T> = T; //~ ERROR: does not have a fixed layout
+8 -8
View File
@@ -4,21 +4,21 @@ error: unions cannot have zero fields
LL | union EmptyUnion {}
| ^^^^^^^^^^^^^^^^^^^
error: `#[rustc_layout]` attribute cannot be used on constants
error: `#[rustc_dump_layout]` attribute cannot be used on constants
--> $DIR/debug.rs:71:1
|
LL | #[rustc_layout(debug)]
| ^^^^^^^^^^^^^^^^^^^^^^
LL | #[rustc_dump_layout(debug)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[rustc_layout]` can be applied to data types and type aliases
= help: `#[rustc_dump_layout]` can be applied to data types and type aliases
error: `#[rustc_layout]` attribute cannot be used on associated consts
error: `#[rustc_dump_layout]` attribute cannot be used on associated consts
--> $DIR/debug.rs:75:5
|
LL | #[rustc_layout(debug)]
| ^^^^^^^^^^^^^^^^^^^^^^
LL | #[rustc_dump_layout(debug)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[rustc_layout]` can be applied to data types and type aliases
= help: `#[rustc_dump_layout]` can be applied to data types and type aliases
error: layout_of(E) = Layout {
size: Size(12 bytes),
+2 -2
View File
@@ -8,7 +8,7 @@
#![feature(never_type)]
#![crate_type = "lib"]
#[rustc_layout(abi)]
#[rustc_dump_layout(abi)]
enum ScalarPairPointerWithInt { //~ERROR: abi: ScalarPair
A(usize),
B(Box<()>),
@@ -17,7 +17,7 @@ enum ScalarPairPointerWithInt { //~ERROR: abi: ScalarPair
// Negative test--ensure that pointers are not commoned with integers
// of a different size. (Assumes that no target has 8 bit pointers, which
// feels pretty safe.)
#[rustc_layout(abi)]
#[rustc_dump_layout(abi)]
enum NotScalarPairPointerWithSmallerInt { //~ERROR: abi: Memory
A(u8),
B(Box<()>),
+4 -4
View File
@@ -5,19 +5,19 @@
#![feature(never_type)]
#![crate_type = "lib"]
#[rustc_layout(align)]
#[rustc_dump_layout(align)]
enum UninhabitedVariantAlign { //~ERROR: abi: Align(2 bytes)
A([u8; 32]),
B([u16; 0], !), // make sure alignment in uninhabited fields is respected
}
#[rustc_layout(size)]
#[rustc_dump_layout(size)]
enum UninhabitedVariantSpace { //~ERROR: size: Size(16 bytes)
A,
B([u8; 15], !), // make sure there is space being reserved for this field.
}
#[rustc_layout(abi)]
#[rustc_dump_layout(abi)]
enum ScalarPairDifferingSign { //~ERROR: abi: ScalarPair
A(u8),
B(i8),
@@ -26,7 +26,7 @@ enum ScalarPairDifferingSign { //~ERROR: abi: ScalarPair
enum Never {}
// See https://github.com/rust-lang/rust/issues/146984
#[rustc_layout(size)]
#[rustc_dump_layout(size)]
#[repr(u32)]
enum DefinedLayoutAllUninhabited { //~ERROR: size: Size(4 bytes)
A(Never),
@@ -21,7 +21,7 @@ trait A {
const B: usize;
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
struct S([u8; <u8 as A>::B]) //~ ERROR: the type `[u8; <u8 as A>::B]` has an unknown layout
where
u8: A;
+5 -5
View File
@@ -14,24 +14,24 @@
extern crate minicore;
use minicore::*;
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum A { Apple } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum B { Banana = 255, } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum C { Chaenomeles = 256, } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of
const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator!
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of
@@ -21,23 +21,23 @@ union WrapperUnion<T: Copy> {
something: T,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test0 = Tuple;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test1 = Wrapper1<Tuple>;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test2 = Wrapper2<Tuple>;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test3 = Wrapper3<Tuple>;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test4 = WrapperUnion<Tuple>;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
@@ -18,7 +18,7 @@ pub struct Middle {
pub b: f32,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type TestMiddle = Middle;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
@@ -29,7 +29,7 @@ pub struct Final {
pub foo: [Foo; 0],
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type TestFinal = Final;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
@@ -49,23 +49,23 @@ pub struct WithEmptyRustEnum {
pub _unit: EmptyRustEnum,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test1 = BaseCase;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test2 = WithPhantomData;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test3 = WithEmptyRustStruct;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test4 = WithTransitivelyEmptyRustStruct;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
pub type Test5 = WithEmptyRustEnum;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) }))
@@ -13,7 +13,7 @@ enum HasNiche {
// This should result in ScalarPair(Initialized, Union),
// since the u8 payload will be uninit for `None`.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub enum MissingPayloadField { //~ ERROR: layout_of
Some(u8),
None
@@ -22,7 +22,7 @@ pub enum MissingPayloadField { //~ ERROR: layout_of
// This should result in ScalarPair(Initialized, Initialized),
// since the u8 field is present in all variants,
// and hence will always be initialized.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub enum CommonPayloadField { //~ ERROR: layout_of
A(u8),
B(u8),
@@ -30,7 +30,7 @@ pub enum CommonPayloadField { //~ ERROR: layout_of
// This should result in ScalarPair(Initialized, Union),
// since, though a u8-sized field is present in all variants, it might be uninit.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub enum CommonPayloadFieldIsMaybeUninit { //~ ERROR: layout_of
A(u8),
B(MaybeUninit<u8>),
@@ -38,7 +38,7 @@ pub enum CommonPayloadFieldIsMaybeUninit { //~ ERROR: layout_of
// This should result in ScalarPair(Initialized, Union),
// since only the niche field (used for the tag) is guaranteed to be initialized.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub enum NicheFirst { //~ ERROR: layout_of
A(HasNiche, u8),
B,
@@ -47,7 +47,7 @@ pub enum NicheFirst { //~ ERROR: layout_of
// This should result in ScalarPair(Union, Initialized),
// since only the niche field (used for the tag) is guaranteed to be initialized.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
pub enum NicheSecond { //~ ERROR: layout_of
A(u8, HasNiche),
B,
@@ -4,7 +4,7 @@
#![feature(rustc_attrs)]
// This cannot use `Scalar` abi since there is padding.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(align(8))]
pub enum Aligned1 { //~ ERROR: layout_of
Zero = 0,
@@ -12,7 +12,7 @@ pub enum Aligned1 { //~ ERROR: layout_of
}
// This should use `Scalar` abi.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(align(1))]
pub enum Aligned2 { //~ ERROR: layout_of
Zero = 0,
+2 -2
View File
@@ -5,8 +5,8 @@
#![feature(never_type)]
#![crate_type = "lib"]
#[rustc_layout(abi)]
#[rustc_dump_layout(abi)]
struct AlignedZstPreventsScalar(i16, [i32; 0]); //~ERROR: abi: Memory
#[rustc_layout(abi)]
#[rustc_dump_layout(abi)]
struct AlignedZstButStillScalar(i32, [i16; 0]); //~ERROR: abi: Scalar
+5 -5
View File
@@ -14,24 +14,24 @@
extern crate minicore;
use minicore::*;
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum A { Apple } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum B { Banana = 255, } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum C { Chaenomeles = 256, } //~ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of
const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator!
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
#[repr(C)]
enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of
+1 -1
View File
@@ -36,7 +36,7 @@ enum Enum
}
// This forces layout computation via the `variant_size_differences` lint.
// FIXME: This could be made more robust, possibly with a variant of `rustc_layout`
// FIXME: This could be made more robust, possibly with a variant of `rustc_dump_layout`
// that doesn't error.
enum Check
where
@@ -14,7 +14,7 @@ impl<C: ?Sized> A for u8 { //~ ERROR: the type parameter `C` is not constrained
const B: usize = 42;
}
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
struct S([u8; <u8 as A>::B]);
//~^ ERROR: the type has an unknown layout
//~| ERROR: type annotations needed
@@ -10,7 +10,7 @@
// `SliceInfo<[SliceInfoElem; 0], Din, Dout>`, where that returns
// `Result<Self, ShapeError>` ~= `Result<AlignedZST, TypeWithNiche>`.
// This is a close enough approximation:
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type AlignedResult = Result<[u32; 0], bool>; //~ ERROR: layout_of
// The bug gave that size 1 with align 4, but the size should also be 4.
// It was also using the bool niche for the enum tag, which is fine, but
@@ -18,7 +18,7 @@
// Here's another case with multiple ZST alignments, where we should
// get the maximal alignment and matching size.
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum MultipleAlignments { //~ ERROR: layout_of
Align2([u16; 0]),
Align4([u32; 0]),
@@ -34,13 +34,13 @@ enum MultipleAlignments { //~ ERROR: layout_of
#[repr(packed)]
struct Packed<T>(T);
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type NicheLosesToTagged = Result<[u32; 0], Packed<std::num::NonZero<u16>>>; //~ ERROR: layout_of
// Should get tag_encoding: Direct, size == align == 4.
#[repr(u16)]
enum U16IsZero { _Zero = 0 }
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type NicheWinsOverTagged = Result<[u32; 0], Packed<U16IsZero>>; //~ ERROR: layout_of
// Should get tag_encoding: Niche, size == align == 4.
+4 -4
View File
@@ -55,7 +55,7 @@ struct Baz1 {
u: U1,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
type TestBaz1 = Baz1;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
@@ -66,7 +66,7 @@ struct Baz2 {
u: U2,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
type TestBaz2 = Baz2;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
@@ -77,7 +77,7 @@ struct Baz3 {
u: U3,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
type TestBaz3 = Baz3;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
@@ -88,7 +88,7 @@ struct Baz4 {
u: U4,
}
#[rustc_layout(homogeneous_aggregate)]
#[rustc_dump_layout(homogeneous_aggregate)]
type TestBaz4 = Baz4;
//~^ ERROR homogeneous_aggregate: Ok(Homogeneous
+3 -3
View File
@@ -40,14 +40,14 @@ enum Void {}
// Compiler must not remove dead variants of `#[repr(C, int)]` ADTs.
#[repr(C)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum Univariant { //~ ERROR layout_of
Variant(Void),
}
// ADTs with variants that have fields must have space allocated for those fields.
#[repr(C)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum TwoVariants { //~ ERROR layout_of
Variant1(Void),
Variant2(u8),
@@ -59,7 +59,7 @@ enum TwoVariants { //~ ERROR layout_of
// This one is 2 x u64: we reserve space for fields in a dead branch.
#[repr(C)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum DeadBranchHasOtherField { //~ ERROR layout_of
Variant1(Void, Align8U64),
Variant2(u8),
+3 -3
View File
@@ -11,14 +11,14 @@ enum Void {}
// Compiler must not remove dead variants of `#[repr(C, int)]` ADTs.
#[repr(C, u8)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum UnivariantU8 { //~ ERROR layout_of
Variant(Void),
}
// ADTs with variants that have fields must have space allocated for those fields.
#[repr(C, u8)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum TwoVariantsU8 { //~ ERROR layout_of
Variant1(Void),
Variant2(u8),
@@ -30,7 +30,7 @@ enum TwoVariantsU8 { //~ ERROR layout_of
// This one is 2 x u64: we reserve space for fields in a dead branch.
#[repr(C, u8)]
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
enum DeadBranchHasOtherFieldU8 { //~ ERROR layout_of
Variant1(Void, Align8U64),
Variant2(u8),
+3 -3
View File
@@ -7,13 +7,13 @@
use std::pat::pattern_type;
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type NonNull<T> = pattern_type!(*const T is !null); //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Test = Option<NonNull<()>>; //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Wide = pattern_type!(*const [u8] is !null); //~ ERROR layout_of
const _: () = assert!(size_of::<NonNull<()>>() == size_of::<Option<NonNull<()>>>());
+2 -2
View File
@@ -13,11 +13,11 @@
use std::pat::pattern_type;
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type NonNullI8 = pattern_type!(i8 is ..0 | 1..);
//~^ ERROR: layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type NonNegOneI8 = pattern_type!(i8 is ..-1 | 0..);
//~^ ERROR: layout_of
+11 -11
View File
@@ -7,34 +7,34 @@
use std::pat::pattern_type;
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type X = std::num::NonZeroU32; //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Y = pattern_type!(u32 is 1..); //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type Z = Option<pattern_type!(u32 is 1..)>; //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type A = Option<std::num::NonZeroU32>; //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
struct NonZeroU32New(pattern_type!(u32 is 1..)); //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type EMPTY = pattern_type!(u32 is 1..1); //~ ERROR unknown layout
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type WRAP = pattern_type!(u32 is 1..0); //~ ERROR unknown layout
//~^ ERROR: evaluation panicked: exclusive range end at minimum value of type
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type WRAP2 = pattern_type!(u32 is 5..2); //~ ERROR unknown layout
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type SIGN = pattern_type!(i8 is -10..=10); //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type MIN = pattern_type!(i8 is -128..=0); //~ ERROR layout_of
#[rustc_layout(debug)]
#[rustc_dump_layout(debug)]
type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR unknown layout
fn main() {