Closed
Description
Consider:
use std::sync::Arc;
trait Foo {
fn bar(&self) -> bool;
}
struct Baz;
impl Foo for Baz {
fn bar(&self) -> bool {
return false;
}
}
fn do_it(foo: Arc<dyn Foo>) {
println!("{}", foo.bar());
}
fn main() {
do_it(Arc::new(Baz));
}
The DWARF debug info for this will contain the following DIE
< 1><0x000004e8 GOFF=0x00000ad5> DW_TAG_structure_type
DW_AT_name dyn rust_scratch::Foo
DW_AT_byte_size 0x00000000
DW_AT_alignment 0x00000001
< 2><0x000004ef GOFF=0x00000adc> DW_TAG_member
DW_AT_name pointer
DW_AT_type <0x00000506 GOFF=0x00000af3>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 0
DW_AT_artificial yes(1)
< 2><0x000004fa GOFF=0x00000ae7> DW_TAG_member
DW_AT_name vtable
DW_AT_type <0x0000051a GOFF=0x00000b07>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 8
DW_AT_artificial yes(1)
The DW_TAG_members have been synthesized via trait_pointer_metadata
and are correct. But the DW_TAG_structure_type's size and alignment have been computed from the Layout
of the type and are wrong.
These incorrect values are computed by the ty::Dynamic
branch of layout_of_uncached
which does
ty::Dynamic(..) | ty::Foreign(..) => {
let mut unit = self.univariant_uninterned(
ty,
&[],
&ReprOptions::default(),
StructKind::AlwaysSized,
)?;
match unit.abi {
Abi::Aggregate { ref mut sized } => *sized = false,
_ => bug!(),
}
tcx.intern_layout(unit)
}
Unsurprisingly, passing in an empty set of members produces a zero sized layout.
For comparison, ty::Ref
is handled differently and produces the correct output
< 1><0x00000555 GOFF=0x00000b42> DW_TAG_structure_type
DW_AT_name &mut dyn rust_scratch::Foo
DW_AT_byte_size 0x00000010
DW_AT_alignment 0x00000008
< 2><0x0000055c GOFF=0x00000b49> DW_TAG_member
DW_AT_name pointer
DW_AT_type <0x00000506 GOFF=0x00000af3>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 0
DW_AT_artificial yes(1)
< 2><0x00000567 GOFF=0x00000b54> DW_TAG_member
DW_AT_name vtable
DW_AT_type <0x0000051a GOFF=0x00000b07>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 8
DW_AT_artificial yes(1)
The incorrect values above result in our debugger being unable to do anything useful with do_it
's foo
parameter.