diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index adec2f91961..d1eb750a621 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -38,37 +38,17 @@ public:
     TRAIT_ITEM,
   };
 
-  TypeCheckContextItem (HIR::Function *item)
-    : type (ItemType::ITEM), item (item)
-  {}
+  TypeCheckContextItem (HIR::Function *item);
+  TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item);
+  TypeCheckContextItem (HIR::TraitItemFunc *trait_item);
 
-  TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item)
-    : type (ItemType::IMPL_ITEM), item (impl_block, item)
-  {}
+  ItemType get_type () const;
 
-  TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
-    : type (ItemType::TRAIT_ITEM), item (trait_item)
-  {}
+  HIR::Function *get_item ();
 
-  ItemType get_type () const { return type; }
+  std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ();
 
-  HIR::Function *get_item ()
-  {
-    rust_assert (get_type () == ItemType::ITEM);
-    return item.item;
-  }
-
-  std::pair<HIR::ImplBlock *, HIR::Function *> &get_impl_item ()
-  {
-    rust_assert (get_type () == ItemType::IMPL_ITEM);
-    return item.impl_item;
-  };
-
-  HIR::TraitItemFunc *get_trait_item ()
-  {
-    rust_assert (get_type () == ItemType::TRAIT_ITEM);
-    return item.trait_item;
-  }
+  HIR::TraitItemFunc *get_trait_item ();
 
   TyTy::FnType *get_context_type ();
 
@@ -79,13 +59,9 @@ private:
     std::pair<HIR::ImplBlock *, HIR::Function *> impl_item;
     HIR::TraitItemFunc *trait_item;
 
-    Item (HIR::Function *item) : item (item) {}
-
-    Item (HIR::ImplBlock *impl_block, HIR::Function *item)
-      : impl_item ({impl_block, item})
-    {}
-
-    Item (HIR::TraitItemFunc *trait_item) : trait_item (trait_item) {}
+    Item (HIR::Function *item);
+    Item (HIR::ImplBlock *impl_block, HIR::Function *item);
+    Item (HIR::TraitItemFunc *trait_item);
   };
 
   ItemType type;
@@ -118,283 +94,71 @@ public:
   void push_return_type (TypeCheckContextItem item,
 			 TyTy::BaseType *return_type);
   void pop_return_type ();
+  void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
 
-  void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
-  {
-    for (auto it = resolved.begin (); it != resolved.end (); it++)
-      {
-	if (!cb (it->first, it->second))
-	  return;
-      }
-  }
-
-  bool have_loop_context () const { return !loop_type_stack.empty (); }
-
-  void push_new_loop_context (HirId id, Location locus)
-  {
-    TyTy::BaseType *infer_var
-      = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
-			     locus);
-    loop_type_stack.push_back (infer_var);
-  }
-
-  void push_new_while_loop_context (HirId id)
-  {
-    TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
-    loop_type_stack.push_back (infer_var);
-  }
-
-  TyTy::BaseType *peek_loop_context () { return loop_type_stack.back (); }
-
-  TyTy::BaseType *pop_loop_context ()
-  {
-    auto back = peek_loop_context ();
-    loop_type_stack.pop_back ();
-    return back;
-  }
-
-  void swap_head_loop_context (TyTy::BaseType *val)
-  {
-    loop_type_stack.pop_back ();
-    loop_type_stack.push_back (val);
-  }
-
-  void insert_trait_reference (DefId id, TraitReference &&ref)
-  {
-    rust_assert (trait_context.find (id) == trait_context.end ());
-    trait_context.emplace (id, std::move (ref));
-  }
-
-  bool lookup_trait_reference (DefId id, TraitReference **ref)
-  {
-    auto it = trait_context.find (id);
-    if (it == trait_context.end ())
-      return false;
+  bool have_loop_context () const;
+  void push_new_loop_context (HirId id, Location locus);
+  void push_new_while_loop_context (HirId id);
+  TyTy::BaseType *peek_loop_context ();
+  TyTy::BaseType *pop_loop_context ();
 
-    *ref = &it->second;
-    return true;
-  }
-
-  void insert_receiver (HirId id, TyTy::BaseType *t)
-  {
-    receiver_context[id] = t;
-  }
+  void swap_head_loop_context (TyTy::BaseType *val);
 
-  bool lookup_receiver (HirId id, TyTy::BaseType **ref)
-  {
-    auto it = receiver_context.find (id);
-    if (it == receiver_context.end ())
-      return false;
+  void insert_trait_reference (DefId id, TraitReference &&ref);
+  bool lookup_trait_reference (DefId id, TraitReference **ref);
 
-    *ref = it->second;
-    return true;
-  }
+  void insert_receiver (HirId id, TyTy::BaseType *t);
+  bool lookup_receiver (HirId id, TyTy::BaseType **ref);
 
-  void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated)
-  {
-    rust_assert (associated_impl_traits.find (id)
-		 == associated_impl_traits.end ());
-    associated_impl_traits.emplace (id, std::move (associated));
-  }
+  void insert_associated_trait_impl (HirId id,
+				     AssociatedImplTrait &&associated);
+  bool lookup_associated_trait_impl (HirId id,
+				     AssociatedImplTrait **associated);
 
-  bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated)
-  {
-    auto it = associated_impl_traits.find (id);
-    if (it == associated_impl_traits.end ())
-      return false;
-
-    *associated = &it->second;
-    return true;
-  }
-
-  void insert_associated_type_mapping (HirId id, HirId mapping)
-  {
-    associated_type_mappings[id] = mapping;
-  }
-
-  void clear_associated_type_mapping (HirId id)
-  {
-    auto it = associated_type_mappings.find (id);
-    if (it != associated_type_mappings.end ())
-      associated_type_mappings.erase (it);
-  }
+  void insert_associated_type_mapping (HirId id, HirId mapping);
+  void clear_associated_type_mapping (HirId id);
 
   // lookup any associated type mappings, the out parameter of mapping is
   // allowed to be nullptr which allows this interface to do a simple does exist
   // check
-  bool lookup_associated_type_mapping (HirId id, HirId *mapping)
-  {
-    auto it = associated_type_mappings.find (id);
-    if (it == associated_type_mappings.end ())
-      return false;
-
-    if (mapping != nullptr)
-      *mapping = it->second;
-
-    return true;
-  }
+  bool lookup_associated_type_mapping (HirId id, HirId *mapping);
 
   void insert_associated_impl_mapping (HirId trait_id,
 				       const TyTy::BaseType *impl_type,
-				       HirId impl_id)
-  {
-    auto it = associated_traits_to_impls.find (trait_id);
-    if (it == associated_traits_to_impls.end ())
-      {
-	associated_traits_to_impls[trait_id] = {};
-      }
-
-    associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
-  }
-
+				       HirId impl_id);
   bool lookup_associated_impl_mapping_for_self (HirId trait_id,
 						const TyTy::BaseType *self,
-						HirId *mapping)
-  {
-    auto it = associated_traits_to_impls.find (trait_id);
-    if (it == associated_traits_to_impls.end ())
-      return false;
-
-    for (auto &item : it->second)
-      {
-	if (item.first->can_eq (self, false))
-	  {
-	    *mapping = item.second;
-	    return true;
-	  }
-      }
-    return false;
-  }
+						HirId *mapping);
 
   void insert_autoderef_mappings (HirId id,
-				  std::vector<Adjustment> &&adjustments)
-  {
-    rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
-    autoderef_mappings.emplace (id, std::move (adjustments));
-  }
-
+				  std::vector<Adjustment> &&adjustments);
   bool lookup_autoderef_mappings (HirId id,
-				  std::vector<Adjustment> **adjustments)
-  {
-    auto it = autoderef_mappings.find (id);
-    if (it == autoderef_mappings.end ())
-      return false;
-
-    *adjustments = &it->second;
-    return true;
-  }
+				  std::vector<Adjustment> **adjustments);
 
   void insert_cast_autoderef_mappings (HirId id,
-				       std::vector<Adjustment> &&adjustments)
-  {
-    rust_assert (cast_autoderef_mappings.find (id)
-		 == cast_autoderef_mappings.end ());
-    cast_autoderef_mappings.emplace (id, std::move (adjustments));
-  }
-
+				       std::vector<Adjustment> &&adjustments);
   bool lookup_cast_autoderef_mappings (HirId id,
-				       std::vector<Adjustment> **adjustments)
-  {
-    auto it = cast_autoderef_mappings.find (id);
-    if (it == cast_autoderef_mappings.end ())
-      return false;
+				       std::vector<Adjustment> **adjustments);
 
-    *adjustments = &it->second;
-    return true;
-  }
+  void insert_variant_definition (HirId id, HirId variant);
+  bool lookup_variant_definition (HirId id, HirId *variant);
 
-  void insert_variant_definition (HirId id, HirId variant)
-  {
-    auto it = variants.find (id);
-    rust_assert (it == variants.end ());
+  void insert_operator_overload (HirId id, TyTy::FnType *call_site);
+  bool lookup_operator_overload (HirId id, TyTy::FnType **call);
 
-    variants[id] = variant;
-  }
+  void insert_unconstrained_check_marker (HirId id, bool status);
+  bool have_checked_for_unconstrained (HirId id, bool *result);
 
-  bool lookup_variant_definition (HirId id, HirId *variant)
-  {
-    auto it = variants.find (id);
-    if (it == variants.end ())
-      return false;
+  void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate);
+  bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result);
 
-    *variant = it->second;
-    return true;
-  }
-
-  void insert_operator_overload (HirId id, TyTy::FnType *call_site)
-  {
-    auto it = operator_overloads.find (id);
-    rust_assert (it == operator_overloads.end ());
-
-    operator_overloads[id] = call_site;
-  }
-
-  bool lookup_operator_overload (HirId id, TyTy::FnType **call)
-  {
-    auto it = operator_overloads.find (id);
-    if (it == operator_overloads.end ())
-      return false;
-
-    *call = it->second;
-    return true;
-  }
+  void insert_query (HirId id);
+  void query_completed (HirId id);
+  bool query_in_progress (HirId id) const;
 
-  void insert_unconstrained_check_marker (HirId id, bool status)
-  {
-    unconstrained[id] = status;
-  }
-
-  bool have_checked_for_unconstrained (HirId id, bool *result)
-  {
-    auto it = unconstrained.find (id);
-    bool found = it != unconstrained.end ();
-    if (!found)
-      return false;
-
-    *result = it->second;
-    return true;
-  }
-
-  void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate)
-  {
-    auto it = predicates.find (id);
-    rust_assert (it == predicates.end ());
-
-    predicates.insert ({id, predicate});
-  }
-
-  bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
-  {
-    auto it = predicates.find (id);
-    bool found = it != predicates.end ();
-    if (!found)
-      return false;
-
-    *result = it->second;
-    return true;
-  }
-
-  void insert_query (HirId id) { querys_in_progress.insert (id); }
-
-  void query_completed (HirId id) { querys_in_progress.erase (id); }
-
-  bool query_in_progress (HirId id) const
-  {
-    return querys_in_progress.find (id) != querys_in_progress.end ();
-  }
-
-  void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); }
-
-  void trait_query_completed (DefId id)
-  {
-    trait_queries_in_progress.erase (id);
-  }
-
-  bool trait_query_in_progress (DefId id) const
-  {
-    return trait_queries_in_progress.find (id)
-	   != trait_queries_in_progress.end ();
-  }
+  void insert_trait_query (DefId id);
+  void trait_query_completed (DefId id);
+  bool trait_query_in_progress (DefId id) const;
 
 private:
   TypeCheckContext ();
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
index 886842b0623..27ff96986dc 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -154,8 +154,387 @@ TypeCheckContext::peek_context ()
   return return_type_stack.back ().first;
 }
 
+void
+TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
+{
+  for (auto it = resolved.begin (); it != resolved.end (); it++)
+    {
+      if (!cb (it->first, it->second))
+	return;
+    }
+}
+
+bool
+TypeCheckContext::have_loop_context () const
+{
+  return !loop_type_stack.empty ();
+}
+
+void
+TypeCheckContext::push_new_loop_context (HirId id, Location locus)
+{
+  TyTy::BaseType *infer_var
+    = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus);
+  loop_type_stack.push_back (infer_var);
+}
+
+void
+TypeCheckContext::push_new_while_loop_context (HirId id)
+{
+  TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
+  loop_type_stack.push_back (infer_var);
+}
+
+TyTy::BaseType *
+TypeCheckContext::peek_loop_context ()
+{
+  return loop_type_stack.back ();
+}
+
+TyTy::BaseType *
+TypeCheckContext::pop_loop_context ()
+{
+  auto back = peek_loop_context ();
+  loop_type_stack.pop_back ();
+  return back;
+}
+
+void
+TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
+{
+  loop_type_stack.pop_back ();
+  loop_type_stack.push_back (val);
+}
+
+void
+TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref)
+{
+  rust_assert (trait_context.find (id) == trait_context.end ());
+  trait_context.emplace (id, std::move (ref));
+}
+
+bool
+TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref)
+{
+  auto it = trait_context.find (id);
+  if (it == trait_context.end ())
+    return false;
+
+  *ref = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t)
+{
+  receiver_context[id] = t;
+}
+
+bool
+TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref)
+{
+  auto it = receiver_context.find (id);
+  if (it == receiver_context.end ())
+    return false;
+
+  *ref = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_associated_trait_impl (
+  HirId id, AssociatedImplTrait &&associated)
+{
+  rust_assert (associated_impl_traits.find (id)
+	       == associated_impl_traits.end ());
+  associated_impl_traits.emplace (id, std::move (associated));
+}
+
+bool
+TypeCheckContext::lookup_associated_trait_impl (
+  HirId id, AssociatedImplTrait **associated)
+{
+  auto it = associated_impl_traits.find (id);
+  if (it == associated_impl_traits.end ())
+    return false;
+
+  *associated = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping)
+{
+  associated_type_mappings[id] = mapping;
+}
+
+void
+TypeCheckContext::clear_associated_type_mapping (HirId id)
+{
+  auto it = associated_type_mappings.find (id);
+  if (it != associated_type_mappings.end ())
+    associated_type_mappings.erase (it);
+}
+
+// lookup any associated type mappings, the out parameter of mapping is
+// allowed to be nullptr which allows this interface to do a simple does exist
+// check
+bool
+TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
+{
+  auto it = associated_type_mappings.find (id);
+  if (it == associated_type_mappings.end ())
+    return false;
+
+  if (mapping != nullptr)
+    *mapping = it->second;
+
+  return true;
+}
+
+void
+TypeCheckContext::insert_associated_impl_mapping (
+  HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
+{
+  auto it = associated_traits_to_impls.find (trait_id);
+  if (it == associated_traits_to_impls.end ())
+    {
+      associated_traits_to_impls[trait_id] = {};
+    }
+
+  associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
+}
+
+bool
+TypeCheckContext::lookup_associated_impl_mapping_for_self (
+  HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
+{
+  auto it = associated_traits_to_impls.find (trait_id);
+  if (it == associated_traits_to_impls.end ())
+    return false;
+
+  for (auto &item : it->second)
+    {
+      if (item.first->can_eq (self, false))
+	{
+	  *mapping = item.second;
+	  return true;
+	}
+    }
+  return false;
+}
+
+void
+TypeCheckContext::insert_autoderef_mappings (
+  HirId id, std::vector<Adjustment> &&adjustments)
+{
+  rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
+  autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_autoderef_mappings (
+  HirId id, std::vector<Adjustment> **adjustments)
+{
+  auto it = autoderef_mappings.find (id);
+  if (it == autoderef_mappings.end ())
+    return false;
+
+  *adjustments = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_cast_autoderef_mappings (
+  HirId id, std::vector<Adjustment> &&adjustments)
+{
+  rust_assert (cast_autoderef_mappings.find (id)
+	       == cast_autoderef_mappings.end ());
+  cast_autoderef_mappings.emplace (id, std::move (adjustments));
+}
+
+bool
+TypeCheckContext::lookup_cast_autoderef_mappings (
+  HirId id, std::vector<Adjustment> **adjustments)
+{
+  auto it = cast_autoderef_mappings.find (id);
+  if (it == cast_autoderef_mappings.end ())
+    return false;
+
+  *adjustments = &it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_variant_definition (HirId id, HirId variant)
+{
+  auto it = variants.find (id);
+  rust_assert (it == variants.end ());
+
+  variants[id] = variant;
+}
+
+bool
+TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant)
+{
+  auto it = variants.find (id);
+  if (it == variants.end ())
+    return false;
+
+  *variant = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site)
+{
+  auto it = operator_overloads.find (id);
+  rust_assert (it == operator_overloads.end ());
+
+  operator_overloads[id] = call_site;
+}
+
+bool
+TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
+{
+  auto it = operator_overloads.find (id);
+  if (it == operator_overloads.end ())
+    return false;
+
+  *call = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
+{
+  unconstrained[id] = status;
+}
+
+bool
+TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result)
+{
+  auto it = unconstrained.find (id);
+  bool found = it != unconstrained.end ();
+  if (!found)
+    return false;
+
+  *result = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_resolved_predicate (HirId id,
+					     TyTy::TypeBoundPredicate predicate)
+{
+  auto it = predicates.find (id);
+  rust_assert (it == predicates.end ());
+
+  predicates.insert ({id, predicate});
+}
+
+bool
+TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
+{
+  auto it = predicates.find (id);
+  bool found = it != predicates.end ();
+  if (!found)
+    return false;
+
+  *result = it->second;
+  return true;
+}
+
+void
+TypeCheckContext::insert_query (HirId id)
+{
+  querys_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::query_completed (HirId id)
+{
+  querys_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::query_in_progress (HirId id) const
+{
+  return querys_in_progress.find (id) != querys_in_progress.end ();
+}
+
+void
+TypeCheckContext::insert_trait_query (DefId id)
+{
+  trait_queries_in_progress.insert (id);
+}
+
+void
+TypeCheckContext::trait_query_completed (DefId id)
+{
+  trait_queries_in_progress.erase (id);
+}
+
+bool
+TypeCheckContext::trait_query_in_progress (DefId id) const
+{
+  return trait_queries_in_progress.find (id)
+	 != trait_queries_in_progress.end ();
+}
+
 // TypeCheckContextItem
 
+TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {}
+
+TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block,
+				  HIR::Function *item)
+  : impl_item ({impl_block, item})
+{}
+
+TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item)
+  : trait_item (trait_item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item)
+  : type (ItemType::ITEM), item (item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block,
+					    HIR::Function *item)
+  : type (ItemType::IMPL_ITEM), item (impl_block, item)
+{}
+
+TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
+  : type (ItemType::TRAIT_ITEM), item (trait_item)
+{}
+
+HIR::Function *
+TypeCheckContextItem::get_item ()
+{
+  rust_assert (get_type () == ItemType::ITEM);
+  return item.item;
+}
+
+std::pair<HIR::ImplBlock *, HIR::Function *> &
+TypeCheckContextItem::get_impl_item ()
+{
+  rust_assert (get_type () == ItemType::IMPL_ITEM);
+  return item.impl_item;
+}
+
+HIR::TraitItemFunc *
+TypeCheckContextItem::get_trait_item ()
+{
+  rust_assert (get_type () == ItemType::TRAIT_ITEM);
+  return item.trait_item;
+}
+
+TypeCheckContextItem::ItemType
+TypeCheckContextItem::get_type () const
+{
+  return type;
+}
+
 TyTy::FnType *
 TypeCheckContextItem::get_context_type ()
 {
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 079055e870d..61c02a85c53 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -17,17 +17,22 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-tyty-call.h"
+
 #include "rust-hir-type-check-expr.h"
 #include "rust-hir-type-check-type.h"
-#include "rust-tyty-rules.h"
-#include "rust-tyty-cmp.h"
+#include "rust-tyty-visitor.h"
+#include "rust-tyty-call.h"
 #include "rust-hir-map.h"
+#include "rust-location.h"
+#include "rust-linemap.h"
+
 #include "rust-substitution-mapper.h"
 #include "rust-hir-trait-ref.h"
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
+#include "rust-tyty-rules.h"
+#include "rust-tyty-cmp.h"
+
 #include "options.h"
 
 namespace Rust {
@@ -658,6 +663,53 @@ ErrorType::monomorphized_clone () const
 
 // Struct Field type
 
+StructFieldType::StructFieldType (HirId ref, std::string name, BaseType *ty,
+				  Location locus)
+  : ref (ref), name (name), ty (ty), locus (locus)
+{}
+
+HirId
+StructFieldType::get_ref () const
+{
+  return ref;
+}
+
+std::string
+StructFieldType::get_name () const
+{
+  return name;
+}
+
+BaseType *
+StructFieldType::get_field_type () const
+{
+  return ty;
+}
+
+void
+StructFieldType::set_field_type (BaseType *fty)
+{
+  ty = fty;
+}
+
+bool
+StructFieldType::is_concrete () const
+{
+  return ty->is_concrete ();
+}
+
+void
+StructFieldType::debug () const
+{
+  rust_debug ("%s", as_string ().c_str ());
+}
+
+Location
+StructFieldType::get_locus () const
+{
+  return locus;
+}
+
 std::string
 StructFieldType::as_string () const
 {
@@ -695,6 +747,241 @@ StructFieldType::monomorphized_clone () const
 			      get_field_type ()->monomorphized_clone (), locus);
 }
 
+// VariantDef
+
+std::string
+VariantDef::variant_type_string (VariantType type)
+{
+  switch (type)
+    {
+    case NUM:
+      return "enumeral";
+    case TUPLE:
+      return "tuple";
+    case STRUCT:
+      return "struct";
+    }
+  gcc_unreachable ();
+  return "";
+}
+
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+			RustIdent ident, HIR::Expr *discriminant)
+  : id (id), defid (defid), identifier (identifier), ident (ident),
+    discriminant (discriminant)
+
+{
+  type = VariantType::NUM;
+  fields = {};
+}
+
+VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
+			RustIdent ident, VariantType type,
+			HIR::Expr *discriminant,
+			std::vector<StructFieldType *> fields)
+  : id (id), defid (defid), identifier (identifier), ident (ident), type (type),
+    discriminant (discriminant), fields (fields)
+{
+  rust_assert ((type == VariantType::NUM && fields.empty ())
+	       || (type == VariantType::TUPLE || type == VariantType::STRUCT));
+}
+
+VariantDef::VariantDef (const VariantDef &other)
+  : id (other.id), defid (other.defid), identifier (other.identifier),
+    ident (other.ident), type (other.type), discriminant (other.discriminant),
+    fields (other.fields)
+{}
+
+VariantDef &
+VariantDef::operator= (const VariantDef &other)
+{
+  id = other.id;
+  identifier = other.identifier;
+  type = other.type;
+  discriminant = other.discriminant;
+  fields = other.fields;
+  ident = other.ident;
+
+  return *this;
+}
+
+VariantDef &
+VariantDef::get_error_node ()
+{
+  static VariantDef node
+    = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
+		  {Resolver::CanonicalPath::create_empty (),
+		   Linemap::unknown_location ()},
+		  nullptr);
+
+  return node;
+}
+
+bool
+VariantDef::is_error () const
+{
+  return get_id () == UNKNOWN_HIRID;
+}
+
+HirId
+VariantDef::get_id () const
+{
+  return id;
+}
+
+DefId
+VariantDef::get_defid () const
+{
+  return defid;
+}
+
+VariantDef::VariantType
+VariantDef::get_variant_type () const
+{
+  return type;
+}
+
+bool
+VariantDef::is_data_variant () const
+{
+  return type != VariantType::NUM;
+}
+
+bool
+VariantDef::is_dataless_variant () const
+{
+  return type == VariantType::NUM;
+}
+
+std::string
+VariantDef::get_identifier () const
+{
+  return identifier;
+}
+
+size_t
+VariantDef::num_fields () const
+{
+  return fields.size ();
+}
+
+StructFieldType *
+VariantDef::get_field_at_index (size_t index)
+{
+  rust_assert (index < fields.size ());
+  return fields.at (index);
+}
+
+std::vector<StructFieldType *> &
+VariantDef::get_fields ()
+{
+  rust_assert (type != NUM);
+  return fields;
+}
+
+bool
+VariantDef::lookup_field (const std::string &lookup,
+			  StructFieldType **field_lookup, size_t *index) const
+{
+  size_t i = 0;
+  for (auto &field : fields)
+    {
+      if (field->get_name ().compare (lookup) == 0)
+	{
+	  if (index != nullptr)
+	    *index = i;
+
+	  if (field_lookup != nullptr)
+	    *field_lookup = field;
+
+	  return true;
+	}
+      i++;
+    }
+  return false;
+}
+
+HIR::Expr *
+VariantDef::get_discriminant () const
+{
+  rust_assert (discriminant != nullptr);
+  return discriminant;
+}
+
+std::string
+VariantDef::as_string () const
+{
+  if (type == VariantType::NUM)
+    return identifier + " = " + discriminant->as_string ();
+
+  std::string buffer;
+  for (size_t i = 0; i < fields.size (); ++i)
+    {
+      buffer += fields.at (i)->as_string ();
+      if ((i + 1) < fields.size ())
+	buffer += ", ";
+    }
+
+  if (type == VariantType::TUPLE)
+    return identifier + " (" + buffer + ")";
+  else
+    return identifier + " {" + buffer + "}";
+}
+
+bool
+VariantDef::is_equal (const VariantDef &other) const
+{
+  if (type != other.type)
+    return false;
+
+  if (identifier.compare (other.identifier) != 0)
+    return false;
+
+  if (discriminant != other.discriminant)
+    return false;
+
+  if (fields.size () != other.fields.size ())
+    return false;
+
+  for (size_t i = 0; i < fields.size (); i++)
+    {
+      if (!fields.at (i)->is_equal (*other.fields.at (i)))
+	return false;
+    }
+
+  return true;
+}
+
+VariantDef *
+VariantDef::clone () const
+{
+  std::vector<StructFieldType *> cloned_fields;
+  for (auto &f : fields)
+    cloned_fields.push_back ((StructFieldType *) f->clone ());
+
+  return new VariantDef (id, defid, identifier, ident, type, discriminant,
+			 cloned_fields);
+}
+
+VariantDef *
+VariantDef::monomorphized_clone () const
+{
+  std::vector<StructFieldType *> cloned_fields;
+  for (auto &f : fields)
+    cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
+
+  return new VariantDef (id, defid, identifier, ident, type, discriminant,
+			 cloned_fields);
+}
+
+const RustIdent &
+VariantDef::get_ident () const
+{
+  return ident;
+}
+
+// ADTType
+
 void
 ADTType::accept_vis (TyVisitor &vis)
 {
@@ -892,6 +1179,57 @@ ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
   return adt;
 }
 
+// TupleType
+
+TupleType::TupleType (HirId ref, Location locus, std::vector<TyVar> fields,
+		      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::TUPLE,
+	      {Resolver::CanonicalPath::create_empty (), locus}, refs),
+    fields (fields)
+{}
+
+TupleType::TupleType (HirId ref, HirId ty_ref, Location locus,
+		      std::vector<TyVar> fields, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::TUPLE,
+	      {Resolver::CanonicalPath::create_empty (), locus}, refs),
+    fields (fields)
+{}
+
+TupleType *
+TupleType::get_unit_type (HirId ref)
+{
+  return new TupleType (ref, Linemap::predeclared_location ());
+}
+
+bool
+TupleType::is_unit () const
+{
+  return this->fields.empty ();
+}
+
+size_t
+TupleType::num_fields () const
+{
+  return fields.size ();
+}
+
+bool
+TupleType::is_concrete () const
+{
+  for (size_t i = 0; i < num_fields (); i++)
+    {
+      if (!get_field (i)->is_concrete ())
+	return false;
+    }
+  return true;
+}
+
+const std::vector<TyVar> &
+TupleType::get_fields () const
+{
+  return fields;
+}
+
 void
 TupleType::accept_vis (TyVisitor &vis)
 {
@@ -1622,6 +1960,34 @@ SliceType::handle_substitions (SubstitutionArgumentMappings mappings)
   return ref;
 }
 
+// BoolType
+
+BoolType::BoolType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::BOOL,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+BoolType::BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::BOOL,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+BoolType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+BoolType::is_concrete () const
+{
+  return true;
+}
+
 void
 BoolType::accept_vis (TyVisitor &vis)
 {
@@ -1666,6 +2032,36 @@ BoolType::monomorphized_clone () const
   return clone ();
 }
 
+// IntType
+
+IntType::IntType (HirId ref, IntKind kind, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::INT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    int_kind (kind)
+{}
+
+IntType::IntType (HirId ref, HirId ty_ref, IntKind kind, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::INT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    int_kind (kind)
+{}
+
+std::string
+IntType::get_name () const
+{
+  return as_string ();
+}
+
+IntType::IntKind
+IntType::get_int_kind () const
+{
+  return int_kind;
+}
+
 void
 IntType::accept_vis (TyVisitor &vis)
 {
@@ -1735,6 +2131,43 @@ IntType::is_equal (const BaseType &other) const
   return get_int_kind () == o.get_int_kind ();
 }
 
+bool
+IntType::is_concrete () const
+{
+  return true;
+}
+
+// UintType
+
+UintType::UintType (HirId ref, UintKind kind, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::UINT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    uint_kind (kind)
+{}
+
+UintType::UintType (HirId ref, HirId ty_ref, UintKind kind,
+		    std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::UINT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    uint_kind (kind)
+{}
+
+std::string
+UintType::get_name () const
+{
+  return as_string ();
+}
+
+UintType::UintKind
+UintType::get_uint_kind () const
+{
+  return uint_kind;
+}
+
 void
 UintType::accept_vis (TyVisitor &vis)
 {
@@ -1804,6 +2237,49 @@ UintType::is_equal (const BaseType &other) const
   return get_uint_kind () == o.get_uint_kind ();
 }
 
+bool
+UintType::is_concrete () const
+{
+  return true;
+}
+
+// FloatType
+
+FloatType::FloatType (HirId ref, FloatKind kind, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::FLOAT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    float_kind (kind)
+{}
+
+FloatType::FloatType (HirId ref, HirId ty_ref, FloatKind kind,
+		      std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::FLOAT,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    float_kind (kind)
+{}
+
+std::string
+FloatType::get_name () const
+{
+  return as_string ();
+}
+
+FloatType::FloatKind
+FloatType::get_float_kind () const
+{
+  return float_kind;
+}
+
+bool
+FloatType::is_concrete () const
+{
+  return true;
+}
+
 void
 FloatType::accept_vis (TyVisitor &vis)
 {
@@ -1867,6 +2343,34 @@ FloatType::is_equal (const BaseType &other) const
   return get_float_kind () == o.get_float_kind ();
 }
 
+// UsizeType
+
+USizeType::USizeType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::USIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+USizeType::USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::USIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+USizeType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+USizeType::is_concrete () const
+{
+  return true;
+}
+
 void
 USizeType::accept_vis (TyVisitor &vis)
 {
@@ -1911,6 +2415,34 @@ USizeType::monomorphized_clone () const
   return clone ();
 }
 
+// ISizeType
+
+ISizeType::ISizeType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::ISIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+ISizeType::ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::ISIZE,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+ISizeType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+ISizeType::is_concrete () const
+{
+  return true;
+}
+
 void
 ISizeType::accept_vis (TyVisitor &vis)
 {
@@ -1955,6 +2487,34 @@ ISizeType::monomorphized_clone () const
   return clone ();
 }
 
+// Char Type
+
+CharType::CharType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::CHAR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+CharType::CharType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::CHAR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+bool
+CharType::is_concrete () const
+{
+  return true;
+}
+
+std::string
+CharType::get_name () const
+{
+  return as_string ();
+}
+
 void
 CharType::accept_vis (TyVisitor &vis)
 {
@@ -1999,6 +2559,76 @@ CharType::monomorphized_clone () const
   return clone ();
 }
 
+// Reference Type
+
+ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut,
+			      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::REF,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+ReferenceType::ReferenceType (HirId ref, HirId ty_ref, TyVar base,
+			      Mutability mut, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::REF,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+bool
+ReferenceType::is_concrete () const
+{
+  return get_base ()->is_concrete ();
+}
+
+Mutability
+ReferenceType::mutability () const
+{
+  return mut;
+}
+
+bool
+ReferenceType::is_mutable () const
+{
+  return mut == Mutability::Mut;
+}
+
+bool
+ReferenceType::is_dyn_object () const
+{
+  return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+ReferenceType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::SLICE)
+    return false;
+  if (slice == nullptr)
+    return true;
+
+  *slice = static_cast<const TyTy::SliceType *> (element);
+  return true;
+}
+
+bool
+ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::STR)
+    return false;
+  if (str == nullptr)
+    return true;
+
+  *str = static_cast<const TyTy::StrType *> (element);
+  return true;
+}
+
 void
 ReferenceType::accept_vis (TyVisitor &vis)
 {
@@ -2089,6 +2719,82 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings)
   return ref;
 }
 
+// PointerType
+
+PointerType::PointerType (HirId ref, TyVar base, Mutability mut,
+			  std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::POINTER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+PointerType::PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
+			  std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::POINTER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    base (base), mut (mut)
+{}
+
+bool
+PointerType::is_concrete () const
+{
+  return get_base ()->is_concrete ();
+}
+
+Mutability
+PointerType::mutability () const
+{
+  return mut;
+}
+
+bool
+PointerType::is_mutable () const
+{
+  return mut == Mutability::Mut;
+}
+
+bool
+PointerType::is_const () const
+{
+  return mut == Mutability::Imm;
+}
+
+bool
+PointerType::is_dyn_object () const
+{
+  return is_dyn_slice_type () || is_dyn_str_type ();
+}
+
+bool
+PointerType::is_dyn_slice_type (const TyTy::SliceType **slice) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::SLICE)
+    return false;
+  if (slice == nullptr)
+    return true;
+
+  *slice = static_cast<const TyTy::SliceType *> (element);
+  return true;
+}
+
+bool
+PointerType::is_dyn_str_type (const TyTy::StrType **str) const
+{
+  const TyTy::BaseType *element = get_base ()->destructure ();
+  if (element->get_kind () != TyTy::TypeKind::STR)
+    return false;
+  if (str == nullptr)
+    return true;
+
+  *str = static_cast<const TyTy::StrType *> (element);
+  return true;
+}
+
 void
 PointerType::accept_vis (TyVisitor &vis)
 {
@@ -2179,6 +2885,52 @@ PointerType::handle_substitions (SubstitutionArgumentMappings mappings)
   return ref;
 }
 
+// PARAM Type
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+		      HIR::GenericParam &param,
+		      std::vector<TypeBoundPredicate> specified_bounds,
+		      std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::PARAM,
+	      {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+	       locus},
+	      specified_bounds, refs),
+    symbol (symbol), param (param)
+{}
+
+ParamType::ParamType (std::string symbol, Location locus, HirId ref,
+		      HirId ty_ref, HIR::GenericParam &param,
+		      std::vector<TypeBoundPredicate> specified_bounds,
+		      std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::PARAM,
+	      {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+	       locus},
+	      specified_bounds, refs),
+    symbol (symbol), param (param)
+{}
+
+HIR::GenericParam &
+ParamType::get_generic_param ()
+{
+  return param;
+}
+
+bool
+ParamType::can_resolve () const
+{
+  return get_ref () != get_ty_ref ();
+}
+
+bool
+ParamType::is_concrete () const
+{
+  auto r = resolve ();
+  if (r == this)
+    return false;
+
+  return r->is_concrete ();
+}
+
 void
 ParamType::accept_vis (TyVisitor &vis)
 {
@@ -2320,6 +3072,34 @@ ParamType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
   return p;
 }
 
+// StrType
+
+StrType::StrType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::STR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+StrType::StrType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::STR,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+StrType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+StrType::is_concrete () const
+{
+  return true;
+}
+
 BaseType *
 StrType::clone () const
 {
@@ -2370,6 +3150,40 @@ StrType::is_equal (const BaseType &other) const
   return get_kind () == other.get_kind ();
 }
 
+// Never Type
+
+NeverType::NeverType (HirId ref, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::NEVER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+NeverType::NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::NEVER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs)
+{}
+
+std::string
+NeverType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+NeverType::is_unit () const
+{
+  return true;
+}
+
+bool
+NeverType::is_concrete () const
+{
+  return true;
+}
+
 void
 NeverType::accept_vis (TyVisitor &vis)
 {
@@ -2416,6 +3230,52 @@ NeverType::monomorphized_clone () const
 
 // placeholder type
 
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
+				  std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::PLACEHOLDER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    symbol (symbol)
+{}
+
+PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
+				  std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    symbol (symbol)
+{}
+
+std::string
+PlaceholderType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+PlaceholderType::is_unit () const
+{
+  rust_assert (can_resolve ());
+  return resolve ()->is_unit ();
+}
+
+std::string
+PlaceholderType::get_symbol () const
+{
+  return symbol;
+}
+
+bool
+PlaceholderType::is_concrete () const
+{
+  if (!can_resolve ())
+    return true;
+
+  return resolve ()->is_concrete ();
+}
+
 void
 PlaceholderType::accept_vis (TyVisitor &vis)
 {
@@ -2515,6 +3375,78 @@ PlaceholderType::is_equal (const BaseType &other) const
 
 // Projection type
 
+ProjectionType::ProjectionType (
+  HirId ref, BaseType *base, const Resolver::TraitReference *trait, DefId item,
+  std::vector<SubstitutionParamMapping> subst_refs,
+  SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::PROJECTION,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+    base (base), trait (trait), item (item)
+{}
+
+ProjectionType::ProjectionType (
+  HirId ref, HirId ty_ref, BaseType *base,
+  const Resolver::TraitReference *trait, DefId item,
+  std::vector<SubstitutionParamMapping> subst_refs,
+  SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::PROJECTION,
+	      {Resolver::CanonicalPath::create_empty (),
+	       Linemap::predeclared_location ()},
+	      refs),
+    SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+    base (base), trait (trait), item (item)
+{}
+
+bool
+ProjectionType::is_unit () const
+{
+  return false;
+}
+
+std::string
+ProjectionType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+ProjectionType::needs_generic_substitutions () const
+{
+  return needs_substitution ();
+}
+
+bool
+ProjectionType::supports_substitutions () const
+{
+  return true;
+}
+
+bool
+ProjectionType::has_subsititions_defined () const
+{
+  return has_substitutions ();
+}
+
+const BaseType *
+ProjectionType::get () const
+{
+  return base;
+}
+BaseType *
+ProjectionType::get ()
+{
+  return base;
+}
+
+bool
+ProjectionType::is_concrete () const
+{
+  return base->is_concrete ();
+}
+
 void
 ProjectionType::accept_vis (TyVisitor &vis)
 {
@@ -2631,6 +3563,26 @@ ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
   return projection;
 }
 
+// DynObjectType
+
+DynamicObjectType::DynamicObjectType (
+  HirId ref, RustIdent ident, std::vector<TypeBoundPredicate> specified_bounds,
+  std::set<HirId> refs)
+  : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+DynamicObjectType::DynamicObjectType (
+  HirId ref, HirId ty_ref, RustIdent ident,
+  std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs)
+  : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+{}
+
+bool
+DynamicObjectType::is_concrete () const
+{
+  return true;
+}
+
 void
 DynamicObjectType::accept_vis (TyVisitor &vis)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 1a6bac3f864..85b3a3b7abc 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -20,11 +20,9 @@
 #define RUST_TYTY
 
 #include "rust-hir-map.h"
-#include "rust-hir-full.h"
-#include "rust-diagnostics.h"
-#include "rust-abi.h"
 #include "rust-common.h"
 #include "rust-identifier.h"
+#include "rust-abi.h"
 #include "rust-tyty-bounds.h"
 #include "rust-tyty-util.h"
 #include "rust-tyty-subst.h"
@@ -274,24 +272,12 @@ public:
   ParamType (std::string symbol, Location locus, HirId ref,
 	     HIR::GenericParam &param,
 	     std::vector<TypeBoundPredicate> specified_bounds,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::PARAM,
-		{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
-		 locus},
-		specified_bounds, refs),
-      symbol (symbol), param (param)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref,
 	     HIR::GenericParam &param,
 	     std::vector<TypeBoundPredicate> specified_bounds,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::PARAM,
-		{Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
-		 locus},
-		specified_bounds, refs),
-      symbol (symbol), param (param)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -306,9 +292,9 @@ public:
 
   std::string get_symbol () const;
 
-  HIR::GenericParam &get_generic_param () { return param; }
+  HIR::GenericParam &get_generic_param ();
 
-  bool can_resolve () const { return get_ref () != get_ty_ref (); }
+  bool can_resolve () const;
 
   BaseType *resolve () const;
 
@@ -316,14 +302,7 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
-  bool is_concrete () const override final
-  {
-    auto r = resolve ();
-    if (r == this)
-      return false;
-
-    return r->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
   ParamType *handle_substitions (SubstitutionArgumentMappings mappings);
 
@@ -335,31 +314,25 @@ private:
 class StructFieldType
 {
 public:
-  StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus)
-    : ref (ref), name (name), ty (ty), locus (locus)
-  {}
-
-  HirId get_ref () const { return ref; }
+  StructFieldType (HirId ref, std::string name, BaseType *ty, Location locus);
 
-  std::string as_string () const;
+  HirId get_ref () const;
 
   bool is_equal (const StructFieldType &other) const;
 
-  std::string get_name () const { return name; }
-
-  BaseType *get_field_type () const { return ty; }
+  std::string get_name () const;
 
-  void set_field_type (BaseType *fty) { ty = fty; }
+  BaseType *get_field_type () const;
+  void set_field_type (BaseType *fty);
 
   StructFieldType *clone () const;
-
   StructFieldType *monomorphized_clone () const;
 
-  bool is_concrete () const { return ty->is_concrete (); }
-
-  void debug () const { rust_debug ("%s", as_string ().c_str ()); }
+  bool is_concrete () const;
 
-  Location get_locus () const { return locus; }
+  void debug () const;
+  Location get_locus () const;
+  std::string as_string () const;
 
 private:
   HirId ref;
@@ -373,29 +346,18 @@ class TupleType : public BaseType
 public:
   TupleType (HirId ref, Location locus,
 	     std::vector<TyVar> fields = std::vector<TyVar> (),
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::TUPLE,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
-      fields (fields)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   TupleType (HirId ref, HirId ty_ref, Location locus,
 	     std::vector<TyVar> fields = std::vector<TyVar> (),
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::TUPLE,
-		{Resolver::CanonicalPath::create_empty (), locus}, refs),
-      fields (fields)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
-  static TupleType *get_unit_type (HirId ref)
-  {
-    return new TupleType (ref, Linemap::predeclared_location ());
-  }
+  static TupleType *get_unit_type (HirId ref);
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
-  bool is_unit () const override { return this->fields.empty (); }
+  bool is_unit () const override;
 
   std::string as_string () const override;
 
@@ -404,24 +366,16 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
-  size_t num_fields () const { return fields.size (); }
+  size_t num_fields () const;
 
   BaseType *get_field (size_t index) const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  bool is_concrete () const override final
-  {
-    for (size_t i = 0; i < num_fields (); i++)
-      {
-	if (!get_field (i)->is_concrete ())
-	  return false;
-      }
-    return true;
-  }
+  bool is_concrete () const override final;
 
-  const std::vector<TyVar> &get_fields () const { return fields; }
+  const std::vector<TyVar> &get_fields () const;
 
   std::string get_name () const override final;
 
@@ -507,185 +461,48 @@ public:
     STRUCT
   };
 
-  static std::string variant_type_string (VariantType type)
-  {
-    switch (type)
-      {
-      case NUM:
-	return "enumeral";
-      case TUPLE:
-	return "tuple";
-      case STRUCT:
-	return "struct";
-      }
-    gcc_unreachable ();
-    return "";
-  }
+  static std::string variant_type_string (VariantType type);
 
   VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
-	      HIR::Expr *discriminant)
-    : id (id), defid (defid), identifier (identifier), ident (ident),
-      discriminant (discriminant)
-
-  {
-    type = VariantType::NUM;
-    fields = {};
-  }
+	      HIR::Expr *discriminant);
 
   VariantDef (HirId id, DefId defid, std::string identifier, RustIdent ident,
 	      VariantType type, HIR::Expr *discriminant,
-	      std::vector<StructFieldType *> fields)
-    : id (id), defid (defid), identifier (identifier), ident (ident),
-      type (type), discriminant (discriminant), fields (fields)
-  {
-    rust_assert (
-      (type == VariantType::NUM && fields.empty ())
-      || (type == VariantType::TUPLE || type == VariantType::STRUCT));
-  }
+	      std::vector<StructFieldType *> fields);
 
-  VariantDef (const VariantDef &other)
-    : id (other.id), defid (other.defid), identifier (other.identifier),
-      ident (other.ident), type (other.type), discriminant (other.discriminant),
-      fields (other.fields)
-  {}
+  VariantDef (const VariantDef &other);
 
-  VariantDef &operator= (const VariantDef &other)
-  {
-    id = other.id;
-    identifier = other.identifier;
-    type = other.type;
-    discriminant = other.discriminant;
-    fields = other.fields;
-    ident = other.ident;
-
-    return *this;
-  }
+  VariantDef &operator= (const VariantDef &other);
 
-  static VariantDef &get_error_node ()
-  {
-    static VariantDef node
-      = VariantDef (UNKNOWN_HIRID, UNKNOWN_DEFID, "",
-		    {Resolver::CanonicalPath::create_empty (),
-		     Linemap::unknown_location ()},
-		    nullptr);
+  static VariantDef &get_error_node ();
+  bool is_error () const;
 
-    return node;
-  }
+  HirId get_id () const;
+  DefId get_defid () const;
 
-  bool is_error () const { return get_id () == UNKNOWN_HIRID; }
+  VariantType get_variant_type () const;
+  bool is_data_variant () const;
+  bool is_dataless_variant () const;
 
-  HirId get_id () const { return id; }
-  DefId get_defid () const { return defid; }
+  std::string get_identifier () const;
 
-  VariantType get_variant_type () const { return type; }
-  bool is_data_variant () const { return type != VariantType::NUM; }
-  bool is_dataless_variant () const { return type == VariantType::NUM; }
+  size_t num_fields () const;
+  StructFieldType *get_field_at_index (size_t index);
 
-  std::string get_identifier () const { return identifier; }
-
-  size_t num_fields () const { return fields.size (); }
-  StructFieldType *get_field_at_index (size_t index)
-  {
-    rust_assert (index < fields.size ());
-    return fields.at (index);
-  }
-
-  std::vector<StructFieldType *> &get_fields ()
-  {
-    rust_assert (type != NUM);
-    return fields;
-  }
+  std::vector<StructFieldType *> &get_fields ();
 
   bool lookup_field (const std::string &lookup, StructFieldType **field_lookup,
-		     size_t *index) const
-  {
-    size_t i = 0;
-    for (auto &field : fields)
-      {
-	if (field->get_name ().compare (lookup) == 0)
-	  {
-	    if (index != nullptr)
-	      *index = i;
-
-	    if (field_lookup != nullptr)
-	      *field_lookup = field;
-
-	    return true;
-	  }
-	i++;
-      }
-    return false;
-  }
-
-  HIR::Expr *get_discriminant () const
-  {
-    rust_assert (discriminant != nullptr);
-    return discriminant;
-  }
-
-  std::string as_string () const
-  {
-    if (type == VariantType::NUM)
-      return identifier + " = " + discriminant->as_string ();
-
-    std::string buffer;
-    for (size_t i = 0; i < fields.size (); ++i)
-      {
-	buffer += fields.at (i)->as_string ();
-	if ((i + 1) < fields.size ())
-	  buffer += ", ";
-      }
-
-    if (type == VariantType::TUPLE)
-      return identifier + " (" + buffer + ")";
-    else
-      return identifier + " {" + buffer + "}";
-  }
-
-  bool is_equal (const VariantDef &other) const
-  {
-    if (type != other.type)
-      return false;
-
-    if (identifier.compare (other.identifier) != 0)
-      return false;
+		     size_t *index) const;
 
-    if (discriminant != other.discriminant)
-      return false;
-
-    if (fields.size () != other.fields.size ())
-      return false;
-
-    for (size_t i = 0; i < fields.size (); i++)
-      {
-	if (!fields.at (i)->is_equal (*other.fields.at (i)))
-	  return false;
-      }
-
-    return true;
-  }
-
-  VariantDef *clone () const
-  {
-    std::vector<StructFieldType *> cloned_fields;
-    for (auto &f : fields)
-      cloned_fields.push_back ((StructFieldType *) f->clone ());
+  HIR::Expr *get_discriminant () const;
 
-    return new VariantDef (id, defid, identifier, ident, type, discriminant,
-			   cloned_fields);
-  }
+  std::string as_string () const;
 
-  VariantDef *monomorphized_clone () const
-  {
-    std::vector<StructFieldType *> cloned_fields;
-    for (auto &f : fields)
-      cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ());
+  bool is_equal (const VariantDef &other) const;
+  VariantDef *clone () const;
+  VariantDef *monomorphized_clone () const;
 
-    return new VariantDef (id, defid, identifier, ident, type, discriminant,
-			   cloned_fields);
-  }
-
-  const RustIdent &get_ident () const { return ident; }
+  const RustIdent &get_ident () const;
 
 private:
   HirId id;
@@ -1262,33 +1079,22 @@ private:
 class BoolType : public BaseType
 {
 public:
-  BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::BOOL,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::BOOL,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class IntType : public BaseType
@@ -1303,40 +1109,27 @@ public:
     I128
   };
 
-  IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::INT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      int_kind (kind)
-  {}
-
+  IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ());
   IntType (HirId ref, HirId ty_ref, IntKind kind,
-	   std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::INT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      int_kind (kind)
-  {}
+	   std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
-  IntKind get_int_kind () const { return int_kind; }
+  IntKind get_int_kind () const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
   bool is_equal (const BaseType &other) const override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
 private:
   IntKind int_kind;
@@ -1354,40 +1147,28 @@ public:
     U128
   };
 
-  UintType (HirId ref, UintKind kind, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::UINT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      uint_kind (kind)
-  {}
-
+  UintType (HirId ref, UintKind kind,
+	    std::set<HirId> refs = std::set<HirId> ());
   UintType (HirId ref, HirId ty_ref, UintKind kind,
-	    std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::UINT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      uint_kind (kind)
-  {}
+	    std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
-  UintKind get_uint_kind () const { return uint_kind; }
+  UintKind get_uint_kind () const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
   bool is_equal (const BaseType &other) const override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
 private:
   UintKind uint_kind;
@@ -1403,40 +1184,26 @@ public:
   };
 
   FloatType (HirId ref, FloatKind kind,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::FLOAT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      float_kind (kind)
-  {}
-
+	     std::set<HirId> refs = std::set<HirId> ());
   FloatType (HirId ref, HirId ty_ref, FloatKind kind,
-	     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::FLOAT,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      float_kind (kind)
-  {}
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
-  FloatKind get_float_kind () const { return float_kind; }
+  FloatKind get_float_kind () const;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
   bool is_equal (const BaseType &other) const override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
 private:
   FloatKind float_kind;
@@ -1445,117 +1212,72 @@ private:
 class USizeType : public BaseType
 {
 public:
-  USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::USIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::USIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  USizeType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class ISizeType : public BaseType
 {
 public:
-  ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::ISIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::ISIZE,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  ISizeType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class CharType : public BaseType
 {
 public:
-  CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::CHAR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::CHAR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class StrType : public BaseType
 {
 public:
-  StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::STR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::STR,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1569,29 +1291,16 @@ public:
 
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 };
 
 class ReferenceType : public BaseType
 {
 public:
   ReferenceType (HirId ref, TyVar base, Mutability mut,
-		 std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::REF,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
-
+		 std::set<HirId> refs = std::set<HirId> ());
   ReferenceType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
-		 std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::REF,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
+		 std::set<HirId> refs = std::set<HirId> ());
 
   BaseType *get_base () const;
 
@@ -1610,45 +1319,19 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  bool is_concrete () const override final
-  {
-    return get_base ()->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
   ReferenceType *handle_substitions (SubstitutionArgumentMappings mappings);
 
-  Mutability mutability () const { return mut; }
+  Mutability mutability () const;
 
-  bool is_mutable () const { return mut == Mutability::Mut; }
+  bool is_mutable () const;
 
-  bool is_dyn_object () const
-  {
-    return is_dyn_slice_type () || is_dyn_str_type ();
-  }
+  bool is_dyn_object () const;
 
-  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::SLICE)
-      return false;
-    if (slice == nullptr)
-      return true;
+  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
 
-    *slice = static_cast<const TyTy::SliceType *> (element);
-    return true;
-  }
-
-  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::STR)
-      return false;
-    if (str == nullptr)
-      return true;
-
-    *str = static_cast<const TyTy::StrType *> (element);
-    return true;
-  }
+  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
 
 private:
   TyVar base;
@@ -1659,22 +1342,9 @@ class PointerType : public BaseType
 {
 public:
   PointerType (HirId ref, TyVar base, Mutability mut,
-	       std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::POINTER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
-
+	       std::set<HirId> refs = std::set<HirId> ());
   PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
-	       std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::POINTER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      base (base), mut (mut)
-  {}
+	       std::set<HirId> refs = std::set<HirId> ());
 
   BaseType *get_base () const;
 
@@ -1692,47 +1362,17 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  bool is_concrete () const override final
-  {
-    return get_base ()->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
   PointerType *handle_substitions (SubstitutionArgumentMappings mappings);
 
-  Mutability mutability () const { return mut; }
-
-  bool is_mutable () const { return mut == Mutability::Mut; }
-
-  bool is_const () const { return mut == Mutability::Imm; }
-
-  bool is_dyn_object () const
-  {
-    return is_dyn_slice_type () || is_dyn_str_type ();
-  }
-
-  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::SLICE)
-      return false;
-    if (slice == nullptr)
-      return true;
+  Mutability mutability () const;
+  bool is_mutable () const;
+  bool is_const () const;
+  bool is_dyn_object () const;
 
-    *slice = static_cast<const TyTy::SliceType *> (element);
-    return true;
-  }
-
-  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const
-  {
-    const TyTy::BaseType *element = get_base ()->destructure ();
-    if (element->get_kind () != TyTy::TypeKind::STR)
-      return false;
-    if (str == nullptr)
-      return true;
-
-    *str = static_cast<const TyTy::StrType *> (element);
-    return true;
-  }
+  bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
+  bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
 
 private:
   TyVar base;
@@ -1752,19 +1392,9 @@ private:
 class NeverType : public BaseType
 {
 public:
-  NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::NEVER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
-
-  NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::NEVER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs)
-  {}
+  NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+  NeverType (HirId ref, HirId ty_ref,
+	     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1777,10 +1407,10 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_unit () const override { return true; }
-  bool is_concrete () const override final { return true; }
+  bool is_unit () const override;
+  bool is_concrete () const override final;
 };
 
 // used at the type in associated types in traits
@@ -1789,22 +1419,9 @@ class PlaceholderType : public BaseType
 {
 public:
   PlaceholderType (std::string symbol, HirId ref,
-		   std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::PLACEHOLDER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      symbol (symbol)
-  {}
-
+		   std::set<HirId> refs = std::set<HirId> ());
   PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
-		   std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      symbol (symbol)
-  {}
+		   std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1817,15 +1434,11 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_unit () const override
-  {
-    rust_assert (can_resolve ());
-    return resolve ()->is_unit ();
-  }
+  bool is_unit () const override;
 
-  std::string get_symbol () const { return symbol; }
+  std::string get_symbol () const;
 
   void set_associated_type (HirId ref);
 
@@ -1837,13 +1450,7 @@ public:
 
   bool is_equal (const BaseType &other) const override;
 
-  bool is_concrete () const override final
-  {
-    if (!can_resolve ())
-      return true;
-
-    return resolve ()->is_concrete ();
-  }
+  bool is_concrete () const override final;
 
 private:
   std::string symbol;
@@ -1857,28 +1464,14 @@ public:
 		  std::vector<SubstitutionParamMapping> subst_refs,
 		  SubstitutionArgumentMappings generic_arguments
 		  = SubstitutionArgumentMappings::error (),
-		  std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::PROJECTION,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
-      base (base), trait (trait), item (item)
-  {}
+		  std::set<HirId> refs = std::set<HirId> ());
 
   ProjectionType (HirId ref, HirId ty_ref, BaseType *base,
 		  const Resolver::TraitReference *trait, DefId item,
 		  std::vector<SubstitutionParamMapping> subst_refs,
 		  SubstitutionArgumentMappings generic_arguments
 		  = SubstitutionArgumentMappings::error (),
-		  std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::PROJECTION,
-		{Resolver::CanonicalPath::create_empty (),
-		 Linemap::predeclared_location ()},
-		refs),
-      SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
-      base (base), trait (trait), item (item)
-  {}
+		  std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1891,26 +1484,20 @@ public:
   BaseType *clone () const final override;
   BaseType *monomorphized_clone () const final override;
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
-  bool is_unit () const override { return false; }
+  bool is_unit () const override;
 
-  bool needs_generic_substitutions () const override final
-  {
-    return needs_substitution ();
-  }
+  bool needs_generic_substitutions () const override final;
 
-  bool supports_substitutions () const override final { return true; }
+  bool supports_substitutions () const override final;
 
-  bool has_subsititions_defined () const override final
-  {
-    return has_substitutions ();
-  }
+  bool has_subsititions_defined () const override final;
 
-  const BaseType *get () const { return base; }
-  BaseType *get () { return base; }
+  const BaseType *get () const;
+  BaseType *get ();
 
-  bool is_concrete () const override final { return base->is_concrete (); }
+  bool is_concrete () const override final;
 
   ProjectionType *
   handle_substitions (SubstitutionArgumentMappings mappings) override final;
@@ -1926,15 +1513,11 @@ class DynamicObjectType : public BaseType
 public:
   DynamicObjectType (HirId ref, RustIdent ident,
 		     std::vector<TypeBoundPredicate> specified_bounds,
-		     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
-  {}
+		     std::set<HirId> refs = std::set<HirId> ());
 
   DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
 		     std::vector<TypeBoundPredicate> specified_bounds,
-		     std::set<HirId> refs = std::set<HirId> ())
-    : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
-  {}
+		     std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
   void accept_vis (TyConstVisitor &vis) const override;
@@ -1951,7 +1534,7 @@ public:
 
   std::string get_name () const override final;
 
-  bool is_concrete () const override final { return true; }
+  bool is_concrete () const override final;
 
   // this returns a flat list of items including super trait bounds
   const std::vector<
