gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / rust-lang.c
index 36dab6788df5447c3528107a3c71be33cc7c0e61..0929daf0511090df9acc46aa5f0cad19e10d2eaf 100644 (file)
@@ -1,6 +1,6 @@
 /* Rust language support routines for GDB, the GNU debugger.
 
-   Copyright (C) 2016 Free Software Foundation, Inc.
+   Copyright (C) 2016-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "c-lang.h"
 #include "charset.h"
 #include "cp-support.h"
+#include "demangle.h"
 #include "gdbarch.h"
 #include "infcall.h"
 #include "objfiles.h"
+#include "psymtab.h"
 #include "rust-lang.h"
+#include "typeprint.h"
 #include "valprint.h"
 #include "varobj.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+#include "cli/cli-style.h"
 
-extern initialize_file_ftype _initialize_rust_language;
-
-/* Returns the last segment of a Rust path like foo::bar::baz.  Will
-   not handle cases where the last segment contains generics.  This
-   will return NULL if the last segment cannot be found.  */
+/* See rust-lang.h.  */
 
-static const char *
-rust_last_path_segment (const char * path)
+const char *
+rust_last_path_segment (const char *path)
 {
   const char *result = strrchr (path, ':');
 
   if (result == NULL)
-    return NULL;
+    return path;
   return result + 1;
 }
 
-/* Find the Rust crate for BLOCK.  If no crate can be found, returns
-   NULL.  Otherwise, returns a newly allocated string that the caller
-   is responsible for freeing.  */
+/* See rust-lang.h.  */
 
-char *
+std::string
 rust_crate_for_block (const struct block *block)
 {
   const char *scope = block_scope (block);
 
   if (scope[0] == '\0')
-    return NULL;
+    return std::string ();
 
-  return xstrndup (scope, cp_find_first_component (scope));
+  return std::string (scope, cp_find_first_component (scope));
 }
 
-/* Information about the discriminant/variant of an enum */
+/* Return true if TYPE, which must be a struct type, represents a Rust
+   enum.  */
 
-struct disr_info
+static bool
+rust_enum_p (struct type *type)
 {
-  /* Name of field.  Must be freed by caller.  */
-  char *name;
-  /* Field number in union.  Negative on error.  For an encoded enum,
-     the "hidden" member will always be field 1, and the "real" member
-     will always be field 0.  */
-  int field_no;
-  /* True if this is an encoded enum that has a single "real" member
-     and a single "hidden" member.  */
-  unsigned int is_encoded : 1;
-};
-
-/* The prefix of a specially-encoded enum.  */
-
-#define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$"
-
-/* The number of the real field.  */
-
-#define RUST_ENCODED_ENUM_REAL 0
-
-/* The number of the hidden field.  */
-
-#define RUST_ENCODED_ENUM_HIDDEN 1
+  /* is_dynamic_type will return true if any field has a dynamic
+     attribute -- but we only want to check the top level.  */
+  return TYPE_HAS_VARIANT_PARTS (type);
+}
 
-/* Utility function to get discriminant info for a given value.  */
+/* Return true if TYPE, which must be an already-resolved enum type,
+   has no variants.  */
 
-static struct disr_info
-rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
-                    int embedded_offset, CORE_ADDR address,
-                    const struct value *val)
+static bool
+rust_empty_enum_p (const struct type *type)
 {
-  int i;
-  struct disr_info ret;
-  struct type *disr_type;
-  struct ui_file *temp_file;
-  struct value_print_options opts;
-  struct cleanup *cleanup;
-  const char *name_segment;
-
-  get_no_prettyformat_print_options (&opts);
-
-  ret.field_no = -1;
-  ret.is_encoded = 0;
-
-  if (TYPE_NFIELDS (type) == 0)
-    error (_("Encountered void enum value"));
-
-  /* If an enum has two values where one is empty and the other holds
-     a pointer that cannot be zero; then the Rust compiler optimizes
-     away the discriminant and instead uses a zero value in the
-     pointer field to indicate the empty variant.  */
-  if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
-              strlen (RUST_ENUM_PREFIX)) == 0)
-    {
-      char *tail;
-      unsigned long fieldno;
-      struct type *member_type;
-      LONGEST value;
-
-      ret.is_encoded = 1;
-
-      if (TYPE_NFIELDS (type) != 1)
-       error (_("Only expected one field in %s type"), RUST_ENUM_PREFIX);
-
-      fieldno = strtoul (TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX),
-                        &tail, 10);
-      if (*tail != '$')
-       error (_("Invalid form for %s"), RUST_ENUM_PREFIX);
-
-      member_type = TYPE_FIELD_TYPE (type, 0);
-      if (fieldno >= TYPE_NFIELDS (member_type))
-       error (_("%s refers to field after end of member type"),
-              RUST_ENUM_PREFIX);
-
-      embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8;
-      value = unpack_long (TYPE_FIELD_TYPE (member_type, fieldno),
-                          valaddr + embedded_offset);
-      if (value == 0)
-       {
-         ret.field_no = RUST_ENCODED_ENUM_HIDDEN;
-         ret.name = concat (TYPE_NAME (type), "::", tail + 1, (char *) NULL);
-       }
-      else
-       {
-         ret.field_no = RUST_ENCODED_ENUM_REAL;
-         ret.name = concat (TYPE_NAME (type), "::",
-                            rust_last_path_segment (TYPE_NAME (member_type)),
-                            (char *) NULL);
-       }
-
-      return ret;
-    }
-
-  disr_type = TYPE_FIELD_TYPE (type, 0);
-
-  if (TYPE_NFIELDS (disr_type) == 0)
-    {
-      /* This is a bounds check and should never be hit unless Rust
-        has changed its debuginfo format.  */
-      error (_("Could not find enum discriminant field"));
-    }
-
-  if (strcmp (TYPE_FIELD_NAME (disr_type, 0), "RUST$ENUM$DISR") != 0)
-    error (_("Rust debug format has changed"));
-
-  temp_file = mem_fileopen ();
-  cleanup = make_cleanup_ui_file_delete (temp_file);
-  /* The first value of the first field (or any field)
-     is the discriminant value.  */
-  c_val_print (TYPE_FIELD_TYPE (disr_type, 0), valaddr,
-              (embedded_offset + TYPE_FIELD_BITPOS (type, 0) / 8
-               + TYPE_FIELD_BITPOS (disr_type, 0) / 8),
-              address, temp_file,
-              0, val, &opts);
-
-  ret.name = ui_file_xstrdup (temp_file, NULL);
-  name_segment = rust_last_path_segment (ret.name);
-  if (name_segment != NULL)
-    {
-      for (i = 0; i < TYPE_NFIELDS (type); ++i)
-       {
-         /* Sadly, the discriminant value paths do not match the type
-            field name paths ('core::option::Option::Some' vs
-            'core::option::Some').  However, enum variant names are
-            unique in the last path segment and the generics are not
-            part of this path, so we can just compare those.  This is
-            hackish and would be better fixed by improving rustc's
-            metadata for enums.  */
-         const char *field_type = TYPE_NAME (TYPE_FIELD_TYPE (type, i));
-
-         if (field_type != NULL
-             && strcmp (name_segment,
-                        rust_last_path_segment (field_type)) == 0)
-           {
-             ret.field_no = i;
-             break;
-           }
-       }
-    }
+  return type->num_fields () == 0;
+}
 
-  if (ret.field_no == -1 && ret.name != NULL)
-    {
-      /* Somehow the discriminant wasn't found.  */
-      make_cleanup (xfree, ret.name);
-      error (_("Could not find variant of %s with discriminant %s"),
-            TYPE_TAG_NAME (type), ret.name);
-    }
+/* Given an already-resolved enum type and contents, find which
+   variant is active.  */
 
-  do_cleanups (cleanup);
-  return ret;
+static int
+rust_enum_variant (struct type *type)
+{
+  /* The active variant is simply the first non-artificial field.  */
+  for (int i = 0; i < type->num_fields (); ++i)
+    if (!TYPE_FIELD_ARTIFICIAL (type, i))
+      return i;
+
+  /* Perhaps we could get here by trying to print an Ada variant
+     record in Rust mode.  Unlikely, but an error is safer than an
+     assert.  */
+  error (_("Could not find active enum variant"));
 }
 
 /* See rust-lang.h.  */
 
-int
+bool
 rust_tuple_type_p (struct type *type)
 {
   /* The current implementation is a bit of a hack, but there's
      nothing else in the debuginfo to distinguish a tuple from a
      struct.  */
-  return (TYPE_CODE (type) == TYPE_CODE_STRUCT
-         && TYPE_TAG_NAME (type) != NULL
-         && TYPE_TAG_NAME (type)[0] == '(');
+  return (type->code () == TYPE_CODE_STRUCT
+         && type->name () != NULL
+         && type->name ()[0] == '(');
 }
 
-
 /* Return true if all non-static fields of a structlike type are in a
-   sequence like __0, __1, __2.  OFFSET lets us skip fields.  */
+   sequence like __0, __1, __2.  */
 
-static int
-rust_underscore_fields (struct type *type, int offset)
+static bool
+rust_underscore_fields (struct type *type)
 {
   int i, field_number;
 
   field_number = 0;
 
-  if (TYPE_CODE (type) != TYPE_CODE_STRUCT)
-    return 0;
-  for (i = 0; i < TYPE_NFIELDS (type); ++i)
+  if (type->code () != TYPE_CODE_STRUCT)
+    return false;
+  for (i = 0; i < type->num_fields (); ++i)
     {
-      if (!field_is_static (&TYPE_FIELD (type, i)))
+      if (!field_is_static (&type->field (i)))
        {
-         if (offset > 0)
-           offset--;
-         else
-           {
-             char buf[20];
+         char buf[20];
 
-             xsnprintf (buf, sizeof (buf), "__%d", field_number);
-             if (strcmp (buf, TYPE_FIELD_NAME (type, i)) != 0)
-               return 0;
-             field_number++;
-           }
+         xsnprintf (buf, sizeof (buf), "__%d", field_number);
+         if (strcmp (buf, TYPE_FIELD_NAME (type, i)) != 0)
+           return false;
+         field_number++;
        }
     }
-  return 1;
+  return true;
 }
 
 /* See rust-lang.h.  */
 
