mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rename #[rustc_layout] to #[rustc_dump_layout]
This commit is contained in:
committed by
Jonathan Brouwer
parent
7659cec4ed
commit
357f670fde
@@ -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 {
|
||||
|
||||
@@ -172,7 +172,7 @@ mod late {
|
||||
Combine<ReprParser>,
|
||||
Combine<RustcAllowConstFnUnstableParser>,
|
||||
Combine<RustcCleanParser>,
|
||||
Combine<RustcLayoutParser>,
|
||||
Combine<RustcDumpLayoutParser>,
|
||||
Combine<RustcMirParser>,
|
||||
Combine<RustcThenThisWouldNeedParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 { .. }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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})`",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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<()>),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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<()>>>());
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user