diff options
| author | bors <bors@rust-lang.org> | 2019-11-23 07:27:17 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-11-23 07:27:17 +0000 |
| commit | 9420ff4c0ebea44b167d530bb59f9d5721d8ff0b (patch) | |
| tree | 83f6563bf56a871442a4909c363273394901073d | |
| parent | d9025395c8e46599f062216c818e3388e597d553 (diff) | |
| parent | 839d58ca56581c432d537ccca7a04010535d748c (diff) | |
| download | rust-9420ff4c0ebea44b167d530bb59f9d5721d8ff0b.tar.gz rust-9420ff4c0ebea44b167d530bb59f9d5721d8ff0b.zip | |
Auto merge of #66597 - MaulingMonkey:pr-natvis-std-collections-hash, r=michaelwoerister
debuginfo: Support for std::collections::Hash* in windows debuggers. Okay, I finally needed to debug code involving a HashMap! Added support for HashSet s as well. r? @michaelwoerister ### Local Testing Verified these are passing locally: ```cmd :: cmd.exe python x.py test --stage 1 --build x86_64-pc-windows-msvc src/test/debuginfo python x.py test --stage 1 --build i686-pc-windows-msvc src/test/debuginfo python x.py test --stage 1 src/tools/tidy :: MinGW MSYS2 ./x.py test --stage 1 --build x86_64-pc-windows-gnu src/test/debuginfo ``` ### Related Issues * https://github.com/rust-lang/rust/issues/36503 * https://github.com/rust-lang/rust/issues/40460 * https://github.com/rust-gamedev/wg/issues/20
| -rw-r--r-- | src/bootstrap/dist.rs | 1 | ||||
| -rw-r--r-- | src/etc/natvis/libstd.natvis | 102 | ||||
| -rw-r--r-- | src/test/debuginfo/pretty-std-collections-hash.rs | 97 |
3 files changed, 200 insertions, 0 deletions
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 67907bc8cbf..d0c9e0dbaf4 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -616,6 +616,7 @@ impl Step for DebuggerScripts { cp_debugger_script("natvis/intrinsic.natvis"); cp_debugger_script("natvis/liballoc.natvis"); cp_debugger_script("natvis/libcore.natvis"); + cp_debugger_script("natvis/libstd.natvis"); } else { cp_debugger_script("debugger_pretty_printers_common.py"); diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis new file mode 100644 index 00000000000..b3fc3d17af7 --- /dev/null +++ b/src/etc/natvis/libstd.natvis @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8"?> +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + <!-- + std::collection::Hash* container visualizers + + Current std impls: + std::collections::hash::set::HashSet<K, S> is implemented in terms of... + std::collections::hash::map::HashMap<K, V, S> is implemented in terms of... + hashbrown::map::HashMap<K, V, S> is implemented in terms of... + hashbrown::raw::RawTable<(K, V)> + + Ideally, we'd teach rustc to scan dependencies/crates for .natvis files so + the bulk of this could live alongside the hashbrown crate implementation, + and std would just forward using e.g. <ExpandedItem>base</ExpandedItem>. + + However, Given that std...Hash*Set* is currently implemented in terms of + hashbrown...Hash*Map*, which would visualize poorly, we want to customize the + look/feel at the std type level *anyways*... + + References: + https://github.com/rust-lang/rust/blob/master/src/libstd/collections/hash/map.rs + https://github.com/rust-lang/rust/blob/master/src/libstd/collections/hash/set.rs + https://github.com/rust-lang/hashbrown/blob/master/src/map.rs + https://github.com/rust-lang/hashbrown/blob/master/src/set.rs + https://github.com/rust-lang/hashbrown/blob/master/src/raw/mod.rs + --> + + <Type Name="std::collections::hash::map::HashMap<*,*,*>"> + <DisplayString>{{ size={base.table.items} }}</DisplayString> + <Expand> + <Item Name="[size]">base.table.items</Item> + <Item Name="[capacity]">base.table.items + base.table.growth_left</Item> + + <CustomListItems> + <Variable Name="i" InitialValue="0" /> + <Variable Name="n" InitialValue="base.table.items" /> + <Size>base.table.items</Size> + <Loop> + <Break Condition="n == 0" /> + <If Condition="(base.table.ctrl.pointer[i] & 0x80) == 0"> + <!-- Bucket is populated --> + <Exec>n--</Exec> + <Item Name="{base.table.data.pointer[i].__0}">base.table.data.pointer[i].__1</Item> + </If> + <Exec>i++</Exec> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="std::collections::hash::set::HashSet<*,*>"> + <DisplayString>{{ size={map.base.table.items} }}</DisplayString> + <Expand> + <Item Name="[size]">map.base.table.items</Item> + <Item Name="[capacity]">map.base.table.items + map.base.table.growth_left</Item> + + <CustomListItems> + <Variable Name="i" InitialValue="0" /> + <Variable Name="n" InitialValue="map.base.table.items" /> + <Size>map.base.table.items</Size> + <Loop> + <Break Condition="n == 0" /> + <If Condition="(map.base.table.ctrl.pointer[i] & 0x80) == 0"> + <!-- Bucket is populated --> + <Exec>n--</Exec> + <Item>map.base.table.data.pointer[i].__0</Item> + </If> + <Exec>i++</Exec> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="hashbrown::raw::RawTable<*>"> + <!-- RawTable has a nice and simple layout. + items Number of *populated* values in the RawTable (less than the size of ctrl.pointer / data.pointer) + growth_left Remaining capacity before growth + ctrl.pointer[i] & 0x80 Indicates the bucket is empty / should be skipped / doesn't count towards items. + data.pointer[i] The (K,V) tuple, if not empty. + --> + <DisplayString>{{ size={items} }}</DisplayString> + <Expand> + <Item Name="[size]">items</Item> + <Item Name="[capacity]">items + growth_left</Item> + + <CustomListItems> + <Variable Name="i" InitialValue="0" /> + <Variable Name="n" InitialValue="items" /> + <Size>items</Size> + <Loop> + <Break Condition="n == 0" /> + <If Condition="(ctrl.pointer[i] & 0x80) == 0"> + <!-- Bucket is populated --> + <Exec>n--</Exec> + <Item>data.pointer[i]</Item> + </If> + <Exec>i++</Exec> + </Loop> + </CustomListItems> + </Expand> + </Type> +</AutoVisualizer> diff --git a/src/test/debuginfo/pretty-std-collections-hash.rs b/src/test/debuginfo/pretty-std-collections-hash.rs new file mode 100644 index 00000000000..361b300f28c --- /dev/null +++ b/src/test/debuginfo/pretty-std-collections-hash.rs @@ -0,0 +1,97 @@ +// cdb-only +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx hash_set,d +// cdb-check:hash_set,d [...] : { size=15 } [Type: [...]::HashSet<u64, [...]>] +// cdb-check: [size] : 15 [Type: [...]] +// cdb-check: [capacity] : [...] +// cdb-check: [[...]] [...] : 0 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 1 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 2 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 3 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 4 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 5 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 6 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 7 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 8 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 9 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 10 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 11 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 12 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 13 [Type: unsigned __int64] +// cdb-command: dx hash_set,d +// cdb-check: [[...]] [...] : 14 [Type: unsigned __int64] + +// cdb-command: dx hash_map,d +// cdb-check:hash_map,d [...] : { size=15 } [Type: [...]::HashMap<u64, u64, [...]>] +// cdb-check: [size] : 15 [Type: [...]] +// cdb-check: [capacity] : [...] +// cdb-check: ["0x0"] : 0 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x1"] : 1 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x2"] : 2 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x3"] : 3 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x4"] : 4 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x5"] : 5 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x6"] : 6 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x7"] : 7 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x8"] : 8 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0x9"] : 9 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0xa"] : 10 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0xb"] : 11 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0xc"] : 12 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0xd"] : 13 [Type: unsigned __int64] +// cdb-command: dx hash_map,d +// cdb-check: ["0xe"] : 14 [Type: unsigned __int64] + +#![allow(unused_variables)] +use std::collections::HashSet; +use std::collections::HashMap; + + +fn main() { + // HashSet + let mut hash_set = HashSet::new(); + for i in 0..15 { + hash_set.insert(i as u64); + } + + // HashMap + let mut hash_map = HashMap::new(); + for i in 0..15 { + hash_map.insert(i as u64, i as u64); + } + + zzz(); // #break +} + +fn zzz() { () } |