-int
+bool
 rust_tuple_struct_type_p (struct type *type)
 {
-  return rust_underscore_fields (type, 0);
-}
-
-/* Return true if a variant TYPE is a tuple variant, false otherwise.  */
-
-static int
-rust_tuple_variant_type_p (struct type *type)
-{
-  /* First field is discriminant */
-  return rust_underscore_fields (type, 1);
+  /* This is just an approximation until DWARF can represent Rust more
+     precisely.  We exclude zero-length structs because they may not
+     be tuple structs, and there's no way to tell.  */
+  return type->num_fields () > 0 && rust_underscore_fields (type);
 }
 
 /* Return true if TYPE is a slice type, otherwise false.  */
 
-static int
+static bool
 rust_slice_type_p (struct type *type)
 {
-  return (TYPE_CODE (type) == TYPE_CODE_STRUCT
-         && TYPE_TAG_NAME (type) != NULL
-         && strncmp (TYPE_TAG_NAME (type), "&[", 2) == 0);
+  return (type->code () == TYPE_CODE_STRUCT
+         && type->name () != NULL
+         && (strncmp (type->name (), "&[", 2) == 0
+             || strcmp (type->name (), "&str") == 0));
 }
 
 /* Return true if TYPE is a range type, otherwise false.  */
 
-static int
+static bool
 rust_range_type_p (struct type *type)
 {
   int i;
 
-  if (TYPE_CODE (type) != TYPE_CODE_STRUCT
-      || TYPE_NFIELDS (type) > 2
-      || TYPE_TAG_NAME (type) == NULL
-      || strstr (TYPE_TAG_NAME (type), "::Range") == NULL)
-    return 0;
+  if (type->code () != TYPE_CODE_STRUCT
+      || type->num_fields () > 2
+      || type->name () == NULL
+      || strstr (type->name (), "::Range") == NULL)
+    return false;
 
-  if (TYPE_NFIELDS (type) == 0)
-    return 1;
+  if (type->num_fields () == 0)
+    return true;
 
   i = 0;
   if (strcmp (TYPE_FIELD_NAME (type, 0), "start") == 0)
     {
-      if (TYPE_NFIELDS (type) == 1)
-       return 1;
+      if (type->num_fields () == 1)
+       return true;
       i = 1;
     }
-  else if (TYPE_NFIELDS (type) == 2)
+  else if (type->num_fields () == 2)
     {
       /* First field had to be "start".  */
-      return 0;
+      return false;
     }
 
   return strcmp (TYPE_FIELD_NAME (type, i), "end") == 0;
 }
 
+/* Return true if TYPE is an inclusive range type, otherwise false.
+   This is only valid for types which are already known to be range
+   types.  */
+
+static bool
+rust_inclusive_range_type_p (struct type *type)
+{
+  return (strstr (type->name (), "::RangeInclusive") != NULL
+         || strstr (type->name (), "::RangeToInclusive") != NULL);
+}
+
 /* Return true if TYPE seems to be the type "u8", otherwise false.  */
 
-static int
+static bool
 rust_u8_type_p (struct type *type)
 {
-  return (TYPE_CODE (type) == TYPE_CODE_INT
+  return (type->code () == TYPE_CODE_INT
          && TYPE_UNSIGNED (type)
          && TYPE_LENGTH (type) == 1);
 }
 
 /* Return true if TYPE is a Rust character type.  */
 
-static int
+static bool
 rust_chartype_p (struct type *type)
 {
-  return (TYPE_CODE (type) == TYPE_CODE_CHAR
+  return (type->code () == TYPE_CODE_CHAR
          && TYPE_LENGTH (type) == 4
          && TYPE_UNSIGNED (type));
 }
 
+/* Return true if TYPE is a string type.  */
+
+static bool
+rust_is_string_type_p (struct type *type)
+{
+  LONGEST low_bound, high_bound;
+
+  type = check_typedef (type);
+  return ((type->code () == TYPE_CODE_STRING)
+         || (type->code () == TYPE_CODE_PTR
+             && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ARRAY
+                 && rust_u8_type_p (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)))
+                 && get_array_bounds (TYPE_TARGET_TYPE (type), &low_bound,
+                                      &high_bound)))
+         || (type->code () == TYPE_CODE_STRUCT
+             && !rust_enum_p (type)
+             && rust_slice_type_p (type)
+             && strcmp (type->name (), "&str") == 0));
+}
+
+/* If VALUE represents a trait object pointer, return the underlying
+   pointer with the correct (i.e., runtime) type.  Otherwise, return
+   NULL.  */
+
+static struct value *
+rust_get_trait_object_pointer (struct value *value)
+{
+  struct type *type = check_typedef (value_type (value));
+
+  if (type->code () != TYPE_CODE_STRUCT || type->num_fields () != 2)
+    return NULL;
+
+  /* Try to be a bit resilient if the ABI changes.  */
+  int vtable_field = 0;
+  for (int i = 0; i < 2; ++i)
+    {
+      if (strcmp (TYPE_FIELD_NAME (type, i), "vtable") == 0)
+       vtable_field = i;
+      else if (strcmp (TYPE_FIELD_NAME (type, i), "pointer") != 0)
+       return NULL;
+    }
+
+  CORE_ADDR vtable = value_as_address (value_field (value, vtable_field));
+  struct symbol *symbol = find_symbol_at_address (vtable);
+  if (symbol == NULL || symbol->subclass != SYMBOL_RUST_VTABLE)
+    return NULL;
+
+  struct rust_vtable_symbol *vtable_sym
+    = static_cast<struct rust_vtable_symbol *> (symbol);
+  struct type *pointer_type = lookup_pointer_type (vtable_sym->concrete_type);
+  return value_cast (pointer_type, value_field (value, 1 - vtable_field));
+}
+
 \f
 
 /* la_emitchar implementation for Rust.  */
