Description
References and pointers to unsized types are "fat" which means that they hold not just the address of the pointee but also an additional field that contains either the size of the pointee's unsized field (for slice-like pointees) or the addr of the vtable (for trait object pointers).
The compiler generates debuginfo for this additional field in most cases (e.g. for &[T]
and *mut [T]
) -- but if the pointee is an unsized struct then the compiler generates regular thin pointer debuginfo which does not describe the additional field.
Example:
pub struct SomeUnsizedType {
pub a: u32,
pub b: u64,
pub c: [u8],
}
pub fn references(_slice_ref: &[u64], _struct_ref: &SomeUnsizedType) {}
The debuginfo for &[u64]
looks as expected:
// the fat reference &[u64] is described as a struct with two fields,
// `data_ptr` and `length`.
< 1><0x0000012c> DW_TAG_structure_type
DW_AT_name &[u64]
DW_AT_byte_size 0x00000010
DW_AT_alignment 0x00000008
< 2><0x00000133> DW_TAG_member
DW_AT_name data_ptr
DW_AT_type <0x000000e3>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 0
< 2><0x0000013e> DW_TAG_member
DW_AT_name length
DW_AT_type <0x000000f7>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 8
But &SomeUnsizedType
does not have the additional field:
< 1><0x0000014a> DW_TAG_pointer_type
DW_AT_type <0x0000009b>
DW_AT_name &SomeUnsizedType
DW_AT_address_class 0x00000000
< 2><0x0000009b> DW_TAG_structure_type
DW_AT_name SomeUnsizedType
DW_AT_byte_size 0x00000010
DW_AT_alignment 0x00000008
< 3><0x000000a2> DW_TAG_member
DW_AT_name a
DW_AT_type <0x0000010b>
DW_AT_alignment 0x00000004
DW_AT_data_member_location 8
< 3><0x000000ad> DW_TAG_member
DW_AT_name b
DW_AT_type <0x000000f0>
DW_AT_alignment 0x00000008
DW_AT_data_member_location 0
< 3><0x000000b8> DW_TAG_member
DW_AT_name c
DW_AT_type <0x00000112>
DW_AT_alignment 0x00000001
DW_AT_data_member_location 12
// This is the type of the unsized field `c`
< 1><0x00000112> DW_TAG_array_type
DW_AT_type <0x0000011e>
< 2><0x00000117> DW_TAG_subrange_type
DW_AT_type <0x00000125>
DW_AT_lower_bound 0x00000000
< 1><0x0000011e> DW_TAG_base_type
DW_AT_name u8
DW_AT_encoding DW_ATE_unsigned
DW_AT_byte_size 0x00000001
< 1><0x00000125> DW_TAG_base_type
DW_AT_name __ARRAY_SIZE_TYPE__
DW_AT_byte_size 0x00000008
DW_AT_encoding DW_ATE_unsigned
The last field is described as a zero-sized array [u8; 0]
. As a consequence, a debugger has no way of finding out how many elements the field actually holds. This affects a number of common types from the standard library, like Rc
, Arc
, CStr
which all use unsized structs internally.
Meta
rustc --version --verbose
:
rustc 1.59.0-nightly (8f3238f89 2022-01-02)
binary: rustc
commit-hash: 8f3238f898163f09726c3d2b2cc9bafb09da26f3
commit-date: 2022-01-02
host: x86_64-unknown-linux-gnu
release: 1.59.0-nightly
LLVM version: 13.0.0