| Age | Commit message (Collapse) | Author | Lines |
|
|
|
|
|
Name the captured upvars for closures/generators in debuginfo
Previously, debuggers print closures as something like
```
y::main::closure-0 (0x7fffffffdd34)
```
The pointer actually references to an upvar. It is not very obvious, especially for beginners.
It's because upvars don't have names before, as they are packed into a tuple. This PR names the upvars, so we can expect to see something like
```
y::main::closure-0 {_captured_ref__b: 0x[...]}
```
r? `@tmandry`
Discussed at https://github.com/rust-lang/rust/pull/84752#issuecomment-831639489 .
|
|
|
|
michaelwoerister:debuginfo-names-dyn-trait-projection-bounds, r=wesleywiser
[debuginfo] Emit associated type bindings in trait object type names.
This PR updates debuginfo type name generation for trait objects to include associated type bindings and auto trait bounds -- so that, for example, the debuginfo type name of `&dyn Iterator<Item=Foo>` and `&dyn Iterator<Item=Bar>` don't both map to just `&dyn Iterator` anymore.
The following table shows examples of debuginfo type names before and after the PR:
| type | before | after |
|------|---------|-------|
| `&dyn Iterator<Item=u32>>` | `&dyn Iterator` | `&dyn Iterator<Item=u32>` |
| `&(dyn Iterator<Item=u32>> + Sync)` | `&dyn Iterator` | `&(dyn Iterator<Item=u32> + Sync)` |
| `&(dyn SomeTrait<bool, i8, Bar=u32>> + Send)` | `&dyn SomeTrait<bool, i8>` | `&(dyn SomeTrait<bool, i8, Bar=u32>> + Send)` |
For targets that need C++-like type names, we use `assoc$<Item,u32>` instead of `Item=u32`:
| type | before | after |
|------|---------|-------|
| `&dyn Iterator<Item=u32>>` | `ref$<dyn$<Iterator> >` | `ref$<dyn$<Iterator<assoc$<Item,u32> > > >` |
| `&(dyn Iterator<Item=u32>> + Sync)` | `ref$<dyn$<Iterator> >` | `ref$<dyn$<Iterator<assoc$<Item,u32> >,Sync> >` |
| `&(dyn SomeTrait<bool, i8, Bar=u32>> + Send)` | `ref$<dyn$<SomeTrait<bool, i8> > >` | `ref$<dyn$<SomeTrait<bool,i8,assoc$<Bar,u32> > >,Send> >` |
The PR also adds self-profiling measurements for debuginfo type name generation (re. https://github.com/rust-lang/rust/issues/86431). It looks like the compiler spends up to 0.5% of its time in that task, so the potential for optimizing it via caching seems limited.
However, the perf run also shows [the biggest regression](https://perf.rust-lang.org/detailed-query.html?commit=585e91c718b0b2c5319e1fffd0ff1e62aaf7ccc2&base_commit=b9197978a90be6f7570741eabe2da175fec75375&benchmark=tokio-webpush-simple-debug&run_name=incr-unchanged) in a test case that does not even invoke the code in question. This suggests that the length of the names we generate here can affect performance by influencing how much data the linker has to copy around.
Fixes https://github.com/rust-lang/rust/issues/86134.
|
|
type names.
|
|
Add or improve natvis definitions for common standard library types
Natvis definitions are used by Windows debuggers to provide a better experience when inspecting a value for types with natvis definitions. Many of our standard library types and intrinsic Rust types like slices and `str` already have natvis definitions.
This PR adds natvis definitions for missing types (like all of the `Atomic*` types) and improves some of the existing ones (such as showing the ref count on `Arc<T>` and `Rc<T>` and showing the borrow state of `RefCell<T>`). I've also added cdb tests to cover these definitions and updated existing tests with the new visualizations.
With this PR, the following types now visualize in a much more intuitive way:
### Type: `NonZero{I,U}{8,16,32,64,128,size}`, `Atomic{I,U}{8,16,32,64,size}`, `AtomicBool` and `Wrapping<T>`
<details><summary>Example:</summary>
```rust
let a_u32 = AtomicU32::new(32i32);
```
```
0:000> dx a_u32
a_u32 : 32 [Type: core::sync::atomic::AtomicU32]
[<Raw View>] [Type: core::sync::atomic::AtomicU32]
```
</details>
### Type: `Cell<T>` and `UnsafeCell<T>`
<details><summary>Example:</summary>
```rust
let cell = Cell::new(123u8);
let unsafecell = UnsafeCell::new((42u16, 30u16));
```
```
0:000> dx cell
cell : 123 [Type: core::cell::Cell<u8>]
[<Raw View>] [Type: core::cell::Cell<u8>]
0:000> dx unsafecell
unsafecell : (42, 30) [Type: core::cell::UnsafeCell<tuple<u16, u16>>]
[<Raw View>] [Type: core::cell::UnsafeCell<tuple<u16, u16>>]
[0] : 42 [Type: unsigned short]
[1] : 30 [Type: unsigned short]
```
</details>
### Type: `RefCell<T>`
<details><summary>Example:</summary>
```rust
let refcell = RefCell::new((123u16, 456u32));
```
```
0:000> dx refcell
refcell : (123, 456) [Type: core::cell::RefCell<tuple<u16, u32>>]
[<Raw View>] [Type: core::cell::RefCell<tuple<u16, u32>>]
[Borrow state] : Unborrowed
[0] : 123 [Type: unsigned short]
[1] : 456 [Type: unsigned int]
```
</details>
### Type: `NonNull<T>` and `Unique<T>`
<details><summary>Example:</summary>
```rust
let nonnull: NonNull<_> = (&(10, 20)).into();
```
```
0:000> dx nonnull
nonnull : NonNull(0x7ff6a5d9c390: (10, 20)) [Type: core::ptr::non_null::NonNull<tuple<i32, i32>>]
[<Raw View>] [Type: core::ptr::non_null::NonNull<tuple<i32, i32>>]
[0] : 10 [Type: int]
[1] : 20 [Type: int]
```
</details>
### Type: `Range<T>`, `RangeFrom<T>`, `RangeInclusive<T>`, `RangeTo<T>` and `RangeToInclusive<T>`
<details><summary>Example:</summary>
```rust
let range = (1..12);
let rangefrom = (9..);
let rangeinclusive = (32..=80);
let rangeto = (..42);
let rangetoinclusive = (..=120);
```
```
0:000> dx range
range : (1..12) [Type: core::ops::range::Range<i32>]
[<Raw View>] [Type: core::ops::range::Range<i32>]
0:000> dx rangefrom
rangefrom : (9..) [Type: core::ops::range::RangeFrom<i32>]
[<Raw View>] [Type: core::ops::range::RangeFrom<i32>]
0:000> dx rangeinclusive
rangeinclusive : (32..=80) [Type: core::ops::range::RangeInclusive<i32>]
[<Raw View>] [Type: core::ops::range::RangeInclusive<i32>]
0:000> dx rangeto
rangeto : (..42) [Type: core::ops::range::RangeTo<i32>]
[<Raw View>] [Type: core::ops::range::RangeTo<i32>]
0:000> dx rangetoinclusive
rangetoinclusive : (..=120) [Type: core::ops::range::RangeToInclusive<i32>]
[<Raw View>] [Type: core::ops::range::RangeToInclusive<i32>]
```
</details>
### Type: `Duration`
<details><summary>Example:</summary>
```rust
let duration = Duration::new(5, 12);
```
```
0:000> dx duration
duration : 5s 12ns [Type: core::time::Duration]
[<Raw View>] [Type: core::time::Duration]
seconds : 5 [Type: unsigned __int64]
nanoseconds : 12 [Type: unsigned int]
```
</details>
### Type: `ManuallyDrop<T>`
<details><summary>Example:</summary>
```rust
let manuallydrop = ManuallyDrop::new((123, 456));
```
```
0:000> dx manuallydrop
manuallydrop : (123, 456) [Type: core::mem::manually_drop::ManuallyDrop<tuple<i32, i32>>]
[<Raw View>] [Type: core::mem::manually_drop::ManuallyDrop<tuple<i32, i32>>]
[0] : 123 [Type: int]
[1] : 456 [Type: int]
```
</details>
### Type: `Pin<T>`
<details><summary>Example:</summary>
```rust
let mut s = "this".to_string();
let pin = Pin::new(&mut s);
```
```
0:000> dx pin
pin : Pin(0x11a0ff6f0: "this") [Type: core::pin::Pin<mut alloc::string::String*>]
[<Raw View>] [Type: core::pin::Pin<mut alloc::string::String*>]
[len] : 4 [Type: unsigned __int64]
[capacity] : 4 [Type: unsigned __int64]
[chars]
```
</details>
### Type: `Rc<T>` and `Arc<T>`
<details><summary>Example:</summary>
```rust
let rc = Rc::new(42i8);
let rc_weak = Rc::downgrade(&rc);
```
```
0:000> dx rc
rc : 42 [Type: alloc::rc::Rc<i8>]
[<Raw View>] [Type: alloc::rc::Rc<i8>]
[Reference count] : 1 [Type: core::cell::Cell<usize>]
0:000> dx rc_weak
rc_weak : 42 [Type: alloc::rc::Weak<i8>]
[<Raw View>] [Type: alloc::rc::Weak<i8>]
```
</details>
r? ```@michaelwoerister```
cc ```@nanguye2496```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Closures in external crates may get compiled in because of
monomorphization. We should store names of captured variables
in `optimized_mir`, so that they are written into the metadata
file and we can use them to generate debuginfo.
- If there are breakpoints inside closures, the names of captured
variables stored in `optimized_mir` can be used to print them.
Now the name is more precise when disjoint fields are captured.
|
|
Previously, debuggers print closures as something like
```
y::main::closure-0 (0x7fffffffdd34)
```
The pointer actually references to an upvar. It is not
very obvious, especially for beginners.
It's because upvars don't have names before, as they
are packed into a tuple. This commit names the upvars,
so we can expect to see something like
```
y::main::closure-0 {_captured_ref__b: 0x[...]}
```
|
|
|
|
|
|
|
|
|
|
Remove the Shared type natvis since it no longer exists
|
|
|
|
|
|
|
|
Support pretty printing slices using GDB
Support pretty printing `&[T]`, `&mut [T]` and `&mut str` types using GDB.
Support pretty printing `&mut [T]` and `&mut str` types using LLDB.
Fixes #85219.
|
|
|
|
|
|
|
|
|
|
|
|
Previously, only the fields would be displayed with no indication of the
variant name. If you already knew the enum was univariant, this was ok
but if the enum was univariant because of layout, for example, a
`Result<T, !>` then it could be very confusing which variant was the
active one.
|
|
Previously, directly tagged enums had a `variant$` field which would
show the name of the active variant. We now show the variant using a
`[variant]` synthetic item just like we do for niche-layout enums.
|
|
|
|
Also an fix issue with tuple type names where we can't cast to them in
natvis (required by the visualizer for `HashMap`) because of
peculiarities with the natvis expression evaluator.
|
|
debugger
There are several cases where names of types and functions in the debug info are either ambiguous, or not helpful, such as including ambiguous placeholders (e.g., `{{impl}}`, `{{closure}}` or `dyn _'`) or dropping qualifications (e.g., for dynamic types).
Instead, each debug symbol name should be unique and useful:
* Include disambiguators for anonymous `DefPathDataName` (closures and generators), and unify their formatting when used as a path-qualifier vs item being qualified.
* Qualify the principal trait for dynamic types.
* If there is no principal trait for a dynamic type, emit all other traits instead.
* Respect the `qualified` argument when emitting ref and pointer types.
* For implementations, emit the disambiguator.
* Print const generics when emitting generic parameters or arguments.
Additionally, when targeting MSVC, its debugger treats many command arguments as C++ expressions, even when the argument is defined to be a symbol name. As such names in the debug info need to be more C++-like to be parsed correctly:
* Avoid characters with special meaning (`#`, `[`, `"`, `+`).
* Never start a name with `<` or `{` as this is treated as an operator.
* `>>` is always treated as a right-shift, even when parsing generic arguments (so add a space to avoid this).
* Emit function declarations using C/C++ style syntax (e.g., leading return type).
* Emit arrays as a synthetic `array$<type, size>` type.
* Include a `$` in all synthetic types as this is a legal character for C++, but not Rust (thus we avoid collisions with user types).
|
|
|
|
|
|
This makes the type name inline with the proposed standard in #85269.
|
|
|
|
|
|
Add --run flag to compiletest
This controls whether run-* tests actually get run.
r? ```@Mark-Simulacrum```
|
|
- Literally, variants are not artificial. We have `yield` statements,
upvars and inner variables in the source code.
- Functionally, we don't want debuggers to suppress the variants. It
contains the state of the generator, which is useful when debugging.
So they shouldn't be marked artificial.
- Debuggers may use artificial flags to find the active variant. In
this case, marking variants artificial will make debuggers not work
properly.
Fixes #79009.
|
|
All fields except the discriminant (including `outer_fields`)
should be put into structures inside the variant part, which gives
an equivalent layout but offers us much better integration with
debuggers.
|
|
I was wary of doing any automatic disabling here, since should-fail
is how we test compiletest itself.
|
|
As mentioned in #79009, there are four failed debuginfo test cases
when using GDB 10. This commit fixes two of them, which fail because
GDB 10 won't print pointers as string anymore. We can use `printf`
as a workaround. It should work regardless of the version of GDB.
Refer this [comment] for more details.
[comment]: https://github.com/rust-lang/rust/issues/79009#issuecomment-826952708
|
|
Stablize `non-ascii-idents`
This is the stablization PR for RFC 2457. Currently this is waiting on fcp in [tracking issue](https://github.com/rust-lang/rust/issues/55467).
r? `@Manishearth`
|
|
The issue was that the resulting debuginfo was too complex for LLVM to
translate into CodeView records correctly. As a result, it simply
ignored the debuginfo which meant Windows debuggers could not display
any closed over variables when stepping inside a closure.
This fixes that by spilling additional variables to the stack so that
the resulting debuginfo is simple (just `*my_variable.dbg.spill`) and
LLVM can generate the correct CV records.
|
|
|
|
This is step 2 towards fixing #77548.
In the codegen and codegen-units test suites, the `//` comment markers
were kept in order not to affect any source locations. This is because
these tests cannot be automatically `--bless`ed.
|
|
|
|
NatVis files describe how to display types in some Windows debuggers,
such as Visual Studio, WinDbg, and VS Code.
This commit makes several improvements:
* Adds visualizers for Rc<T>, Weak<T>, and Arc<T>.
* Changes [size] to [len], for consistency with the Rust API.
Visualizers often use [size] to mirror the size() method on C++ STL
collections.
* Several visualizers used the PVOID and ULONG typedefs. These are part
of the Windows API; they are not guaranteed to always be defined in a
pure Rust DLL/EXE. I converted PVOID to `void*` and `ULONG` to
`unsigned long`.
* Cosmetic change: Removed {} braces around the visualized display
for `Option` types. They now display simply as `Some(value)` or
`None`, which reflects what is written in source code.
* The visualizer for `alloc::string::String` makes assumptions about
the layout of `String` (it casts `String*` to another type), rather
than using symbolic expressions. This commit changes the visualizer
so that it simply uses symbolic expressions to access the string
data and string length.
|