@@ -414,6 +350,187 @@ rust_printstr (struct ui_file *stream, struct type *type,
 
 \f
 
+static void rust_value_print_inner (struct value *val, struct ui_file *stream,
+                                   int recurse,
+                                   const struct value_print_options *options);
+
+/* Helper function to print a string slice.  */
+
+static void
+rust_val_print_str (struct ui_file *stream, struct value *val,
+                   const struct value_print_options *options)
+{
+  struct value *base = value_struct_elt (&val, NULL, "data_ptr", NULL,
+                                        "slice");
+  struct value *len = value_struct_elt (&val, NULL, "length", NULL, "slice");
+
+  val_print_string (TYPE_TARGET_TYPE (value_type (base)), "UTF-8",
+                   value_as_address (base), value_as_long (len), stream,
+                   options);
+}
+
+/* rust_val_print helper for structs and untagged unions.  */
+
+static void
+val_print_struct (struct value *val, struct ui_file *stream, int recurse,
+                 const struct value_print_options *options)
+{
+  int i;
+  int first_field;
+  struct type *type = check_typedef (value_type (val));
+
+  if (rust_slice_type_p (type) && strcmp (type->name (), "&str") == 0)
+    {
+      /* If what we are printing here is actually a string within a
+        structure then VAL will be the original parent value, while TYPE
+        will be the type of the structure representing the string we want
+        to print.
+        However, RUST_VAL_PRINT_STR looks up the fields of the string
+        inside VAL, assuming that VAL is the string.
+        So, recreate VAL as a value representing just the string.  */
+      val = value_at_lazy (type, value_address (val));
+      rust_val_print_str (stream, val, options);
+      return;
+    }
+
+  bool is_tuple = rust_tuple_type_p (type);
+  bool is_tuple_struct = !is_tuple && rust_tuple_struct_type_p (type);
+  struct value_print_options opts;
+
+  if (!is_tuple)
+    {
+      if (type->name () != NULL)
+        fprintf_filtered (stream, "%s", type->name ());
+
+      if (type->num_fields () == 0)
+        return;
+
+      if (type->name () != NULL)
+        fputs_filtered (" ", stream);
+    }
+
+  if (is_tuple || is_tuple_struct)
+    fputs_filtered ("(", stream);
+  else
+    fputs_filtered ("{", stream);
+
+  opts = *options;
+  opts.deref_ref = 0;
+
+  first_field = 1;
+  for (i = 0; i < type->num_fields (); ++i)
+    {
+      if (field_is_static (&type->field (i)))
+        continue;
+
+      if (!first_field)
+        fputs_filtered (",", stream);
+
+      if (options->prettyformat)
+        {
+         fputs_filtered ("\n", stream);
+         print_spaces_filtered (2 + 2 * recurse, stream);
+        }
+      else if (!first_field)
+        fputs_filtered (" ", stream);
+
+      first_field = 0;
+
+      if (!is_tuple && !is_tuple_struct)
+        {
+         fputs_styled (TYPE_FIELD_NAME (type, i),
+                       variable_name_style.style (), stream);
+         fputs_filtered (": ", stream);
+        }
+
+      rust_value_print_inner (value_field (val, i), stream, recurse + 1,
+                             &opts);
+    }
+
+  if (options->prettyformat)
+    {
+      fputs_filtered ("\n", stream);
+      print_spaces_filtered (2 * recurse, stream);
+    }
+
+  if (is_tuple || is_tuple_struct)
+    fputs_filtered (")", stream);
+  else
+    fputs_filtered ("}", stream);
+}
+
+/* rust_val_print helper for discriminated unions (Rust enums).  */
+
+static void
+rust_print_enum (struct value *val, struct ui_file *stream, int recurse,
+                const struct value_print_options *options)
+{
+  struct value_print_options opts = *options;
+  struct type *type = check_typedef (value_type (val));
+
+  opts.deref_ref = 0;
+
+  gdb_assert (rust_enum_p (type));
+  gdb::array_view<const gdb_byte> view (value_contents_for_printing (val),
+                                       TYPE_LENGTH (value_type (val)));
+  type = resolve_dynamic_type (type, view, value_address (val));
+
+  if (rust_empty_enum_p (type))
+    {
+      /* Print the enum type name here to be more clear.  */
+      fprintf_filtered (stream, _("%s {%p[<No data fields>%p]}"),
+                       type->name (),
+                       metadata_style.style ().ptr (), nullptr);
+      return;
+    }
+
+  int variant_fieldno = rust_enum_variant (type);
+  val = value_field (val, variant_fieldno);
+  struct type *variant_type = TYPE_FIELD_TYPE (type, variant_fieldno);
+
+  int nfields = variant_type->num_fields ();
+
+  bool is_tuple = rust_tuple_struct_type_p (variant_type);
+
+  fprintf_filtered (stream, "%s", variant_type->name ());
+  if (nfields == 0)
+    {
+      /* In case of a nullary variant like 'None', just output
+        the name. */
+      return;
+    }
+
+  /* In case of a non-nullary variant, we output 'Foo(x,y,z)'. */
+  if (is_tuple)
+    fprintf_filtered (stream, "(");
+  else
+    {
+      /* struct variant.  */
+      fprintf_filtered (stream, "{");
+    }
+
+  bool first_field = true;
+  for (int j = 0; j < variant_type->num_fields (); j++)
+    {
+      if (!first_field)
+       fputs_filtered (", ", stream);
+      first_field = false;
+
+      if (!is_tuple)
+       fprintf_filtered (stream, "%ps: ",
+                         styled_string (variable_name_style.style (),
+                                        TYPE_FIELD_NAME (variant_type, j)));
+
+      rust_value_print_inner (value_field (val, j), stream, recurse + 1,
+                             &opts);
+    }
+
+  if (is_tuple)
+    fputs_filtered (")", stream);
+  else
+    fputs_filtered ("}", stream);
+}
+
 static const struct generic_val_print_decorations rust_decorations =
 {
   /* Complex isn't used in Rust, but we provide C-ish values just in
@@ -423,63 +540,66 @@ static const struct generic_val_print_decorations rust_decorations =
   " * I",
   "true",
   "false",
-  "void",
+  "()",
   "[",
   "]"
 };
 
-/* la_val_print implementation for Rust.  */
-
+/* la_value_print_inner implementation for Rust.  */
 static void
-rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
-               CORE_ADDR address, struct ui_file *stream, int recurse,
-               const struct value *val,
-               const struct value_print_options *options)
+rust_value_print_inner (struct value *val, struct ui_file *stream,
+                       int recurse,
+                       const struct value_print_options *options)
 {
-  type = check_typedef (type);
-  switch (TYPE_CODE (type))
+  struct value_print_options opts = *options;
+  opts.deref_ref = 1;
+
+  if (opts.prettyformat == Val_prettyformat_default)
+    opts.prettyformat = (opts.prettyformat_structs
+                        ? Val_prettyformat : Val_no_prettyformat);
+
+  struct type *type = check_typedef (value_type (val));
+  switch (type->code ())
     {
     case TYPE_CODE_PTR:
       {
        LONGEST low_bound, high_bound;
        
-       if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY
+       if (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ARRAY
            && rust_u8_type_p (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)))
            && get_array_bounds (TYPE_TARGET_TYPE (type), &low_bound,
-                                &high_bound)) {
-         /* We have a pointer to a byte string, so just print
-            that.  */
-         struct type *elttype = check_typedef (TYPE_TARGET_TYPE (type));
-         CORE_ADDR addr;
-         struct gdbarch *arch = get_type_arch (type);
-         int unit_size = gdbarch_addressable_memory_unit_size (arch);
+                                &high_bound))
+         {
+           /* We have a pointer to a byte string, so just print
+              that.  */
+           struct type *elttype = check_typedef (TYPE_TARGET_TYPE (type));
+           CORE_ADDR addr = value_as_address (val);
+           struct gdbarch *arch = get_type_arch (type);
 
-         addr = unpack_pointer (type, valaddr + embedded_offset * unit_size);
-         if (options->addressprint)
-           {
-             fputs_filtered (paddress (arch, addr), stream);
-             fputs_filtered (" ", stream);
-           }
+           if (opts.addressprint)
+             {
+               fputs_filtered (paddress (arch, addr), stream);
+               fputs_filtered (" ", stream);
+             }
 
-         fputs_filtered ("b", stream);
-         val_print_string (TYPE_TARGET_TYPE (elttype), "ASCII", addr,
-                           high_bound - low_bound + 1, stream,
-                           options);
-         break;
-       }
+           fputs_filtered ("b", stream);
+           val_print_string (TYPE_TARGET_TYPE (elttype), "ASCII", addr,
+                             high_bound - low_bound + 1, stream,
+                             &opts);
+           break;
+         }
       }
-      /* Fall through.  */
+      goto generic_print;
 
     case TYPE_CODE_METHODPTR:
     case TYPE_CODE_MEMBERPTR:
-      c_val_print (type, valaddr, embedded_offset, address, stream,
-                  recurse, val, options);
+      c_value_print_inner (val, stream, recurse, &opts);
       break;
 
     case TYPE_CODE_INT:
       /* Recognize the unit type.  */
       if (TYPE_UNSIGNED (type) && TYPE_LENGTH (type) == 0
-         && TYPE_NAME (type) != NULL && strcmp (TYPE_NAME (type), "()") == 0)
+         && type->name () != NULL && strcmp (type->name (), "()") == 0)
        {
          fputs_filtered ("()", stream);
          break;
@@ -488,8 +608,6 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
     case TYPE_CODE_STRING:
       {
-       struct gdbarch *arch = get_type_arch (type);
-       int unit_size = gdbarch_addressable_memory_unit_size (arch);
        LONGEST low_bound, high_bound;
 
        if (!get_array_bounds (type, &low_bound, &high_bound))
@@ -500,8 +618,8 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
           encoding.  */
        fputs_filtered ("b", stream);
        rust_printstr (stream, TYPE_TARGET_TYPE (type),
-                      valaddr + embedded_offset * unit_size,
-                      high_bound - low_bound + 1, "ASCII", 0, options);
+                      value_contents_for_printing (val),
+                      high_bound - low_bound + 1, "ASCII", 0, &opts);
       }
       break;
 
@@ -518,168 +636,171 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
       break;
 
     case TYPE_CODE_UNION:
-      {
-       int j, nfields, first_field, is_tuple, start;
-       struct type *variant_type;
-       struct disr_info disr;
-       struct value_print_options opts;
-       struct cleanup *cleanup;
-
-       opts = *options;
-       opts.deref_ref = 0;
-
-       disr = rust_get_disr_info (type, valaddr, embedded_offset, address,
-                                  val);
-       cleanup = make_cleanup (xfree, disr.name);
-
-       if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
-         {
-           fprintf_filtered (stream, "%s", disr.name);
-           goto cleanup;
-         }
-
-       first_field = 1;
-       variant_type = TYPE_FIELD_TYPE (type, disr.field_no);
-       nfields = TYPE_NFIELDS (variant_type);
-
-       is_tuple = (disr.is_encoded
-                   ? rust_tuple_struct_type_p (variant_type)
-                   : rust_tuple_variant_type_p (variant_type));
-       start = disr.is_encoded ? 0 : 1;
-
-       if (nfields > start)
-         {
-           /* In case of a non-nullary variant, we output 'Foo(x,y,z)'. */
-           if (is_tuple)
-             fprintf_filtered (stream, "%s(", disr.name);
-           else
-             {
-               /* struct variant.  */
-               fprintf_filtered (stream, "%s{", disr.name);
-             }
-         }
-       else
-         {
-           /* In case of a nullary variant like 'None', just output
-              the name. */
-           fprintf_filtered (stream, "%s", disr.name);
-           goto cleanup;
-         }
-
-       for (j = start; j < TYPE_NFIELDS (variant_type); j++)
-         {
-           if (!first_field)
-             fputs_filtered (", ", stream);
-           first_field = 0;
-
-           if (!is_tuple)
-             fprintf_filtered (stream, "%s: ",
-                               TYPE_FIELD_NAME (variant_type, j));
-
-           val_print (TYPE_FIELD_TYPE (variant_type, j),
-                      valaddr,
-                      (embedded_offset
-                       + TYPE_FIELD_BITPOS (type, disr.field_no) / 8
-                       + TYPE_FIELD_BITPOS (variant_type, j) / 8),
-                      address,
-                      stream, recurse + 1, val, &opts,
-                      current_language);
-         }
-
-       if (is_tuple)
-         fputs_filtered (")", stream);
-       else
-         fputs_filtered ("}", stream);
-
-      cleanup:
-       do_cleanups (cleanup);
-      }
+      /* Untagged unions are printed as if they are structs.  Since
+        the field bit positions overlap in the debuginfo, the code
+        for printing a union is same as that for a struct, the only
+        difference is that the input type will have overlapping
+        fields.  */
+      val_print_struct (val, stream, recurse, &opts);
       break;
 
     case TYPE_CODE_STRUCT:
