about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-06 15:24:52 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-06 15:24:52 -0800
commitf358dbf1e7c3c3b474164f3d8bb4bd9f8e563c29 (patch)
tree4f89b89075c76c44705aa0da56d47d487ab725a6
parente2f97f51ad4cf902e5a5835b5332447fe59089c4 (diff)
parentd33857208f9af74fd414c79eeda40bdf50bf4574 (diff)
downloadrust-f358dbf1e7c3c3b474164f3d8bb4bd9f8e563c29.tar.gz
rust-f358dbf1e7c3c3b474164f3d8bb4bd9f8e563c29.zip
rollup merge of #20557: cactorium/prettyprinters
As per https://github.com/rust-lang/rust/issues/20405. To be more precise, the changes just the processing of enums when the name is "RUST$ENCODED$ENUM$..." so it correctly parses when there is more than one number encoding the location of the field it's looking for to determine state of the enum
-rwxr-xr-x[-rw-r--r--]src/etc/gdb_rust_pretty_printing.py25
-rw-r--r--src/etc/lldb_rust_formatters.py26
-rw-r--r--src/test/debuginfo/gdb-pretty-struct-and-enums.rs9
3 files changed, 38 insertions, 22 deletions
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
index 7e5918ea39e..b6770c99975 100644..100755
--- a/src/etc/gdb_rust_pretty_printing.py
+++ b/src/etc/gdb_rust_pretty_printing.py
@@ -51,7 +51,7 @@ def rust_pretty_printer_lookup_function(val):
     enum_member_count = len(enum_members)
 
     if enum_member_count == 0:
-      return RustStructPrinter(val, false)
+      return RustStructPrinter(val, False)
 
     if enum_member_count == 1:
       first_variant_name = enum_members[0].name
@@ -60,21 +60,27 @@ def rust_pretty_printer_lookup_function(val):
         return rust_pretty_printer_lookup_function(val[enum_members[0]])
       else:
         assert first_variant_name.startswith("RUST$ENCODED$ENUM$")
-        # This is a space-optimized enum
+        # This is a space-optimized enum.
+        # This means this enum has only two states, and Rust uses one of the
+        # fields somewhere in the struct to determine which of the two states
+        # it's in. The location of the field is encoded in the name as something
+        # like RUST$ENCODED$ENUM$(num$)*name_of_zero_state
         last_separator_index = first_variant_name.rfind("$")
-        second_last_separator_index = first_variant_name.rfind("$", 0, last_separator_index)
-        disr_field_index = first_variant_name[second_last_separator_index + 1 :
-                                              last_separator_index]
-        disr_field_index = int(disr_field_index)
+        start_index = len("RUST$ENCODED$ENUM$")
+        disr_field_indices = first_variant_name[start_index :
+                                              last_separator_index].split("$")
+        disr_field_indices = [int(index) for index in disr_field_indices]
 
         sole_variant_val = val[enum_members[0]]
-        disr_field = get_field_at_index(sole_variant_val, disr_field_index)
-        discriminant = sole_variant_val[disr_field]
+        discriminant = sole_variant_val
+        for disr_field_index in disr_field_indices:
+          disr_field = get_field_at_index(discriminant, disr_field_index)
+          discriminant = discriminant[disr_field]
 
         # If the discriminant field is a fat pointer we have to consider the
         # first word as the true discriminant
         if discriminant.type.code == gdb.TYPE_CODE_STRUCT:
-            discriminant = discriminant[get_field_at_index(discriminant, 0)]
+          discriminant = discriminant[get_field_at_index(discriminant, 0)]
 
         if discriminant == 0:
           null_variant_name = first_variant_name[last_separator_index + 1:]
@@ -234,4 +240,5 @@ def get_field_at_index(val, index):
   for field in val.type.fields():
     if i == index:
       return field
+    i += 1
   return None
diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
index f4f1a5121d1..05d71902904 100644
--- a/src/etc/lldb_rust_formatters.py
+++ b/src/etc/lldb_rust_formatters.py
@@ -79,11 +79,11 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict):
   has_field_names = type_has_field_names(t)
 
   if has_field_names:
-      template = "%(type_name)s {\n%(body)s\n}"
-      separator = ", \n"
+    template = "%(type_name)s {\n%(body)s\n}"
+    separator = ", \n"
   else:
-      template = "%(type_name)s(%(body)s)"
-      separator = ", "
+    template = "%(type_name)s(%(body)s)"
+    separator = ", "
 
   if type_name.startswith("("):
     # this is a tuple, so don't print the type name
@@ -125,25 +125,25 @@ def print_enum_val(val, internal_dict):
       if last_separator_index == -1:
         return "<invalid enum encoding: %s>" % first_variant_name
 
-      second_last_separator_index = first_variant_name.rfind("$", 0, last_separator_index)
-      if second_last_separator_index == -1:
-        return "<invalid enum encoding: %s>" % first_variant_name
+      start_index = len("RUST$ENCODED$ENUM$")
 
-      # Extract index of the discriminator field
+      # Extract indices of the discriminator field
       try:
-        disr_field_index = first_variant_name[second_last_separator_index + 1 :
-                                              last_separator_index]
-        disr_field_index = int(disr_field_index)
+        disr_field_indices = first_variant_name[start_index :
+                                              last_separator_index].split("$")
+        disr_field_indices = [int(index) for index in disr_field_indices]
       except:
         return "<invalid enum encoding: %s>" % first_variant_name
 
       # Read the discriminant
-      disr_val = val.GetChildAtIndex(0).GetChildAtIndex(disr_field_index)
+      disr_val = val.GetChildAtIndex(0)
+      for index in disr_field_indices:
+        disr_val = disr_val.GetChildAtIndex(index)
 
       # If the discriminant field is a fat pointer we have to consider the
       # first word as the true discriminant
       if disr_val.GetType().GetTypeClass() == lldb.eTypeClassStruct:
-          disr_val = disr_val.GetChildAtIndex(0)
+        disr_val = disr_val.GetChildAtIndex(0)
 
       if disr_val.GetValueAsUnsigned() == 0:
         # Null case: Print the name of the null-variant
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
index 64c120e1ab3..4b2628b2a1f 100644
--- a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
+++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
@@ -69,6 +69,12 @@
 // gdb-command: print nested_variant2
 // gdb-check:$16 = NestedVariant2 = {abc = NestedStruct = {regular_struct = RegularStruct = {the_first_field = 117, the_second_field = 118.5, the_third_field = false, the_fourth_field = "NestedStructString10"}, tuple_struct = TupleStruct = {119.5, 120}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar3, mixed_enum = MixedEnumStructVar = {field1 = 121.5, field2 = -122}}}
 
+// gdb-command: print none_check1
+// gdb-check:$17 = None
+
+// gdb-command: print none_check2
+// gdb-check:$18 = None
+
 use self::CStyleEnum::{CStyleEnumVar1, CStyleEnumVar2, CStyleEnumVar3};
 use self::MixedEnum::{MixedEnumCStyleVar, MixedEnumTupleVar, MixedEnumStructVar};
 use self::NestedEnum::{NestedVariant1, NestedVariant2};
@@ -170,6 +176,9 @@ fn main() {
         }
     };
 
+    let none_check1: Option<(uint, Vec<uint>)> = None;
+    let none_check2: Option<String> = None;
+
     zzz(); // #break
 }