Repository: rust
Issue: debuginfo: How to (ideally) represent reference and pointer types in DWARF
Labels: A-debuginfo,T-compiler

Currently, we represent thin references and pointers with `DW_TAG_pointer_type` DIEs and fat pointers (slices and trait objects) as `DW_TAG_struct` DIEs with fields representing payload and metadata pointers. This is not ideal and with debuggers knowing about Rust, we can do better. The question is, what exactly do we want the representation for these kinds of types to look like.

Some things seem pretty straightforward to me:
- Rust references should be `DW_TAG_reference_type` DIEs.
- Rust raw pointers should be `DW_TAG_pointer_type` DIEs.

But beyond that, there are some decisions to be made:

### (1) How do we represent mutability?
The C++ version of DWARF represents a const pointer like `const char *` with three separate type entries:
```
0:
DW_TAG_base_type
    DW_AT_name "char"
    ... 

1:
DW_TAG_const_type
    DW_AT_type: ref to <0>

2:
DW_TAG_pointer_type
    DW_AT_type: ref to <1>
```

I think this is a bit verbose and I'm not sure it is entirely appropriate for Rust. Do we really have `const` and `mut` *types*? That is, does Rust have the concept of a `mut i32` at the type level, for example? I mean there are mutable and immutable *slots*/memory locations and we have "mutable" and "shared" references, but those two things seem kind of different to me.

As an alternative to using `DW_TAG_const_type` for representing mutability, we could re-use the `DW_AT_mutable` attribute that is already defined in DWARF. In C++ DWARF it is used for `mutable` fields. We could use it for reference type and local variable DIEs:
```
0: // char
DW_TAG_base_type
    DW_AT_name "char"
    ... 

1: // &mut char
DW_TAG_reference_type
    DW_AT_type: ref to <0>
    DW_AT_mutable: true

2: // &char
DW_TAG_reference_type
    DW_AT_type: ref to <0>
    DW_AT_mutable: false       // or just leave it off

3: 
DW_TAG_variable
    DW_AT_name: "foo"
    DW_AT_type: ref to <0>
    DW_AT_mutable: true
    ...
```

### (2) How to represent fat pointers?
The pointer types in C/C++ DWARF don't have `DW_TAG_member` sub-DIEs, since they are always just values. Fat pointers in Rust are different: they have one field that is a pointer to the data, and another field that holds additional information, either the size of a slice or the pointer to a vtable. These need to be described somehow.
I see a few options:

1. A fat-pointer type is described by a `DW_TAG_pointer_type` or `DW_TAG_reference_type` DIE with two fields that are described by `DW_TAG_member` sub-DIEs, both having the `DW_AT_artificial` attribute. @tromey once suggested for slices that the field entries have no name and the debugger determines which is which by the type (the size is always an integer type, the data is always a pointer type). This could also be extended for trait objects, since the data pointer will always be a pointer to a trait and the vtable-pointer will always be something else.
2. Treat trait objects and slices differently. Have a new `DW_TAG_slice_type` DIE that follows the encoding above and borrow some other attributes for trait objects: a `DW_AT_vtable_elem_location` attribute holds the offset of the vtable field within the fat-pointer value, and a `DW_AT_object_pointer` attribute does the same for the data pointer. This is distinctly not how these attributes are used in a C++ context but it would be a nice fit, I think.
3. Mix of the above with `DW_AT_object_pointer` indicating data pointer field

Another questions is: Should fat-pointers (and thin pointers too, maybe) have a `DW_AT_byte_size` attribute that specifies their size explicitly?

cc @tromey, @Manishearth 
See also https://github.com/rust-lang/rust/issues/33073