-      {
-       int i;
-       int first_field;
-       int is_tuple = rust_tuple_type_p (type);
-       int is_tuple_struct = !is_tuple && rust_tuple_struct_type_p (type);
-       struct value_print_options opts;
-
-       if (!is_tuple)
-         {
-           if (TYPE_TAG_NAME (type) != NULL)
-             fprintf_filtered (stream, "%s", TYPE_TAG_NAME (type));
-
-           if (TYPE_NFIELDS (type) == 0)
-             break;
-
-           if (TYPE_TAG_NAME (type) != NULL)
-             fputs_filtered (" ", stream);
-         }
+      if (rust_enum_p (type))
+       rust_print_enum (val, stream, recurse, &opts);
+      else
+       val_print_struct (val, stream, recurse, &opts);
+      break;
 
-       if (is_tuple || is_tuple_struct)
-         fputs_filtered ("(", stream);
-       else
-         fputs_filtered ("{", stream);
+    default:
+    generic_print:
+      /* Nothing special yet.  */
+      generic_value_print (val, stream, recurse, &opts, &rust_decorations);
+    }
+}
 
-       opts = *options;
-       opts.deref_ref = 0;
+\f
 
-       first_field = 1;
-       for (i = 0; i < TYPE_NFIELDS (type); ++i)
-         {
-           if (field_is_static (&TYPE_FIELD (type, i)))
-             continue;
+static void
+rust_internal_print_type (struct type *type, const char *varstring,
+                         struct ui_file *stream, int show, int level,
+                         const struct type_print_options *flags,
+                         bool for_rust_enum, print_offset_data *podata);
 
-           if (!first_field)
-             fputs_filtered (",", stream);
+/* Print a struct or union typedef.  */
+static void
+rust_print_struct_def (struct type *type, const char *varstring,
+                      struct ui_file *stream, int show, int level,
+                      const struct type_print_options *flags,
+                      bool for_rust_enum, print_offset_data *podata)
+{
+  /* Print a tuple type simply.  */
+  if (rust_tuple_type_p (type))
+    {
+      fputs_filtered (type->name (), stream);
+      return;
+    }
 
-           if (options->prettyformat)
-             {
-               fputs_filtered ("\n", stream);
-               print_spaces_filtered (2 + 2 * recurse, stream);
-             }
-           else if (!first_field)
-             fputs_filtered (" ", stream);
+  /* If we see a base class, delegate to C.  */
+  if (TYPE_N_BASECLASSES (type) > 0)
+    c_print_type (type, varstring, stream, show, level, flags);
 
-           first_field = 0;
+  if (flags->print_offsets)
+    {
+      /* Temporarily bump the level so that the output lines up
+        correctly.  */
+      level += 2;
+    }
 
-           if (!is_tuple && !is_tuple_struct)
-             {
-               fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
-               fputs_filtered (": ", stream);
-             }
+  /* Compute properties of TYPE here because, in the enum case, the
+     rest of the code ends up looking only at the variant part.  */
+  const char *tagname = type->name ();
+  bool is_tuple_struct = rust_tuple_struct_type_p (type);
+  bool is_tuple = rust_tuple_type_p (type);
+  bool is_enum = rust_enum_p (type);
 
-           val_print (TYPE_FIELD_TYPE (type, i),
-                      valaddr,
-                      embedded_offset + TYPE_FIELD_BITPOS (type, i) / 8,
-                      address,
-                      stream, recurse + 1, val, &opts,
-                      current_language);
-         }
+  if (for_rust_enum)
+    {
+      /* Already printing an outer enum, so nothing to print here.  */
+    }
+  else
+    {
+      /* This code path is also used by unions and enums.  */
+      if (is_enum)
+       {
+         fputs_filtered ("enum ", stream);
+         dynamic_prop *prop = type->dyn_prop (DYN_PROP_VARIANT_PARTS);
+         if (prop != nullptr && prop->kind == PROP_TYPE)
+           type = prop->data.original_type;
+       }
+      else if (type->code () == TYPE_CODE_STRUCT)
+       fputs_filtered ("struct ", stream);
+      else
+       fputs_filtered ("union ", stream);
 
-       if (options->prettyformat)
-         {
-           fputs_filtered ("\n", stream);
-           print_spaces_filtered (2 * recurse, stream);
-         }
+      if (tagname != NULL)
+       fputs_filtered (tagname, stream);
+    }
 
-       if (is_tuple || is_tuple_struct)
-         fputs_filtered (")", stream);
-       else
-         fputs_filtered ("}", stream);
-      }
-      break;
+  if (type->num_fields () == 0 && !is_tuple)
+    return;
+  if (for_rust_enum && !flags->print_offsets)
+    fputs_filtered (is_tuple_struct ? "(" : "{", stream);
+  else
+    fputs_filtered (is_tuple_struct ? " (\n" : " {\n", stream);
+
+  /* When printing offsets, we rearrange the fields into storage
+     order.  This lets us show holes more clearly.  We work using
+     field indices here because it simplifies calls to
+     print_offset_data::update below.  */
+  std::vector<int> fields;
+  for (int i = 0; i < type->num_fields (); ++i)
+    {
+      if (field_is_static (&type->field (i)))
+       continue;
+      if (is_enum && TYPE_FIELD_ARTIFICIAL (type, i))
+       continue;
+      fields.push_back (i);
+    }
+  if (flags->print_offsets)
+    std::sort (fields.begin (), fields.end (),
+              [&] (int a, int b)
+              {
+                return (TYPE_FIELD_BITPOS (type, a)
+                        < TYPE_FIELD_BITPOS (type, b));
+              });
+
+  for (int i : fields)
+    {
+      QUIT;
+
+      gdb_assert (!field_is_static (&type->field (i)));
+      gdb_assert (! (is_enum && TYPE_FIELD_ARTIFICIAL (type, i)));
+
+      if (flags->print_offsets)
+       podata->update (type, i, stream);
+
+      /* We'd like to print "pub" here as needed, but rustc
+        doesn't emit the debuginfo, and our types don't have
+        cplus_struct_type attached.  */
+
+      /* For a tuple struct we print the type but nothing
+        else.  */
+      if (!for_rust_enum || flags->print_offsets)
+       print_spaces_filtered (level + 2, stream);
+      if (is_enum)
+       fputs_styled (TYPE_FIELD_NAME (type, i), variable_name_style.style (),
+                     stream);
+      else if (!is_tuple_struct)
+       fprintf_filtered (stream, "%ps: ",
+                         styled_string (variable_name_style.style (),
+                                        TYPE_FIELD_NAME (type, i)));
+
+      rust_internal_print_type (TYPE_FIELD_TYPE (type, i), NULL,
+                               stream, (is_enum ? show : show - 1),
+                               level + 2, flags, is_enum, podata);
+      if (!for_rust_enum || flags->print_offsets)
+       fputs_filtered (",\n", stream);
+      /* Note that this check of "I" is ok because we only sorted the
+        fields by offset when print_offsets was set, so we won't take
+        this branch in that case.  */
+      else if (i + 1 < type->num_fields ())
+       fputs_filtered (", ", stream);
+    }
 
-    default:
-    generic_print:
-      /* Nothing special yet.  */
-      generic_val_print (type, valaddr, embedded_offset, address, stream,
-                        recurse, val, options, &rust_decorations);
+  if (flags->print_offsets)
+    {
+      /* Undo the temporary level increase we did above.  */
+      level -= 2;
+      podata->finish (type, level, stream);
+      print_spaces_filtered (print_offset_data::indentation, stream);
+      if (level == 0)
+       print_spaces_filtered (2, stream);
     }
+  if (!for_rust_enum || flags->print_offsets)
+    print_spaces_filtered (level, stream);
+  fputs_filtered (is_tuple_struct ? ")" : "}", stream);
 }
 
-\f
-
 /* la_print_typedef implementation for Rust.  */
 
 static void
@@ -688,31 +809,43 @@ rust_print_typedef (struct type *type,
                    struct ui_file *stream)
 {
   type = check_typedef (type);
-  fprintf_filtered (stream, "type %s = ", SYMBOL_PRINT_NAME (new_symbol));
+  fprintf_filtered (stream, "type %s = ", new_symbol->print_name ());
   type_print (type, "", stream, 0);
-  fprintf_filtered (stream, ";\n");
+  fprintf_filtered (stream, ";");
 }
 
 /* la_print_type implementation for Rust.  */
 
 static void
-rust_print_type (struct type *type, const char *varstring,
-                struct ui_file *stream, int show, int level,
-                const struct type_print_options *flags)
+rust_internal_print_type (struct type *type, const char *varstring,
+                         struct ui_file *stream, int show, int level,
+                         const struct type_print_options *flags,
+                         bool for_rust_enum, print_offset_data *podata)
 {
-  int i;
-
   QUIT;
   if (show <= 0
-      && TYPE_NAME (type) != NULL)
+      && type->name () != NULL)
     {
-      fputs_filtered (TYPE_NAME (type), stream);
+      /* Rust calls the unit type "void" in its debuginfo,
+         but we don't want to print it as that.  */
+      if (type->code () == TYPE_CODE_VOID)
+        fputs_filtered ("()", stream);
+      else
+        fputs_filtered (type->name (), stream);
       return;
     }
 
   type = check_typedef (type);
