Skip to content

Commit e4220fb

Browse files
Respond to latest round of feedback. Specify which kinds of entities this attribute is applicable to and what happens if used elsewhere.
1 parent cf1cba0 commit e4220fb

File tree

1 file changed

+51
-76
lines changed

1 file changed

+51
-76
lines changed

text/0000-debugger-visualizer.md

Lines changed: 51 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ With Natvis applied, WinDbg results in the following:
6565
```
6666

6767
Currently, Rust provides visualizations for a handful of types defined in its
68-
standard library via `.natvis` files or pretty printers via python scripts.
68+
standard library via Natvis files or pretty printers via python scripts.
6969
However, this support is inflexible; updating it requires modifying the Rust
7070
toolchain itself, and either using a local build of the toolchain or waiting
7171
for a new upstream build of the toolchain. It is not feasible for developers of
@@ -197,23 +197,20 @@ The Natvis files provide patterns, which match type names, and for matching
197197
types, a description of how to display those types. This allows for some
198198
limited support for generic types.
199199

200-
Rust developers can add one or more `.natvis` files to their crate. Through
201-
the use of a new Rust attribute, `#[debugger_visualizer]`, the compiler will
202-
encode the contents of the `.natvis` file in the crate metadata if the target
200+
Rust developers can add one or more Natvis files to their crate. Through
201+
the use of a new Rust attribute, `#![debugger_visualizer]`, the compiler will
202+
encode the contents of the Natvis file in the crate metadata if the target
203203
is an `rlib`. If the target is a `dll` or `exe`, the `/NATVIS` MSVC linker flag is
204-
set for each `.natvis` file which will embed the Natvis visualizations into the PDB.
204+
set for each Natvis file which will embed the Natvis visualizations into the PDB.
205205

206-
To provide Natvis files, developers create a file with the `.natvis` file
207-
extension.
206+
To provide Natvis files, developers create a file using the Natvis XML syntax
207+
and reference it via the new `#![debugger_visualizer]` attribute that this RFC proposes.
208208

209-
See the below example for how rustc would embed these Natvis files in the
210-
debuginfo for a binary.
211-
212-
As an example, consider a crate `foo` with this directory structure:
209+
As an example for how to use this attribute, consider a crate `foo` with this directory structure:
213210

214211
```text
215212
/Cargo.toml
216-
/Foo.natvis (Note: the .natvis file does not have to match the name of the crate.)
213+
/Foo.natvis (Note: the Natvis file does not have to match the name of the crate.)
217214
+-- src
218215
+-- main.rs
219216
```
@@ -283,14 +280,12 @@ The pretty printers provide patterns, which match type names, and for matching
283280
types, descibe how to display those types. (For writing a pretty printer, see: https://sourceware.org/gdb/onlinedocs/gdb/Writing-a-Pretty_002dPrinter.html#Writing-a-Pretty_002dPrinter).
284281

285282
Rust developers can add one or more pretty printers to their crate. This is done
286-
in the Rust compiler via `.py` python scripts. Through the use of a new Rust attribute,
287-
`#[debugger_visualizer]`, the compiler will encode the contents of the `.py` file in
288-
the crate metadata if the target is an `rlib`. If the target is an executable, the
289-
`.debug_gdb_scripts` section will include a reference to the pretty printer specified
290-
by embedding the contents of the pretty printer directly into this section.
283+
in the Rust compiler via python scripts. Through the use of the new Rust attribute
284+
this RFC proposes, `#![debugger_visualizer]`, the compiler will encode the contents
285+
of the pretty printer in the `.debug_gdb_scripts` section of the `ELF` generated.
291286

292-
To provide pretty printers, developers create a file with the `.py` file
293-
extension and reference it via the `#[debugger_visualizer]` attribute as follows:
287+
To provide pretty printers, developers create a pretty printer using the syntax provided
288+
above and reference it via the `#![debugger_visualizer]` attribute as follows:
294289

295290
```rust
296291
#![debugger_visualizer(gdb_script_file = "../foo.py")]
@@ -299,38 +294,28 @@ extension and reference it via the `#[debugger_visualizer]` attribute as follows
299294
# Reference-level explanation
300295
[reference-level-explanation]: #reference-level-explanation
301296

302-
In rustc, a new built-in attribute `#[debugger_visualizer]` will be added which
303-
instructs the compiler to take the specified file path for a debugger visualizer
304-
and add it to the current binary being built. The file path specified must be
305-
relative to the location of the attribute and is resolved in a manner that is
306-
identical to how paths are resolved in the `include_str!` macro. This attribute
307-
will directly target modules which means the syntax `#![debugger_visualizer]` is
308-
also valid when placed at the module level.
297+
In rustc, a new built-in crate-level attribute `#![debugger_visualizer]` will be
298+
added which instructs the compiler to take the debugger visualizer specified by the
299+
attribute and add it to the current binary being built. The file path specified must
300+
be relative to the location of the attribute and is resolved in a manner that is
301+
identical to how paths are resolved in the `include_str!` macro.
302+
303+
Since the `#![debugger_visualizer]` is a crate-level attribute, any usage of this
304+
attribute in a different context (i.e. targeting types, modules, etc) will cause a
305+
compiler error.
309306

310-
For example, the following uses of the attribute are valid:
307+
For example, the `#![debugger_visualizer]` attribute may be used in the following:
311308

312309
Where `main.rs` contains:
313310

314311
```rust
315312
#![debugger_visualizer(natvis_file = "../main.natvis")]
316-
317-
#[debugger_visualizer(natvis_file = "../foo.natvis")]
318-
mod foo;
319-
```
320-
321-
and `bar.rs` contains:
322-
323-
```rust
324-
#![debugger_visualizer(natvis_file = "../bar.natvis")]
325313
```
326314

327-
In the first case, the attribute is applied to the crate as a top-level attribute
328-
using the inner attribute syntax and also added to the module foo using the outer
329-
attribute syntax. In the second case, the attribute is applied to the module bar
330-
via a top-level attribute as well which also is valid since it is still targeting
331-
a module.
315+
The attribute must be placed at the top of `main.rs` where other crate-level
316+
attributes are placed.
332317

333-
The `#[debugger_visualizer]` attribute will reserve multiple keys to be able to
318+
The `#![debugger_visualizer]` attribute will reserve multiple keys to be able to
334319
specify which type of visualizer is being applied. The following keys will be
335320
reserved as part of this RFC:
336321

@@ -340,7 +325,7 @@ reserved as part of this RFC:
340325
As more visualizer schemes arise, more keys may be added in the future to ensure
341326
a great debugging experience for any debugger that the Rust community sees fit.
342327

343-
For example, to specify that a `.natvis` file should be included in the binary
328+
For example, to specify that a Natvis file should be included in the binary
344329
being built, the following attribute should be added to the Rust source:
345330

346331
```rust
@@ -357,20 +342,20 @@ Depending on the Rust target, the correct debugger visualizer will be selected
357342
and embedded in the output.
358343

359344
The Rust compiler will serialize the contents of the file specified via the
360-
`#[debugger_visualizer]` attribute and store it in the crate metadata. This attribute
345+
`#![debugger_visualizer]` attribute and store it in the crate metadata. This attribute
361346
can be used multiple times to allow for multiple debugger visualizer files to be
362347
embedded for each crate. When generating the final binary, the contents of the
363-
visualizer file will be extracted from the crate metadata and written to a new file
364-
in the target directory under a new `visualizer` directory.
348+
visualizer file will be extracted from the crate metadata and written to a temp
349+
directory.
365350

366-
In the case of a Natvis file, `#[debugger_visualizer(natvis_file = "../foo.natvis")]`
351+
In the case of a Natvis file, `#![debugger_visualizer(natvis_file = "../foo.natvis")]`
367352
the compiler will set the `/NATVIS:{.natvis file}` MSVC linker flag for each of the
368353
Natvis files specified for the current crate as well as transitive dependencies if
369354
using the MSVC toolchain. This linker flag ensures that the specified Natvis files
370355
be embedded in the PDB generated for the binary being built. Any crate type that
371-
would generate a PDB would have all applicable `.natvis` files embedded.
356+
would generate a PDB would have all applicable Natvis files embedded.
372357

373-
In the case of GDB pretty printer, `#[debugger_visualizer(gdb_script_file = "../foo.py")]`
358+
In the case of GDB pretty printer, `#![debugger_visualizer(gdb_script_file = "../foo.py")]`
374359
the compiler will ensure that the set of pretty printers specified will be added to the
375360
`.debug_gdb_scripts` section of the `ELF` generated. The `.debug_gdb_scripts` section
376361
takes a list of null-terminated entries which specify scripts to load within GDB. This
@@ -381,12 +366,6 @@ This attribute will embed the contents of the debugger script so that it will no
381366
need to reference a file in the search path. This has proven to be a more reliable
382367
route than depending on file paths which can be unstable at times.
383368

384-
The `CrateRoot` type would need to be updated to account for debugger visualizer
385-
files for crates within the dependency graph. The `CrateRoot` would contain
386-
the field, `debugger_visualizers: Lazy<[DebuggerVisualizerFile]>`. The new type
387-
`pub struct DebuggerVisualizerFile` will be created to ensure the contents of a
388-
debugger visualizer file can be serialized and stored in the crate metadata.
389-
390369
There are a couple of reasons why the contents of a visualizer file passed into
391370
rustc will be serialized and encoded in the crate metadata.
392371

@@ -401,24 +380,20 @@ know how or why it flows through the dependency graph.
401380
Secondly, there's also been interest within the community of supporting
402381
binary crate packages. That is, compiling crates to rlibs, and then passing
403382
around rlibs directly and not rebuilding the entire library. Having to
404-
ensure that `.natvis` files are always passed along with rlibs as well
383+
ensure that Natvis files are always passed along with rlibs as well
405384
could become very difficult especially when other debugger visualizations
406385
also become supported such as GDB's debugger scripts and WinDbg's JavaScript
407386
debugger scripts. Packaging these sorts of things in the `rmeta` for an `rlib`
408387
is simple, reliable and seems like the "right" thing to do here.
409388

410-
Another change that would need to be made here is to add a new field to the
411-
`CrateInfo` type, `pub debugger_visualizers: FxHashSet<DebuggerVisualizerFile>`.
412-
This will allow the Rust compiler to query the list of visualizer files being
413-
added for a specific crate. The compiler will then be responsible for collecting
414-
the set of visualizer files that were previously encoded and stored in the
415-
`CrateMetadata` for a given crate dependency, will be decoded and have the
416-
contents written to a new file in the `target` directory. In the case of Natvis,
417-
the path of this new file will be what is passed to the `/NATVIS` linker flag.
418-
For example, in a debug build, the contents of the `.natvis` files that were encoded
419-
in the crate metadata will be written to new files in a temp directory where they will
420-
be included from. Each visualizer file that is written will have a new name to
421-
ensure it is unique across visualizer files for all crates.
389+
The Rust compiler will be responsible for collecting the entire set of visualizer
390+
files that were specified via the `#![debugger_visualizer]` attribute across all
391+
transitive crate dependencies and embedding them in the `.debug_gdb_scripts`
392+
section for a pretty printer or passing them to the `/NATVIS` MSVC linker flag.
393+
For example, in the case of a Natvis file, the contents of the Natvis files that
394+
were specified will be written to new files in a temp directory where they will
395+
be included from. The path of these files in the temp directory is what will be
396+
passed to the `/NATVIS` MSVC linker flag.
422397

423398
# Drawbacks
424399
[drawbacks]: #drawbacks
@@ -493,7 +468,7 @@ code directly if only the attribute syntax was supported. For types with many fi
493468
or types that need extensive amounts of Natvis to appropriately visualize them in a
494469
meaninngful way, this could distract from the contents of the code. Without being able
495470
to pull some of the more intricate Natvis descriptions into a separate standalone
496-
`.natvis` file, there may become an issue with the visibility of the source code.
471+
Natvis file, there may become an issue with the visibility of the source code.
497472
Also, if/when other debugger visualization formats are supported, it could become
498473
very obscure to read the source with large amounts of visualization scripts from
499474
multiple schemas all being directly embedded in source code.
@@ -529,7 +504,7 @@ need be.
529504
The drawbacks for this option is that it seems a sub-optimal in terms of user
530505
experience. It requires the author to operate at a lower level of abstraction by
531506
having to use a more general attribute and annotating it to tackle a specific use
532-
case. Having a more targeted attribute, i.e. `#[debugger_visualizer]` allows for the
507+
case. Having a more targeted attribute, i.e. `#![debugger_visualizer]` allows for the
533508
author to simply specify which debugger visualizer file should be included and allow
534509
the compiler to select the right one under the covers.
535510

@@ -557,7 +532,7 @@ Briefly, we cover some of the known systems for debugger views:
557532

558533
Natvis is a framework that customizes how native types appear when viewed under
559534
a debugger. The Visual Studio Natvis framework is supported out of the box on
560-
WinDbg. The debugger has the ability to load `.natvis` files via the `.nvload`
535+
WinDbg. The debugger has the ability to load Natvis files via the `.nvload`
561536
command and directly apply them to types within loaded modules. WinDbg is also
562537
able to load `.natvis` files that have been embedded in the PDB for a binary and
563538
serve up the resulting views after applying those visualizations as well. This
@@ -604,12 +579,12 @@ None.
604579
## Inline Natvis XML fragments via an attribute
605580

606581
Debugger visualizer support for Rust could be improved upon by adding support
607-
for in-source visualizer definitions via the `#[debugger_visualizer]` attribute
582+
for in-source visualizer definitions via the `#![debugger_visualizer]` attribute
608583
or a new attribute. Example:
609584

610585
```rust
611586
/// A rectangle in first quadrant
612-
#[debugger_visualizer(
587+
#![debugger_visualizer(
613588
natvis(r#"
614589
<DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
615590
<Item Name="LowerLeft">({x}, {y})</Item>
@@ -625,9 +600,9 @@ struct FancyRect {
625600
}
626601
```
627602

628-
Currently the `#[debugger_visualizer]` attribute is only allowed to target modules
629-
but can be updated to allow targeting types as well if the same attribute was to be
630-
re-used to support this.
603+
Currently the `#![debugger_visualizer]` attribute is only allowed to be used as a
604+
crate-level attribute. This can be updated to allow targeting types as well if the
605+
same attribute was to be re-used to support this.
631606

632607
## Inline Natvis XML fragments via a macro
633608

0 commit comments

Comments
 (0)