Skip to content

Commit

Permalink
Update HashMap/HashSet pretty-printers to Rust 1.47
Browse files Browse the repository at this point in the history
The corresponding PRs in rustc:
rust-lang/rust#76458
rust-lang/rust#70052
  • Loading branch information
artemmukhin committed Oct 14, 2020
1 parent 8e7a4e7 commit d56d9e3
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 12 deletions.
4 changes: 2 additions & 2 deletions prettyPrinters/gdb_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ def lookup(valobj):
else:
return StdOldHashMapProvider(valobj)
if rust_type == RustType.STD_HASH_SET:
hash_map = valobj["map"]
hash_map = valobj[valobj.type.fields()[0]]
if is_hashbrown_hashmap(hash_map):
return StdHashMapProvider(hash_map, show_values=False)
return StdHashMapProvider(valobj, show_values=False)
else:
return StdOldHashMapProvider(hash_map, show_values=False)

Expand Down
25 changes: 22 additions & 3 deletions prettyPrinters/gdb_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,18 @@ def __init__(self, valobj, show_values=True):
self.valobj = valobj
self.show_values = show_values

table = self.valobj["base"]["table"]
table = self.table()
capacity = int(table["bucket_mask"]) + 1
ctrl = table["ctrl"]["pointer"]

self.size = int(table["items"])
self.data_ptr = table["data"]["pointer"]
self.pair_type = self.data_ptr.dereference().type
self.pair_type = table.type.template_argument(0).strip_typedefs()

self.new_layout = not table.type.has_key("data")
if self.new_layout:
self.data_ptr = ctrl.cast(self.pair_type.pointer())
else:
self.data_ptr = table["data"]["pointer"]

self.valid_indices = []
for idx in range(capacity):
Expand All @@ -366,6 +371,18 @@ def __init__(self, valobj, show_values=True):
if is_presented:
self.valid_indices.append(idx)

def table(self):
if self.show_values:
hashbrown_hashmap = self.valobj["base"]
elif self.valobj.type.fields()[0].name == "map":
# BACKCOMPAT: rust 1.47
# HashSet wraps std::collections::HashMap, which wraps hashbrown::HashMap
hashbrown_hashmap = self.valobj["map"]["base"]
else:
# HashSet wraps hashbrown::HashSet, which wraps hashbrown::HashMap
hashbrown_hashmap = self.valobj["base"]["map"]
return hashbrown_hashmap["table"]

def to_string(self):
return "size={}".format(self.size)

Expand All @@ -374,6 +391,8 @@ def children(self):

for index in range(self.size):
idx = self.valid_indices[index]
if self.new_layout:
idx = -(idx + 1)
element = (pairs_start + idx).dereference()
if self.show_values:
yield ("key{}".format(index), element[ZERO_FIELD])
Expand Down
2 changes: 1 addition & 1 deletion prettyPrinters/lldb_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def synthetic_lookup(valobj, dict):
if rust_type == RustType.STD_HASH_SET:
hash_map = valobj.GetChildAtIndex(0)
if is_hashbrown_hashmap(hash_map):
return StdHashMapSyntheticProvider(hash_map, dict, show_values=False)
return StdHashMapSyntheticProvider(valobj, dict, show_values=False)
else:
return StdOldHashMapSyntheticProvider(hash_map, dict, show_values=False)

Expand Down
27 changes: 23 additions & 4 deletions prettyPrinters/lldb_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ def get_child_at_index(self, index):
# type: (int) -> SBValue
pairs_start = self.data_ptr.GetValueAsUnsigned()
idx = self.valid_indices[index]
if self.new_layout:
idx = -(idx + 1)
address = pairs_start + idx * self.pair_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
if self.show_values:
Expand All @@ -480,26 +482,43 @@ def get_child_at_index(self, index):

def update(self):
# type: () -> None
table = self.valobj.GetChildMemberWithName("base").GetChildMemberWithName("table")
table = self.table()
capacity = table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)

self.size = table.GetChildMemberWithName("items").GetValueAsUnsigned()
self.data_ptr = table.GetChildMemberWithName("data").GetChildAtIndex(0)
self.pair_type = self.data_ptr.Dereference().GetType()
self.pair_type = table.type.template_args[0].GetTypedefedType()
self.pair_type_size = self.pair_type.GetByteSize()

self.new_layout = not table.GetChildMemberWithName("data").IsValid()
if self.new_layout:
self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType())
else:
self.data_ptr = table.GetChildMemberWithName("data").GetChildAtIndex(0)

u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar)
u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()

self.valid_indices = []
for idx in range(capacity):
address = ctrl.GetValueAsUnsigned() + idx * u8_type_size
value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address, u8_type).GetValueAsUnsigned()
value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address,
u8_type).GetValueAsUnsigned()
is_present = value & 128 == 0
if is_present:
self.valid_indices.append(idx)

def table(self):
# type: () -> SBValue
if self.show_values:
hashbrown_hashmap = self.valobj.GetChildMemberWithName("base")
else:
# BACKCOMPAT: rust 1.47
# HashSet wraps either std HashMap or hashbrown::HashSet, which both
# wrap hashbrown::HashMap, so either way we "unwrap" twice.
hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0)
return hashbrown_hashmap.GetChildMemberWithName("table")

def has_children(self):
# type: () -> bool
return True
Expand Down
2 changes: 0 additions & 2 deletions pretty_printers_tests/tests/hash_map.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// min-version: 1.33.0
// https://github.com/intellij-rust/intellij-rust/issues/6198
// max-version: 1.46.0

// === LLDB TESTS ==================================================================================

Expand Down

0 comments on commit d56d9e3

Please sign in to comment.