-  switch (TYPE_CODE (type))
+  switch (type->code ())
     {
+    case TYPE_CODE_VOID:
+      /* If we have an enum, we've already printed the type's
+        unqualified name, and there is nothing else to print
+        here.  */
+      if (!for_rust_enum)
+       fputs_filtered ("()", stream);
+      break;
+
     case TYPE_CODE_FUNC:
       /* Delegate varargs to the C printer.  */
       if (TYPE_VARARGS (type))
@@ -722,16 +855,22 @@ rust_print_type (struct type *type, const char *varstring,
       if (varstring != NULL)
        fputs_filtered (varstring, stream);
       fputs_filtered ("(", stream);
-      for (i = 0; i < TYPE_NFIELDS (type); ++i)
+      for (int i = 0; i < type->num_fields (); ++i)
        {
          QUIT;
          if (i > 0)
            fputs_filtered (", ", stream);
-         rust_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0,
-                          flags);
+         rust_internal_print_type (TYPE_FIELD_TYPE (type, i), "", stream,
+                                   -1, 0, flags, false, podata);
        }
-      fputs_filtered (") -> ", stream);
-      rust_print_type (TYPE_TARGET_TYPE (type), "", stream, -1, 0, flags);
+      fputs_filtered (")", stream);
+      /* If it returns unit, we can omit the return type.  */
+      if (TYPE_TARGET_TYPE (type)->code () != TYPE_CODE_VOID)
+        {
+          fputs_filtered (" -> ", stream);
+          rust_internal_print_type (TYPE_TARGET_TYPE (type), "", stream,
+                                   -1, 0, flags, false, podata);
+        }
       break;
 
     case TYPE_CODE_ARRAY:
@@ -739,155 +878,70 @@ rust_print_type (struct type *type, const char *varstring,
        LONGEST low_bound, high_bound;
 
        fputs_filtered ("[", stream);
-       rust_print_type (TYPE_TARGET_TYPE (type), NULL,
-                        stream, show - 1, level, flags);
-       fputs_filtered ("; ", stream);
+       rust_internal_print_type (TYPE_TARGET_TYPE (type), NULL,
+                                 stream, show - 1, level, flags, false,
+                                 podata);
 
        if (TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCEXPR
            || TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCLIST)
-         fprintf_filtered (stream, "variable length");
+         fprintf_filtered (stream, "variable length");
        else if (get_array_bounds (type, &low_bound, &high_bound))
-         fprintf_filtered (stream, "%s", 
+         fprintf_filtered (stream, "; %s",
                            plongest (high_bound - low_bound + 1));
        fputs_filtered ("]", stream);
       }
       break;
 
+    case TYPE_CODE_UNION:
     case TYPE_CODE_STRUCT:
-      {
-       int is_tuple_struct;
-
-       /* Print a tuple type simply.  */
-       if (rust_tuple_type_p (type))
-         {
-           fputs_filtered (TYPE_TAG_NAME (type), stream);
-           break;
-         }
-
-       /* If we see a base class, delegate to C.  */
-       if (TYPE_N_BASECLASSES (type) > 0)
-         goto c_printer;
-
-       fputs_filtered ("struct ", stream);
-       if (TYPE_TAG_NAME (type) != NULL)
-         fputs_filtered (TYPE_TAG_NAME (type), stream);
-
-       is_tuple_struct = rust_tuple_struct_type_p (type);
-
-       if (TYPE_NFIELDS (type) == 0 && !rust_tuple_type_p (type))
-         break;
-       fputs_filtered (is_tuple_struct ? " (\n" : " {\n", stream);
-
-       for (i = 0; i < TYPE_NFIELDS (type); ++i)
-         {
-           const char *name;
-
-           QUIT;
-           if (field_is_static (&TYPE_FIELD (type, i)))
-             continue;
-
-           /* We'd like to print "pub" here as needed, but rustc
-              doesn't emit the debuginfo, and our types don't have
-              cplus_struct_type attached.  */
-
-           /* For a tuple struct we print the type but nothing
-              else.  */
-           print_spaces_filtered (level + 2, stream);
-           if (!is_tuple_struct)
-             fprintf_filtered (stream, "%s: ", TYPE_FIELD_NAME (type, i));
-
-           rust_print_type (TYPE_FIELD_TYPE (type, i), NULL,
-                            stream, show - 1, level + 2,
-                            flags);
-           fputs_filtered (",\n", stream);
-         }
-
-       fprintfi_filtered (level, stream, is_tuple_struct ? ")" : "}");
-      }
+      rust_print_struct_def (type, varstring, stream, show, level, flags,
+                            for_rust_enum, podata);
       break;
 
     case TYPE_CODE_ENUM:
       {
-       int i, len = 0;
+       int len = 0;
 
        fputs_filtered ("enum ", stream);
-       if (TYPE_TAG_NAME (type) != NULL)
+       if (type->name () != NULL)
          {
-           fputs_filtered (TYPE_TAG_NAME (type), stream);
+           fputs_filtered (type->name (), stream);
            fputs_filtered (" ", stream);
-           len = strlen (TYPE_TAG_NAME (type));
+           len = strlen (type->name ());
          }
        fputs_filtered ("{\n", stream);
 
-       for (i = 0; i < TYPE_NFIELDS (type); ++i)
+       for (int i = 0; i < type->num_fields (); ++i)
          {
            const char *name = TYPE_FIELD_NAME (type, i);
 
            QUIT;
 
            if (len > 0
-               && strncmp (name, TYPE_TAG_NAME (type), len) == 0
+               && strncmp (name, type->name (), len) == 0
                && name[len] == ':'
                && name[len + 1] == ':')
              name += len + 2;
-           fprintfi_filtered (level + 2, stream, "%s,\n", name);
+           fprintfi_filtered (level + 2, stream, "%ps,\n",
+                              styled_string (variable_name_style.style (),
+                                             name));
          }
 
        fputs_filtered ("}", stream);
       }
       break;
 
-    case TYPE_CODE_UNION:
+    case TYPE_CODE_PTR:
       {
-       /* ADT enums */
-       int i, len = 0;
-
-       fputs_filtered ("enum ", stream);
-       if (TYPE_TAG_NAME (type) != NULL)
+       if (type->name () != nullptr)
+         fputs_filtered (type->name (), stream);
+       else
          {
-           fputs_filtered (TYPE_TAG_NAME (type), stream);
-           fputs_filtered (" ", stream);
-           len = strlen (TYPE_TAG_NAME (type));
+           /* We currently can't distinguish between pointers and
+              references.  */
+           fputs_filtered ("*mut ", stream);
+           type_print (TYPE_TARGET_TYPE (type), "", stream, 0);
          }
-       fputs_filtered ("{\n", stream);      
-
-       for (i = 0; i < TYPE_NFIELDS (type); ++i)
-         {
-           struct type *variant_type = TYPE_FIELD_TYPE (type, i);
-           const char *name
-             = rust_last_path_segment (TYPE_NAME (variant_type));
-
-           fprintfi_filtered (level + 2, stream, "%s", name);
-
-           if (TYPE_NFIELDS (variant_type) > 1)
-             {
-               int first = 1;
-               int is_tuple = rust_tuple_variant_type_p (variant_type);
-               int j;
-
-               fputs_filtered (is_tuple ? "(" : "{", stream);
-               for (j = 1; j < TYPE_NFIELDS (variant_type); j++)
-                 {
-                   if (first)
-                     first = 0;
-                   else
-                     fputs_filtered (", ", stream);
-
-                   if (!is_tuple)
-                     fprintf_filtered (stream, "%s: ",
-                                       TYPE_FIELD_NAME (variant_type, j));
-
-                   rust_print_type (TYPE_FIELD_TYPE (variant_type, j), NULL,
-                                    stream, show - 1, level + 2,
-                                    flags);
-                 }
-               fputs_filtered (is_tuple ? ")" : "}", stream);
-             }
-
-           fputs_filtered (",\n", stream);
-         }
-
-       fputs_filtered ("}", stream);
       }
       break;
 
@@ -899,47 +953,6 @@ rust_print_type (struct type *type, const char *varstring,
 
 \f
 
-/* Compute the alignment of the type T.  */
-
-static int
-rust_type_alignment (struct type *t)
-{
-  t = check_typedef (t);
-  switch (TYPE_CODE (t))
-    {
-    default:
-      error (_("Could not compute alignment of type"));
-
-    case TYPE_CODE_PTR:
-    case TYPE_CODE_ENUM:
-    case TYPE_CODE_INT:
-    case TYPE_CODE_FLT:
-    case TYPE_CODE_REF:
-    case TYPE_CODE_CHAR:
-    case TYPE_CODE_BOOL:
-      return TYPE_LENGTH (t);
-
-    case TYPE_CODE_ARRAY:
-    case TYPE_CODE_COMPLEX:
-      return rust_type_alignment (TYPE_TARGET_TYPE (t));
-
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      {
-       int i;
-       int align = 1;
-
-       for (i = 0; i < TYPE_NFIELDS (t); ++i)
-         {
-           int a = rust_type_alignment (TYPE_FIELD_TYPE (t, i));
-           if (a > align)
-             align = a;
-         }
-       return align;
-      }
-    }
-}
-
 /* Like arch_composite_type, but uses TYPE to decide how to allocate
    -- either on an obstack or on a gdbarch.  */
 
@@ -958,19 +971,18 @@ rust_composite_type (struct type *original,
   if (field2 != NULL)
     ++nfields;
 
-  TYPE_CODE (result) = TYPE_CODE_STRUCT;
-  TYPE_NAME (result) = name;
-  TYPE_TAG_NAME (result) = name;
+  result->set_code (TYPE_CODE_STRUCT);
+  result->set_name (name);
 
-  TYPE_NFIELDS (result) = nfields;
-  TYPE_FIELDS (result)
-    = (struct field *) TYPE_ZALLOC (result, nfields * sizeof (struct field));
+  result->set_num_fields (nfields);
+  result->set_fields
+    ((struct field *) TYPE_ZALLOC (result, nfields * sizeof (struct field)));
 
   i = 0;
   bitpos = 0;
   if (field1 != NULL)
     {
-      struct field *field = &TYPE_FIELD (result, i);
+      struct field *field = &result->field (i);
 
       SET_FIELD_BITPOS (*field, bitpos);
       bitpos += TYPE_LENGTH (type1) * TARGET_CHAR_BIT;
@@ -981,8 +993,8 @@ rust_composite_type (struct type *original,
     }
   if (field2 != NULL)
     {
-      struct field *field = &TYPE_FIELD (result, i);
-      int align = rust_type_alignment (type2);
+      struct field *field = &result->field (i);
+      unsigned align = type_align (type2);
 
       if (align != 0)
        {
@@ -1044,49 +1056,6 @@ enum rust_primitive_types
   nr_rust_primitive_types
 };
 
-/* la_language_arch_info implementation for Rust.  */
-
-static void
-rust_language_arch_info (struct gdbarch *gdbarch,
-                        struct language_arch_info *lai)
-{
-  const struct builtin_type *builtin = builtin_type (gdbarch);
-  struct type *tem;
-  struct type **types;
-  unsigned int length;
-
-  types = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_rust_primitive_types + 1,
-                                 struct type *);
-
-  types[rust_primitive_bool] = arch_boolean_type (gdbarch, 8, 1, "bool");
-  types[rust_primitive_char] = arch_character_type (gdbarch, 32, 1, "char");
-  types[rust_primitive_i8] = arch_integer_type (gdbarch, 8, 0, "i8");
-  types[rust_primitive_u8] = arch_integer_type (gdbarch, 8, 1, "u8");
-  types[rust_primitive_i16] = arch_integer_type (gdbarch, 16, 0, "i16");
-  types[rust_primitive_u16] = arch_integer_type (gdbarch, 16, 1, "u16");
-  types[rust_primitive_i32] = arch_integer_type (gdbarch, 32, 0, "i32");
-  types[rust_primitive_u32] = arch_integer_type (gdbarch, 32, 1, "u32");
-  types[rust_primitive_i64] = arch_integer_type (gdbarch, 64, 0, "i64");
-  types[rust_primitive_u64] = arch_integer_type (gdbarch, 64, 1, "u64");
-
-  length = 8 * TYPE_LENGTH (builtin->builtin_data_ptr);
-  types[rust_primitive_isize] = arch_integer_type (gdbarch, length, 0, "isize");
-  types[rust_primitive_usize] = arch_integer_type (gdbarch, length, 1, "usize");
-
-  types[rust_primitive_f32] = arch_float_type (gdbarch, 32, "f32", NULL);
-  types[rust_primitive_f64] = arch_float_type (gdbarch, 64, "f64", NULL);
-
-  types[rust_primitive_unit] = arch_integer_type (gdbarch, 0, 1, "()");
-
-  tem = make_cv_type (1, 0, types[rust_primitive_u8], NULL);
-  types[rust_primitive_str] = rust_slice_type ("&str", tem,
-                                              types[rust_primitive_usize]);
-
-  lai->primitive_type_vector = types;
-  lai->bool_type_default = types[rust_primitive_bool];
-  lai->string_char_type = types[rust_primitive_u8];
-}
-
 \f
 
 /* A helper for rust_evaluate_subexp that handles OP_FUNCALL.  */
@@ -1097,10 +1066,7 @@ rust_evaluate_funcall (struct expression *exp, int *pos, enum noside noside)
   int i;
   int num_args = exp->elts[*pos + 1].longconst;
   const char *method;
-  char *name;
   struct value *function, *result, *arg0;
-  struct value **args;
-  struct cleanup *cleanup;
   struct type *type, *fn_type;
   const struct block *block;
   struct block_symbol sym;
@@ -1126,36 +1092,34 @@ rust_evaluate_funcall (struct expression *exp, int *pos, enum noside noside)
       return arg0;
     }
 
-  args = XNEWVEC (struct value *, num_args + 1);
-  cleanup = make_cleanup (xfree, args);
+  std::vector<struct value *> args (num_args + 1);
   args[0] = arg0;
 
   /* We don't yet implement real Deref semantics.  */
-  while (TYPE_CODE (value_type (args[0])) == TYPE_CODE_PTR)
+  while (value_type (args[0])->code () == TYPE_CODE_PTR)
     args[0] = value_ind (args[0]);
 
   type = value_type (args[0]);
-  if ((TYPE_CODE (type) != TYPE_CODE_STRUCT
-       && TYPE_CODE (type) != TYPE_CODE_UNION
-       && TYPE_CODE (type) != TYPE_CODE_ENUM)
+  if ((type->code () != TYPE_CODE_STRUCT
+       && type->code () != TYPE_CODE_UNION
+       && type->code () != TYPE_CODE_ENUM)
       || rust_tuple_type_p (type))
     error (_("Method calls only supported on struct or enum types"));
-  if (TYPE_TAG_NAME (type) == NULL)
+  if (type->name () == NULL)
     error (_("Method call on nameless type"));
 
-  name = concat (TYPE_TAG_NAME (type), "::", method, (char *) NULL);
-  make_cleanup (xfree, name);
+  std::string name = std::string (type->name ()) + "::" + method;
 
   block = get_selected_block (0);
-  sym = lookup_symbol (name, block, VAR_DOMAIN, NULL);
+  sym = lookup_symbol (name.c_str (), block, VAR_DOMAIN, NULL);
   if (sym.symbol == NULL)
-    error (_("Could not find function named '%s'"), name);
+    error (_("Could not find function named '%s'"), name.c_str ());
 
   fn_type = SYMBOL_TYPE (sym.symbol);
-  if (TYPE_NFIELDS (fn_type) == 0)
-    error (_("Function '%s' takes no arguments"), name);
+  if (fn_type->num_fields () == 0)
+    error (_("Function '%s' takes no arguments"), name.c_str ());
 
-  if (TYPE_CODE (TYPE_FIELD_TYPE (fn_type, 0)) == TYPE_CODE_PTR)
+  if (TYPE_FIELD_TYPE (fn_type, 0)->code () == TYPE_CODE_PTR)
     args[0] = value_addr (args[0]);
 
   function = address_of_variable (sym.symbol, block);
@@ -1166,8 +1130,7 @@ rust_evaluate_funcall (struct expression *exp, int *pos, enum noside noside)
   if (noside == EVAL_AVOID_SIDE_EFFECTS)
     result = value_zero (TYPE_TARGET_TYPE (fn_type), not_lval);
   else
-    result = call_function_by_hand (function, num_args + 1, args);
-  do_cleanups (cleanup);
+    result = call_function_by_hand (function, NULL, args);
   return result;
 }
 
@@ -1188,10 +1151,13 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
   kind = (enum range_type) longest_to_int (exp->elts[*pos + 1].longconst);
   *pos += 3;
 
-  if (kind == HIGH_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT)
+  if (kind == HIGH_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT
+      || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
     low = evaluate_subexp (NULL_TYPE, exp, pos, noside);
-  if (kind == LOW_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT)
+  if (kind == LOW_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT_EXCLUSIVE
+      || kind == NONE_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
     high = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+  bool inclusive = (kind == NONE_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT);
 
   if (noside == EVAL_SKIP)
     return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
@@ -1206,7 +1172,8 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
       else
        {
          index_type = value_type (high);
-         name = "std::ops::RangeTo";
+         name = (inclusive
+                 ? "std::ops::RangeToInclusive" : "std::ops::RangeTo");
        }
     }
   else
@@ -1221,7 +1188,7 @@ rust_range (struct expression *exp, int *pos, enum noside noside)
          if (!types_equal (value_type (low), value_type (high)))
            error (_("Range expression with different types"));
          index_type = value_type (low);
-         name = "std::ops::Range";
+         name = inclusive ? "std::ops::RangeInclusive" : "std::ops::Range";
        }
     }
 
@@ -1281,7 +1248,7 @@ rust_compute_range (struct type *type, struct value *range,
   *high = 0;
   *kind = BOTH_BOUND_DEFAULT;
 
-  if (TYPE_NFIELDS (type) == 0)
+  if (type->num_fields () == 0)
     return;
 
   i = 0;
@@ -1291,12 +1258,15 @@ rust_compute_range (struct type *type, struct value *range,
       *low = value_as_long (value_field (range, 0));
       ++i;
     }
-  if (TYPE_NFIELDS (type) > i
+  if (type->num_fields () > i
       && strcmp (TYPE_FIELD_NAME (type, i), "end") == 0)
     {
       *kind = (*kind == BOTH_BOUND_DEFAULT
               ? LOW_BOUND_DEFAULT : NONE_BOUND_DEFAULT);
       *high = value_as_long (value_field (range, i));
+
+      if (rust_inclusive_range_type_p (type))
+       ++*high;
     }
 }
 
@@ -1332,19 +1302,55 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
   else
     low = value_as_long (rhs);
 
+  struct type *type = check_typedef (value_type (lhs));
   if (noside == EVAL_AVOID_SIDE_EFFECTS)
     {
-      struct type *type = check_typedef (value_type (lhs));
+      struct type *base_type = nullptr;
+      if (type->code () == TYPE_CODE_ARRAY)
+       base_type = TYPE_TARGET_TYPE (type);
+      else if (rust_slice_type_p (type))
+       {
+         for (int i = 0; i < type->num_fields (); ++i)
+           {
+             if (strcmp (TYPE_FIELD_NAME (type, i), "data_ptr") == 0)
+               {
+                 base_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, i));
+                 break;
+               }
+           }
+         if (base_type == nullptr)
+           error (_("Could not find 'data_ptr' in slice type"));
+       }
+      else if (type->code () == TYPE_CODE_PTR)
+       base_type = TYPE_TARGET_TYPE (type);
+      else
+       error (_("Cannot subscript non-array type"));
+
+      struct type *new_type;
+      if (want_slice)
+       {
+         if (rust_slice_type_p (type))
+           new_type = type;
+         else
+           {
+             struct type *usize
+               = language_lookup_primitive_type (exp->language_defn,
+                                                 exp->gdbarch,
+                                                 "usize");
+             new_type = rust_slice_type ("&[*gdb*]", base_type, usize);
+           }
+       }
+      else
+       new_type = base_type;
 
-      result = value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (lhs));
+      return value_zero (new_type, VALUE_LVAL (lhs));
     }
   else
     {
       LONGEST low_bound;
       struct value *base;
-      struct type *type = check_typedef (value_type (lhs));
 
-      if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+      if (type->code () == TYPE_CODE_ARRAY)
        {
          base = lhs;
          if (!get_array_bounds (type, &low_bound, &high_bound))
@@ -1362,6 +1368,12 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
          low_bound = 0;
          high_bound = value_as_long (len);
        }
+      else if (type->code () == TYPE_CODE_PTR)
+       {
+         base = lhs;
+         low_bound = 0;
+         high_bound = LONGEST_MAX;
+       }
       else
        error (_("Cannot subscript non-array type"));
 
@@ -1396,8 +1408,11 @@ rust_subscript (struct expression *exp, int *pos, enum noside noside,
          usize = language_lookup_primitive_type (exp->language_defn,
                                                  exp->gdbarch,
                                                  "usize");
-         slice = rust_slice_type ("&[*gdb*]", value_type (result),
-                                  usize);
+         const char *new_name = ((type != nullptr
+                                  && rust_slice_type_p (type))
+                                 ? type->name () : "&[*gdb*]");
+
+         slice = rust_slice_type (new_name, value_type (result), usize);
 
          addrval = value_allocate_space_in_inferior (TYPE_LENGTH (slice));
          addr = value_as_long (addrval);
@@ -1426,6 +1441,25 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
 
   switch (exp->elts[*pos].opcode)
     {
+    case UNOP_IND:
+      {
+       if (noside != EVAL_NORMAL)
+         result = evaluate_subexp_standard (expect_type, exp, pos, noside);
+       else
+         {
+           ++*pos;
+           struct value *value = evaluate_subexp (expect_type, exp, pos,
+                                                  noside);
+
+           struct value *trait_ptr = rust_get_trait_object_pointer (value);
+           if (trait_ptr != NULL)
+             value = trait_ptr;
+
+           result = value_ind (value);
+         }
+      }
+      break;
+
     case UNOP_COMPLEMENT:
       {
        struct value *value;
@@ -1437,7 +1471,7 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
            /* Preserving the type is enough.  */
            return value;
          }
-       if (TYPE_CODE (value_type (value)) == TYPE_CODE_BOOL)
+       if (value_type (value)->code () == TYPE_CODE_BOOL)
          result = value_from_longest (value_type (value),
                                       value_logical_not (value));
        else
@@ -1523,7 +1557,7 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
 
     case OP_RUST_ARRAY:
       {
-       int pc = (*pos)++;
+       (*pos)++;
        int copies;
        struct value *elt;
        struct value *ncopies;
@@ -1536,16 +1570,12 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
 
        if (noside == EVAL_NORMAL)
          {
-           CORE_ADDR addr;
            int i;
-           struct value **eltvec = XNEWVEC (struct value *, copies);
-           struct cleanup *cleanup = make_cleanup (xfree, eltvec);
+           std::vector<struct value *> eltvec (copies);
 
            for (i = 0; i < copies; ++i)
              eltvec[i] = elt;
-           result = value_array (0, copies - 1, eltvec);
-
-           do_cleanups (cleanup);
+           result = value_array (0, copies - 1, eltvec.data ());
          }
        else
          {
@@ -1561,8 +1591,7 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
         /* Anonymous field access, i.e. foo.1.  */
         struct value *lhs;
         int pc, field_number, nfields;
-        struct type *type, *variant_type;
-        struct disr_info disr;
+        struct type *type;
 
         pc = (*pos)++;
         field_number = longest_to_int (exp->elts[pc + 1].longconst);
@@ -1570,60 +1599,57 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
         lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside);
 
         type = value_type (lhs);
-        if (TYPE_CODE (type) == TYPE_CODE_UNION)
-         {
-           struct cleanup *cleanup;
 
-           disr = rust_get_disr_info (type, value_contents (lhs),
-                                      value_embedded_offset (lhs),
-                                      value_address (lhs), lhs);
-
-           cleanup = make_cleanup (xfree, disr.name);
+       if (type->code () == TYPE_CODE_STRUCT)
+         {
+           struct type *outer_type = NULL;
 
-           if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
-             {
-               variant_type = NULL;
-               nfields = 0;
-             }
-           else
+           if (rust_enum_p (type))
              {
-               variant_type = TYPE_FIELD_TYPE (type, disr.field_no);
-               nfields = TYPE_NFIELDS (variant_type);
+               gdb::array_view<const gdb_byte> view (value_contents (lhs),
+                                                     TYPE_LENGTH (type));
+               type = resolve_dynamic_type (type, view, value_address (lhs));
+
+               if (rust_empty_enum_p (type))
+                 error (_("Cannot access field %d of empty enum %s"),
+                        field_number, type->name ());
+
+               int fieldno = rust_enum_variant (type);
+               lhs = value_primitive_field (lhs, 0, fieldno, type);
+               outer_type = type;
+               type = value_type (lhs);
              }
 
-           if (!disr.is_encoded)
-             ++field_number;
-
-           if (field_number >= nfields || field_number < 0)
-             error(_("Cannot access field %d of variant %s, \
-there are only %d fields"),
-                   disr.is_encoded ? field_number : field_number - 1,
-                   disr.name,
-                   disr.is_encoded ? nfields : nfields - 1);
-
-           if (!(disr.is_encoded
-                 ? rust_tuple_struct_type_p (variant_type)
-                 : rust_tuple_variant_type_p (variant_type)))
-             error(_("Variant %s is not a tuple variant"), disr.name);
-
-           result = value_primitive_field (lhs, 0, field_number,
-                                           variant_type);
-           do_cleanups (cleanup);
-         }
-       else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
-         {
            /* Tuples and tuple structs */
-           nfields = TYPE_NFIELDS(type);
+           nfields = type->num_fields ();
 
            if (field_number >= nfields || field_number < 0)
-             error(_("Cannot access field %d of %s, there are only %d fields"),
-                   field_number, TYPE_TAG_NAME (type), nfields);
+             {
+               if (outer_type != NULL)
+                 error(_("Cannot access field %d of variant %s::%s, "
+                         "there are only %d fields"),
+                       field_number, outer_type->name (),
+                       rust_last_path_segment (type->name ()),
+                       nfields);
+               else
+                 error(_("Cannot access field %d of %s, "
+                         "there are only %d fields"),
+                       field_number, type->name (), nfields);
+             }
 
            /* Tuples are tuple structs too.  */
            if (!rust_tuple_struct_type_p (type))
-             error(_("Attempting to access anonymous field %d of %s, which is \
-not a tuple, tuple struct, or tuple-like variant"),
-                   field_number, TYPE_TAG_NAME (type));
+             {
+               if (outer_type != NULL)
+                 error(_("Variant %s::%s is not a tuple variant"),
+                       outer_type->name (),
+                       rust_last_path_segment (type->name ()));
+               else
+                 error(_("Attempting to access anonymous field %d "
+                         "of %s, which is not a tuple, tuple struct, or "
+                         "tuple-like variant"),
+                     field_number, type->name ());
+             }
 
            result = value_primitive_field (lhs, 0, field_number, type);
          }
@@ -1635,7 +1661,7 @@ tuple structs, and tuple-like enum variants"));
 
     case STRUCTOP_STRUCT:
       {
-        struct valuelhs;
+        struct value *lhs;
         struct type *type;
         int tem, pc;
 
@@ -1644,58 +1670,45 @@ tuple structs, and tuple-like enum variants"));
         (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
         lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside);
 
+       const char *field_name = &exp->elts[pc + 2].string;
         type = value_type (lhs);
-
-        if (TYPE_CODE (type) == TYPE_CODE_UNION)
+        if (type->code () == TYPE_CODE_STRUCT && rust_enum_p (type))
          {
-           int i, start;
-           struct disr_info disr;
-           struct cleanup* cleanup;
-           struct type* variant_type;
-           char* field_name;
-
-           field_name = &exp->elts[pc + 2].string;
-
-           disr = rust_get_disr_info (type, value_contents (lhs),
-                                      value_embedded_offset (lhs),
-                                      value_address (lhs), lhs);
-
-           cleanup = make_cleanup (xfree, disr.name);
-
-           if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
-             error(_("Could not find field %s of struct variant %s"),
-                   field_name, disr.name);
-
-           variant_type = TYPE_FIELD_TYPE (type, disr.field_no);
-
-           if (variant_type == NULL
-               || rust_tuple_variant_type_p (variant_type))
-             error(_("Attempting to access named field %s of tuple variant %s, \
-which has only anonymous fields"),
-                   field_name, disr.name);
-
-           start = disr.is_encoded ? 0 : 1;
-           for (i = start; i < TYPE_NFIELDS (variant_type); i++)
+           gdb::array_view<const gdb_byte> view (value_contents (lhs),
+                                                 TYPE_LENGTH (type));
+           type = resolve_dynamic_type (type, view, value_address (lhs));
+
+           if (rust_empty_enum_p (type))
+             error (_("Cannot access field %s of empty enum %s"),
+                    field_name, type->name ());
+
+           int fieldno = rust_enum_variant (type);
+           lhs = value_primitive_field (lhs, 0, fieldno, type);
+
+           struct type *outer_type = type;
+           type = value_type (lhs);
+           if (rust_tuple_type_p (type) || rust_tuple_struct_type_p (type))
+               error (_("Attempting to access named field %s of tuple "
+                        "variant %s::%s, which has only anonymous fields"),
+                      field_name, outer_type->name (),
+                      rust_last_path_segment (type->name ()));
+
+           try
              {
-               if (strcmp (TYPE_FIELD_NAME (variant_type, i),
-                           field_name) == 0) {
-                 result = value_primitive_field (lhs, 0, i, variant_type);
-                 break;
-               }
+               result = value_struct_elt (&lhs, NULL, field_name,
+                                          NULL, "structure");
+             }
+           catch (const gdb_exception_error &except)
+             {
+               error (_("Could not find field %s of struct variant %s::%s"),
+                      field_name, outer_type->name (),
+                      rust_last_path_segment (type->name ()));
              }
-
-           if (i == TYPE_NFIELDS (variant_type))
-             /* We didn't find it.  */
-             error(_("Could not find field %s of struct variant %s"),
-                   field_name, disr.name);
-
-           do_cleanups (cleanup);
          }
        else
-         {
-           *pos = pc;
-           result = evaluate_subexp_standard (expect_type, exp, pos, noside);
-         }
+         result = value_struct_elt (&lhs, NULL, field_name, NULL, "structure");
+       if (noside == EVAL_AVOID_SIDE_EFFECTS)
+         result = value_zero (value_type (result), VALUE_LVAL (result));
       }
       break;
 
@@ -1766,7 +1779,7 @@ rust_operator_length (const struct expression *exp, int pc, int *oplenp,
 
 /* op_name implementation for Rust.  */
 
-static char *
+static const char *
 rust_op_name (enum exp_opcode opcode)
 {
   switch (opcode)
@@ -1826,14 +1839,15 @@ rust_dump_subexp_body (struct expression *exp, struct ui_file *stream,
       {
        int field_number;
 
-       field_number = longest_to_int (exp->elts[elt].longconst);
+       field_number = longest_to_int (exp->elts[elt + 1].longconst);
 
        fprintf_filtered (stream, "Field number: %d", field_number);
-       elt = dump_subexp (exp, stream, elt + 2);
+       elt = dump_subexp (exp, stream, elt + 3);
       }
       break;
 
     case OP_RUST_ARRAY:
+      ++elt;
       break;
 
     default:
@@ -1896,7 +1910,7 @@ rust_print_subexp (struct expression *exp, int *pos, struct ui_file *stream,
        print_subexp (exp, pos, stream, PREC_SUFFIX);
        fprintf_filtered (stream, ".%d", tem);
       }
-      return;
+      break;
 
     case OP_RUST_ARRAY:
       ++*pos;
@@ -1955,7 +1969,7 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
                             const struct block *block,
                             const domain_enum domain)
 {
-  struct block_symbol result = {NULL, NULL};
+  struct block_symbol result = {};
 
   if (symbol_lookup_debug)
     {
@@ -1967,27 +1981,45 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
     }
 
   /* Look up bare names in the block's scope.  */
+  std::string scopedname;
   if (name[cp_find_first_component (name)] == '\0')
     {
       const char *scope = block_scope (block);
 
       if (scope[0] != '\0')
        {
-         char *scopedname = concat (scope, "::", name, (char *) NULL);
-         struct cleanup *cleanup = make_cleanup (xfree, scopedname);
-
-         result = lookup_symbol_in_static_block (scopedname, block,
-                                                 domain);
-         if (result.symbol == NULL)
-           result = lookup_global_symbol (scopedname, block, domain);
-         do_cleanups (cleanup);
+         scopedname = std::string (scope) + "::" + name;
+         name = scopedname.c_str ();
        }
+      else
+       name = NULL;
+    }
+
+  if (name != NULL)
+    {
+      result = lookup_symbol_in_static_block (name, block, domain);
+      if (result.symbol == NULL)
+       result = lookup_global_symbol (name, block, domain);
     }
   return result;
 }
 
 \f
 
+/* la_watch_location_expression for Rust.  */
+
+static gdb::unique_xmalloc_ptr<char>
+rust_watch_location_expression (struct type *type, CORE_ADDR addr)
+{
+  type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type)));
+  std::string name = type_to_string (type);
+  return gdb::unique_xmalloc_ptr<char>
+    (xstrprintf ("*(%s as *mut %s)", core_addr_to_string (addr),
+                name.c_str ()));
+}
+
+\f
+
 static const struct exp_descriptor exp_descriptor_rust = 
 {
   rust_print_subexp,
@@ -2003,7 +2035,9 @@ static const char *rust_extensions[] =
   ".rs", NULL
 };
 
-static const struct language_defn rust_language_defn =
+/* Constant data representing the Rust language.  */
+
+extern const struct language_data rust_language_data =
 {
   "rust",
   "Rust",
@@ -2015,42 +2049,108 @@ static const struct language_defn rust_language_defn =
   rust_extensions,
   &exp_descriptor_rust,
   rust_parse,
-  rustyyerror,
   null_post_parser,
   rust_printchar,              /* Print a character constant */
   rust_printstr,               /* Function to print string constant */
   rust_emitchar,               /* Print a single char */
-  rust_print_type,             /* Print a type using appropriate syntax */
   rust_print_typedef,          /* Print a typedef using appropriate syntax */
-  rust_val_print,              /* Print a value using appropriate syntax */
+  rust_value_print_inner,      /* la_value_print_inner */
   c_value_print,               /* Print a top-level value */
-  default_read_var_value,      /* la_read_var_value */
-  NULL,                                /* Language specific skip_trampoline */
   NULL,                                /* name_of_this */
+  false,                       /* la_store_sym_names_in_linkage_form_p */
   rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
-  basic_lookup_transparent_type,/* lookup_transparent_type */
-  gdb_demangle,                        /* Language specific symbol demangler */
   NULL,                                /* Language specific
                                   class_name_from_physname */
   c_op_print_tab,              /* expression operators for printing */
   1,                           /* c-style arrays */
   0,                           /* String lower bound */
   default_word_break_characters,
-  default_make_symbol_completion_list,
-  rust_language_arch_info,
-  default_print_array_index,
-  default_pass_by_reference,
-  c_get_string,
-  NULL,                                /* la_get_symbol_name_cmp */
-  iterate_over_symbols,
+  default_collect_symbol_completion_matches,
+  rust_watch_location_expression,
+  NULL,                                /* la_get_symbol_name_matcher */
   &default_varobj_ops,
   NULL,
-  NULL,
-  LANG_MAGIC
+  rust_is_string_type_p,
+  "{...}"                      /* la_struct_too_deep_ellipsis */
 };
 
-void
-_initialize_rust_language (void)
+/* Class representing the Rust language.  */
+
+class rust_language : public language_defn
 {
-  add_language (&rust_language_defn);
-}
+public:
+  rust_language ()
+    : language_defn (language_rust, rust_language_data)
+  { /* Nothing.  */ }
+
+  /* See language.h.  */
+  void language_arch_info (struct gdbarch *gdbarch,
+                          struct language_arch_info *lai) const override
+  {
+    const struct builtin_type *builtin = builtin_type (gdbarch);
+
+    struct type **types
+      = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_rust_primitive_types + 1,
+                               struct type *);
+
+    types[rust_primitive_bool] = arch_boolean_type (gdbarch, 8, 1, "bool");
+    types[rust_primitive_char] = arch_character_type (gdbarch, 32, 1, "char");
+    types[rust_primitive_i8] = arch_integer_type (gdbarch, 8, 0, "i8");
+    types[rust_primitive_u8] = arch_integer_type (gdbarch, 8, 1, "u8");
+    types[rust_primitive_i16] = arch_integer_type (gdbarch, 16, 0, "i16");
+    types[rust_primitive_u16] = arch_integer_type (gdbarch, 16, 1, "u16");
+    types[rust_primitive_i32] = arch_integer_type (gdbarch, 32, 0, "i32");
+    types[rust_primitive_u32] = arch_integer_type (gdbarch, 32, 1, "u32");
+    types[rust_primitive_i64] = arch_integer_type (gdbarch, 64, 0, "i64");
+    types[rust_primitive_u64] = arch_integer_type (gdbarch, 64, 1, "u64");
+
+    unsigned int length = 8 * TYPE_LENGTH (builtin->builtin_data_ptr);
+    types[rust_primitive_isize] = arch_integer_type (gdbarch, length, 0, "isize");
+    types[rust_primitive_usize] = arch_integer_type (gdbarch, length, 1, "usize");
+
+    types[rust_primitive_f32] = arch_float_type (gdbarch, 32, "f32",
+                                                floatformats_ieee_single);
+    types[rust_primitive_f64] = arch_float_type (gdbarch, 64, "f64",
+                                                floatformats_ieee_double);
+
+    types[rust_primitive_unit] = arch_integer_type (gdbarch, 0, 1, "()");
+
+    struct type *tem = make_cv_type (1, 0, types[rust_primitive_u8], NULL);
+    types[rust_primitive_str] = rust_slice_type ("&str", tem,
+                                                types[rust_primitive_usize]);
+
+    lai->primitive_type_vector = types;
+    lai->bool_type_default = types[rust_primitive_bool];
+    lai->string_char_type = types[rust_primitive_u8];
+  }
+
+  /* See language.h.  */
+  bool sniff_from_mangled_name (const char *mangled,
+                               char **demangled) const override
+  {
+    *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+    return *demangled != NULL;
+  }
+
+  /* See language.h.  */
+
+  char *demangle (const char *mangled, int options) const override
+  {
+    return gdb_demangle (mangled, options);
+  }
+
+  /* See language.h.  */
+
+  void print_type (struct type *type, const char *varstring,
+                  struct ui_file *stream, int show, int level,
+                  const struct type_print_options *flags) const override
+  {
+    print_offset_data podata;
+    rust_internal_print_type (type, varstring, stream, show, level,
+                             flags, false, &podata);
+  }
+};
+
+/* Single instance of the Rust language class.  */
+
+static rust_language rust_language_defn;
This page took 0.049982 seconds and 4 git commands to generate.