@@ -301,7 +301,154 @@ When used on a function in a trait implementation, the attribute does nothing.
301
301
> let _ = five();
302
302
> ```
303
303
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
+
304
449
[ 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
305
452
[ _MetaListNameValueStr_ ] : ../attributes.md#meta-item-attribute-syntax
306
453
[ _MetaListPaths_ ] : ../attributes.md#meta-item-attribute-syntax
307
454
[ _MetaNameValueStr_ ] : ../attributes.md#meta-item-attribute-syntax
0 commit comments