1
Fork 0

Rollup merge of #69901 - RalfJung:rustc_layout, r=eddyb

add #[rustc_layout(debug)]

@eddyb recently told me about the `#[rustc_layout]` attribute, and I think it would be very useful if it could be used to print all the layout information Rust has about a type. When working with layouts (e.g. in Miri), it is often not clear how certain surface language features get represented internally. I have some awful hacks locally to be able to dump this debug information; with this attribute I could get it on the playground which is so much better. :)
This commit is contained in:
Dylan DPC 2020-03-21 13:06:35 +01:00 committed by GitHub
commit fd3f9176c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 356 additions and 8 deletions

View file

@ -17,32 +17,38 @@ use rustc_span::symbol::sym;
pub fn test_layout(tcx: TyCtxt<'_>) {
if tcx.features().rustc_attrs {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx });
tcx.hir().krate().visit_all_item_likes(&mut LayoutTest { tcx });
}
}
struct VarianceTest<'tcx> {
struct LayoutTest<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
if let ItemKind::TyAlias(..) = item.kind {
match item.kind {
ItemKind::TyAlias(..)
| ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::Union(..) => {
for attr in self.tcx.get_attrs(item_def_id).iter() {
if attr.check_name(sym::rustc_layout) {
self.dump_layout_of(item_def_id, item, attr);
}
}
}
_ => {}
}
}
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
}
impl VarianceTest<'tcx> {
impl LayoutTest<'tcx> {
fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item<'tcx>, attr: &Attribute) {
let tcx = self.tcx;
let param_env = self.tcx.param_env(item_def_id);
@ -81,6 +87,13 @@ impl VarianceTest<'tcx> {
);
}
sym::debug => {
self.tcx.sess.span_err(
item.span,
&format!("layout debugging: {:#?}", *ty_layout),
);
}
name => {
self.tcx.sess.span_err(
meta_item.span(),

View file

@ -253,6 +253,7 @@ symbols! {
debug_trait,
declare_lint_pass,
decl_macro,
debug,
Debug,
Decodable,
Default,

View file

@ -0,0 +1,15 @@
// normalize-stderr-test "pref: Align \{\n *pow2: [1-3],\n *\}" -> "pref: $$PREF_ALIGN"
#![feature(never_type, rustc_attrs)]
#![crate_type = "lib"]
#[rustc_layout(debug)]
enum E { Foo, Bar(!, i32, i32) } //~ ERROR: layout debugging
#[rustc_layout(debug)]
struct S { f1: i32, f2: (), f3: i32 } //~ ERROR: layout debugging
#[rustc_layout(debug)]
union U { f1: (i32, i32), f3: i32 } //~ ERROR: layout debugging
#[rustc_layout(debug)]
type Test = Result<i32, i32>; //~ ERROR: layout debugging

View file

@ -0,0 +1,319 @@
error: layout debugging: LayoutDetails {
fields: Arbitrary {
offsets: [
Size {
raw: 0,
},
],
memory_index: [
0,
],
},
variants: Multiple {
discr: Scalar {
value: Int(
I32,
false,
),
valid_range: 0..=0,
},
discr_kind: Tag,
discr_index: 0,
variants: [
LayoutDetails {
fields: Arbitrary {
offsets: [],
memory_index: [],
},
variants: Single {
index: 0,
},
abi: Aggregate {
sized: true,
},
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 0,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 4,
},
},
LayoutDetails {
fields: Arbitrary {
offsets: [
Size {
raw: 4,
},
Size {
raw: 4,
},
Size {
raw: 8,
},
],
memory_index: [
0,
1,
2,
],
},
variants: Single {
index: 1,
},
abi: Uninhabited,
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 12,
},
},
],
},
abi: Aggregate {
sized: true,
},
largest_niche: Some(
Niche {
offset: Size {
raw: 0,
},
scalar: Scalar {
value: Int(
I32,
false,
),
valid_range: 0..=0,
},
},
),
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 12,
},
}
--> $DIR/debug.rs:6:1
|
LL | enum E { Foo, Bar(!, i32, i32) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: layout debugging: LayoutDetails {
fields: Arbitrary {
offsets: [
Size {
raw: 0,
},
Size {
raw: 0,
},
Size {
raw: 4,
},
],
memory_index: [
1,
0,
2,
],
},
variants: Single {
index: 0,
},
abi: ScalarPair(
Scalar {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
Scalar {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
),
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 8,
},
}
--> $DIR/debug.rs:9:1
|
LL | struct S { f1: i32, f2: (), f3: i32 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: layout debugging: LayoutDetails {
fields: Union(
2,
),
variants: Single {
index: 0,
},
abi: Aggregate {
sized: true,
},
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 8,
},
}
--> $DIR/debug.rs:12:1
|
LL | union U { f1: (i32, i32), f3: i32 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: layout debugging: LayoutDetails {
fields: Arbitrary {
offsets: [
Size {
raw: 0,
},
],
memory_index: [
0,
],
},
variants: Multiple {
discr: Scalar {
value: Int(
I32,
false,
),
valid_range: 0..=1,
},
discr_kind: Tag,
discr_index: 0,
variants: [
LayoutDetails {
fields: Arbitrary {
offsets: [
Size {
raw: 4,
},
],
memory_index: [
0,
],
},
variants: Single {
index: 0,
},
abi: Aggregate {
sized: true,
},
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 8,
},
},
LayoutDetails {
fields: Arbitrary {
offsets: [
Size {
raw: 4,
},
],
memory_index: [
0,
],
},
variants: Single {
index: 1,
},
abi: Aggregate {
sized: true,
},
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 8,
},
},
],
},
abi: ScalarPair(
Scalar {
value: Int(
I32,
false,
),
valid_range: 0..=1,
},
Scalar {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
),
largest_niche: Some(
Niche {
offset: Size {
raw: 0,
},
scalar: Scalar {
value: Int(
I32,
false,
),
valid_range: 0..=1,
},
},
),
align: AbiAndPrefAlign {
abi: Align {
pow2: 2,
},
pref: $PREF_ALIGN,
},
size: Size {
raw: 8,
},
}
--> $DIR/debug.rs:15:1
|
LL | type Test = Result<i32, i32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors