@@ -301,7 +301,154 @@ When used on a function in a trait implementation, the attribute does nothing.
301301> let _ = five();
302302> ```
303303
304+ ## The `debugger_visualizer ` attribute
305+
306+ The `debugger_visualizer ` attribute can be used to embed a debugger visualizer file into the PDB / ELF generated by `rustc `.
307+ This enables an improved debugger experience for types outside of Rust 's standard library .
308+
309+ ### Using `debugger_visualizer ` with Natvis
310+
311+ Natvis is an XML - based framework , and a `. natvis` file declares how a type 's fields should be displayed in the debugger view .
312+ A Natvis file is embedded using the `natvis - file ` meta item .
313+ Microsoft 's [Natvis documentation ] can be referenced to help developers write their own `. natvis` files .
314+
315+ <div class = " warning" >
316+ Currently , this attribute only supports embedding Natvis files on `- windows - msvc ` targets .
317+ `- windows - gnu ` targets are not currently supported .
318+ </ div >
319+
320+ Consider a crate with this directory structure :
321+
322+ ```text
323+ / Cargo . toml
324+ / Foo . natvis (Note : the Natvis file does not have to match the name of the crate . )
325+ +-- src
326+ +-- main . rs
327+ ```
328+
329+ Where ` main.rs ` contains:
330+
331+ ``` rust
332+ #![debugger_visualizer(natvis_file = " ../Foo.natvis" )]
333+ struct FancyRect {
334+ pub x : f32 ,
335+ pub y : f32 ,
336+ pub dx : f32 ,
337+ pub dy : f32 ,
338+ }
339+
340+ fn main () {
341+ let mut fancy_rect = FancyRect :: new (10.0 , 10.0 , 5.0 , 5.0 );
342+ }
343+ ```
344+
345+ and ` Foo.natvis ` contains:
346+
347+ ``` xml
348+ <?xml version =" 1.0" encoding =" utf-8" ?>
349+ <AutoVisualizer xmlns =" http://schemas.microsoft.com/vstudio/debugger/natvis/2010" >
350+ <Type Name =" foo::FancyRect" >
351+ <DisplayString >({x},{y}) + ({dx}, {dy})</DisplayString >
352+ <Expand >
353+ <Synthetic Name =" LowerLeft" >
354+ <DisplayString >({x}, {y})</DisplayString >
355+ </Synthetic >
356+ <Synthetic Name =" UpperLeft" >
357+ <DisplayString >({x}, {y + dy})</DisplayString >
358+ </Synthetic >
359+ <Synthetic Name =" UpperRight" >
360+ <DisplayString >({x + dx}, {y + dy})</DisplayString >
361+ </Synthetic >
362+ <Synthetic Name =" LowerRight" >
363+ <DisplayString >({x + dx}, {y})</DisplayString >
364+ </Synthetic >
365+ </Expand >
366+ </Type >
367+ </AutoVisualizer >
368+ ```
369+
370+ When viewed under WinDbg, the ` fancy_rect ` variable would be shown as follows:
371+
372+ ``` text
373+ > Variables:
374+ > fancy_rect: (10, 10) + (5, 5)
375+ > LowerLeft: (10, 10)
376+ > UpperLeft: (10, 15)
377+ > UpperRight: (15, 15)
378+ > LowerRight: (15, 10)
379+ ```
380+
381+ ### Using ` debugger_visualizer ` with GDB
382+
383+ Developers using GDB are able to embed * pretty printers* onto types.
384+ In GDB, a pretty printer is a structured Python script that describes how a type's fields should be displayed in the debugger view.
385+ These scripts are embedded using the ` gdb_script_file ` meta item.
386+ GDB's [ pretty print documentation] can be referenced by developers to help them write their own ` .py ` scripts.
387+
388+ Consider a crate with this directory structure:
389+
390+ ``` text
391+ /Cargo.toml
392+ /bar.py (Note: the file does not have to match the name of the crate.)
393+ +-- src
394+ +-- main.rs
395+ ```
396+
397+ Where ` main.rs ` contains:
398+
399+ ``` rust
400+ #![debugger_visualizer(gdb_script_file = " ../bar.py" )]
401+ mod person {
402+ pub struct Person {
403+ pub name : String ,
404+ pub age : i32 ,
405+ }
406+ }
407+
408+ use person :: Person ;
409+
410+ fn main () {
411+ let person = Person :: new (String :: from (" Bob" ), 10 );
412+ }
413+ ```
414+
415+ and ` bar.py ` contains:
416+
417+ ``` python
418+ import gdb
419+
420+ class PersonPrinter :
421+ " Print a Person"
422+
423+ def __init__ (self , val ):
424+ self .val = val
425+ self .name = val[" name" ]
426+ self .age = int (val[" age" ])
427+
428+ def to_string (self ):
429+ return " {} is {} years old." .format(self .name, self .age)
430+
431+ def lookup (val ):
432+ lookup_tag = val.type.tag
433+ if lookup_tag is None :
434+ return None
435+ if " main::Person" == lookup_tag:
436+ return PersonPrinter(val)
437+
438+ return None
439+
440+ gdb.current_objfile().pretty_printers.append(lookup)
441+ ```
442+
443+ When the crate's debug executable is passed into GDB, ` print person ` should display:
444+
445+ ```
446+ "Bob" is 10 years old.
447+ ```
448+
304449[ Clippy ] : https://github.com/rust-lang/rust-clippy
450+ [ Natvis documentation ] : https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects
451+ [ pretty print documentation ] : https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html
305452[ _MetaListNameValueStr_ ] : ../attributes.md#meta-item-attribute-syntax
306453[ _MetaListPaths_ ] : ../attributes.md#meta-item-attribute-syntax
307454[ _MetaNameValueStr_ ] : ../attributes.md#meta-item-attribute-syntax
0 commit comments