public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc/devel/rust/master] Refactor TypeResolution to be a simple query based system
Date: Tue, 27 Sep 2022 15:49:58 +0000 (GMT)	[thread overview]
Message-ID: <20220927154958.451063858029@sourceware.org> (raw)

https://gcc.gnu.org/g:96c8baa8a7a8aa796450585c1ba2c1fe2428b6f4

commit 96c8baa8a7a8aa796450585c1ba2c1fe2428b6f4
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Tue Sep 27 11:35:21 2022 +0100

    Refactor TypeResolution to be a simple query based system
    
    This patch refactors the type resolution system to introduce a new
    interface
    
      bool query_type (HirId, TyTy::BaseType** result)
    
    This is needed in order to properly support forward declared items. Our
    name resolution system has two parts:
    
      1. Toplevel scan
      2. Item resolution
    
    The toplevel scan gathers all the nesseacry 'names' into their respective
    namespace by doing a full toplevel scan and generate canonical paths for
    each item. The second pass is responsible for drilling down into each
    structure or function to resolve each field or variable etc. This means
    our name resolution system supports forward decalred items but our type
    resolution system did not.
    
    This patch removes the toplevel scan from our type resolution pass which
    is not able to handle all cases such as a function with return type and
    the type is decalred after the fact or a type alias to a type declared
    after the fact. The name resolution mappings are resolved so when errors
    occured here we got errors such as unable to lookup HirId 1234, which meant
    yes we have 'resolved' this reference to this HirId but we are unable to
    find any type information for it. This means we needed a new way to figure
    out the type in a query based way.
    
    This is where the new query_type inferface comes in so when we have an
    HirId we want to resolve the mappings class allows us to figure out what
    item this is such as:
    
      1. HIR::Item (normal HIR::Function, Struct, TypeAlias, ...)
      2. HIR::ImplItem (function, constant, ... within an impl-block)
      3. HIR::ImplBlock (Self type on an impl-block)
      4. HIR::ExternalItem (extern-block item)
    
    The mappings class allows us to simply lookup these HIR nodes and then
    call the relevant resolver class to compute the type. This patch does not
    add support for self-referencial types but is the starting point to be able to support such types.
    
    Fixes #1455

Diff:
---
 gcc/rust/Make-lang.in                              |   2 +-
 gcc/rust/typecheck/rust-hir-dot-operator.cc        |   8 +-
 gcc/rust/typecheck/rust-hir-dot-operator.h         |   6 +-
 gcc/rust/typecheck/rust-hir-path-probe.cc          |  46 ++
 gcc/rust/typecheck/rust-hir-path-probe.h           |  24 +-
 gcc/rust/typecheck/rust-hir-type-check-base.cc     |  76 +++
 gcc/rust/typecheck/rust-hir-type-check-base.h      |   2 +
 gcc/rust/typecheck/rust-hir-type-check-expr.cc     |   3 +
 gcc/rust/typecheck/rust-hir-type-check-implitem.cc | 181 +++----
 gcc/rust/typecheck/rust-hir-type-check-implitem.h  |  42 +-
 gcc/rust/typecheck/rust-hir-type-check-item.cc     | 554 +++++++++++++++++----
 gcc/rust/typecheck/rust-hir-type-check-item.h      |  47 +-
 gcc/rust/typecheck/rust-hir-type-check-path.cc     |   4 +-
 gcc/rust/typecheck/rust-hir-type-check-stmt.cc     | 387 ++------------
 gcc/rust/typecheck/rust-hir-type-check-stmt.h      |  62 +--
 gcc/rust/typecheck/rust-hir-type-check-toplevel.cc | 378 --------------
 gcc/rust/typecheck/rust-hir-type-check-toplevel.h  |  56 ---
 gcc/rust/typecheck/rust-hir-type-check-type.cc     | 110 ++--
 gcc/rust/typecheck/rust-hir-type-check.cc          |   9 +-
 gcc/rust/typecheck/rust-hir-type-check.h           |  41 ++
 gcc/rust/typecheck/rust-substitution-mapper.h      |   2 +-
 gcc/rust/typecheck/rust-tyty-bounds.cc             |  24 +-
 gcc/rust/typecheck/rust-tyty-cmp.h                 |   2 +
 gcc/rust/typecheck/rust-tyty.cc                    |  45 +-
 gcc/rust/typecheck/rust-tyty.h                     |  34 +-
 gcc/rust/util/rust-hir-map.cc                      |  13 +
 gcc/rust/util/rust-hir-map.h                       |   2 +
 gcc/testsuite/rust/compile/const_generics_5.rs     |  13 +-
 .../rust/compile/unconstrained_type_param.rs       |   2 +
 29 files changed, 952 insertions(+), 1223 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index f687cc2f667..5996696e425 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -111,7 +111,6 @@ GRS_OBJS = \
     rust/rust-tyty-bounds.o \
     rust/rust-hir-type-check-util.o \
     rust/rust-hir-trait-resolve.o \
-    rust/rust-hir-type-check-toplevel.o \
     rust/rust-hir-type-check-item.o \
     rust/rust-hir-type-check-type.o \
     rust/rust-hir-type-check-struct.o \
@@ -121,6 +120,7 @@ GRS_OBJS = \
     rust/rust-hir-type-check-enumitem.o \
     rust/rust-hir-type-check-implitem.o \
     rust/rust-hir-dot-operator.o \
+    rust/rust-hir-path-probe.o \
     rust/rust-coercion.o \
     rust/rust-casts.o \
     rust/rust-hir-type-check-base.o \
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 78d36b18c18..1976a5f6a34 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -25,8 +25,7 @@ namespace Resolver {
 
 MethodResolver::MethodResolver (bool autoderef_flag,
 				const HIR::PathIdentSegment &segment_name)
-  : AutoderefCycle (autoderef_flag), mappings (Analysis::Mappings::get ()),
-    context (TypeCheckContext::get ()), segment_name (segment_name),
+  : AutoderefCycle (autoderef_flag), segment_name (segment_name),
     try_result (MethodCandidate::get_error ())
 {}
 
@@ -80,8 +79,9 @@ MethodResolver::select (const TyTy::BaseType &receiver)
 	return true;
 
       TyTy::BaseType *ty = nullptr;
-      if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty))
+      if (!query_type (func->get_mappings ().get_hirid (), &ty))
 	return true;
+      rust_assert (ty != nullptr);
       if (ty->get_kind () == TyTy::TypeKind::ERROR)
 	return true;
 
@@ -127,7 +127,7 @@ MethodResolver::select (const TyTy::BaseType &receiver)
 	  continue;
 
 	TyTy::BaseType *ty = nullptr;
-	if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty))
+	if (!query_type (func->get_mappings ().get_hirid (), &ty))
 	  continue;
 	if (ty->get_kind () == TyTy::TypeKind::ERROR)
 	  continue;
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index 750601a2d9e..054608dc931 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -37,7 +37,7 @@ struct MethodCandidate
   bool is_error () const { return candidate.is_error (); }
 };
 
-class MethodResolver : protected AutoderefCycle
+class MethodResolver : private TypeCheckBase, protected AutoderefCycle
 {
 public:
   struct predicate_candidate
@@ -63,10 +63,6 @@ protected:
   bool select (const TyTy::BaseType &receiver) override;
 
 private:
-  // context info
-  Analysis::Mappings *mappings;
-  TypeCheckContext *context;
-
   // search
   const HIR::PathIdentSegment &segment_name;
   std::vector<MethodResolver::predicate_candidate> predicate_items;
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
new file mode 100644
index 00000000000..cb3270d3623
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-path-probe.h"
+#include "rust-hir-type-check-item.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
+					    HIR::ImplBlock *impl)
+{
+  current_impl = impl;
+  HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
+  TyTy::BaseType *impl_block_ty = nullptr;
+  if (!query_type (impl_ty_id, &impl_block_ty))
+    return;
+
+  if (!receiver->can_eq (impl_block_ty, false))
+    {
+      if (!impl_block_ty->can_eq (receiver, false))
+	return;
+    }
+
+  // lets visit the impl_item
+  item->accept_vis (*this);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index bd4f91e49bf..b1d7f4b26ac 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -195,7 +195,7 @@ public:
       {
 	HirId tyid = alias.get_mappings ().get_hirid ();
 	TyTy::BaseType *ty = nullptr;
-	bool ok = context->lookup_type (tyid, &ty);
+	bool ok = query_type (tyid, &ty);
 	rust_assert (ok);
 
 	PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
@@ -214,7 +214,7 @@ public:
       {
 	HirId tyid = constant.get_mappings ().get_hirid ();
 	TyTy::BaseType *ty = nullptr;
-	bool ok = context->lookup_type (tyid, &ty);
+	bool ok = query_type (tyid, &ty);
 	rust_assert (ok);
 
 	PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
@@ -233,7 +233,7 @@ public:
       {
 	HirId tyid = function.get_mappings ().get_hirid ();
 	TyTy::BaseType *ty = nullptr;
-	bool ok = context->lookup_type (tyid, &ty);
+	bool ok = query_type (tyid, &ty);
 	rust_assert (ok);
 
 	PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
@@ -272,23 +272,7 @@ protected:
   }
 
   void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
-				    HIR::ImplBlock *impl)
-  {
-    current_impl = impl;
-    HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
-    TyTy::BaseType *impl_block_ty = nullptr;
-    if (!context->lookup_type (impl_ty_id, &impl_block_ty))
-      return;
-
-    if (!receiver->can_eq (impl_block_ty, false))
-      {
-	if (!impl_block_ty->can_eq (receiver, false))
-	  return;
-      }
-
-    // lets visit the impl_item
-    item->accept_vis (*this);
-  }
+				    HIR::ImplBlock *impl);
 
   void
   process_associated_trait_for_candidates (const TraitReference *trait_ref,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index cba7e594cba..bd6a2fb3e73 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -17,8 +17,10 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-hir-type-check-base.h"
+#include "rust-hir-type-check-item.h"
 #include "rust-hir-type-check-type.h"
 #include "rust-hir-type-check-expr.h"
+#include "rust-hir-type-check-implitem.h"
 #include "rust-coercion.h"
 #include "rust-casts.h"
 
@@ -37,6 +39,13 @@ TypeCheckBase::check_for_unconstrained (
   const TyTy::SubstitutionArgumentMappings &constraint_b,
   const TyTy::BaseType *reference)
 {
+  bool check_result = false;
+  bool check_completed
+    = context->have_checked_for_unconstrained (reference->get_ref (),
+					       &check_result);
+  if (check_completed)
+    return check_result;
+
   std::set<HirId> symbols_to_constrain;
   std::map<HirId, Location> symbol_to_location;
   for (const auto &p : params_to_constrain)
@@ -86,6 +95,10 @@ TypeCheckBase::check_for_unconstrained (
 	  unconstrained = true;
 	}
     }
+
+  context->insert_unconstrained_check_marker (reference->get_ref (),
+					      unconstrained);
+
   return unconstrained;
 }
 
@@ -479,5 +492,68 @@ TypeCheckBase::resolve_generic_params (
     }
 }
 
+bool
+TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
+{
+  if (context->lookup_type (reference, result))
+    return true;
+
+  HIR::Item *item = mappings->lookup_hir_item (reference);
+  if (item != nullptr)
+    {
+      rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference);
+      *result = TypeCheckItem::Resolve (*item);
+      return true;
+    }
+
+  HirId parent_impl_id = UNKNOWN_HIRID;
+  HIR::ImplItem *impl_item
+    = mappings->lookup_hir_implitem (reference, &parent_impl_id);
+  if (impl_item != nullptr)
+    {
+      HIR::ImplBlock *impl_block
+	= mappings->lookup_hir_impl_block (parent_impl_id);
+      rust_assert (impl_block != nullptr);
+
+      // found an impl item
+      rust_debug_loc (impl_item->get_locus (), "resolved impl-item {%u} to",
+		      reference);
+
+      *result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item);
+      return true;
+    }
+
+  // is it an impl_type?
+  HIR::ImplBlock *impl_block_by_type = nullptr;
+  bool found_impl_block_type
+    = mappings->lookup_impl_block_type (reference, &impl_block_by_type);
+  if (found_impl_block_type)
+    {
+      *result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type);
+      return true;
+    }
+
+  // is it an extern item?
+  HirId parent_extern_block_id = UNKNOWN_HIRID;
+  HIR::ExternalItem *extern_item
+    = mappings->lookup_hir_extern_item (reference, &parent_extern_block_id);
+  if (extern_item != nullptr)
+    {
+      HIR::ExternBlock *block
+	= mappings->lookup_hir_extern_block (parent_extern_block_id);
+      rust_assert (block != nullptr);
+
+      *result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block);
+      return true;
+    }
+
+  // more?
+  Location possible_locus = mappings->lookup_location (reference);
+  rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
+		  reference);
+
+  return false;
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index ce6195e44e1..743cf4f94bd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -69,6 +69,8 @@ protected:
     const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
     std::vector<TyTy::SubstitutionParamMapping> &substitutions);
 
+  bool query_type (HirId reference, TyTy::BaseType **result);
+
   Analysis::Mappings *mappings;
   Resolver *resolver;
   TypeCheckContext *context;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 9a0d144ab10..9a5785f71b7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -188,6 +188,9 @@ TypeCheckExpr::visit (HIR::CallExpr &expr)
       return;
     }
 
+  rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}",
+		  function_tyty->get_name ().c_str ());
+
   TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node ();
   if (function_tyty->get_kind () == TyTy::TypeKind::ADT)
     {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index 81dd3677609..9643bb473bb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -32,12 +32,21 @@ TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem (
   : TypeCheckBase (), parent (parent)
 {}
 
-void
+TyTy::BaseType *
 TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem *item,
 				      const HIR::ExternBlock &parent)
 {
+  // is it already resolved?
+  auto context = TypeCheckContext::get ();
+  TyTy::BaseType *resolved = nullptr;
+  bool already_resolved
+    = context->lookup_type (item->get_mappings ().get_hirid (), &resolved);
+  if (already_resolved)
+    return resolved;
+
   TypeCheckTopLevelExternItem resolver (parent);
   item->accept_vis (resolver);
+  return resolver.resolved;
 }
 
 void
@@ -47,6 +56,7 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item)
     = TypeCheckType::Resolve (item.get_item_type ().get ());
 
   context->insert_type (item.get_mappings (), actual_type);
+  resolved = actual_type;
 }
 
 void
@@ -142,79 +152,40 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
 				  ret_type, std::move (substitutions));
 
   context->insert_type (function.get_mappings (), fnType);
+  resolved = fnType;
 }
 
-TypeCheckTopLevelImplItem::TypeCheckTopLevelImplItem (
-  TyTy::BaseType *self,
+TypeCheckImplItem::TypeCheckImplItem (
+  HIR::ImplBlock *parent, TyTy::BaseType *self,
   std::vector<TyTy::SubstitutionParamMapping> substitutions)
-  : TypeCheckBase (), self (self), substitutions (substitutions)
+  : TypeCheckBase (), parent (parent), self (self),
+    substitutions (substitutions)
 {}
 
-void
-TypeCheckTopLevelImplItem::Resolve (
-  HIR::ImplItem *item, TyTy::BaseType *self,
+TyTy::BaseType *
+TypeCheckImplItem::Resolve (
+  HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
   std::vector<TyTy::SubstitutionParamMapping> substitutions)
 {
-  TypeCheckTopLevelImplItem resolver (self, substitutions);
+  // is it already resolved?
+  auto context = TypeCheckContext::get ();
+  TyTy::BaseType *resolved = nullptr;
+  bool already_resolved
+    = context->lookup_type (item->get_impl_mappings ().get_hirid (), &resolved);
+  if (already_resolved)
+    return resolved;
+
+  // resolve
+  TypeCheckImplItem resolver (parent, self, substitutions);
   item->accept_vis (resolver);
+  return resolver.result;
 }
 
 void
-TypeCheckTopLevelImplItem::visit (HIR::TypeAlias &alias)
-{
-  TyTy::BaseType *actual_type
-    = TypeCheckType::Resolve (alias.get_type_aliased ().get ());
-
-  context->insert_type (alias.get_mappings (), actual_type);
-
-  for (auto &where_clause_item : alias.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-}
-
-void
-TypeCheckTopLevelImplItem::visit (HIR::ConstantItem &constant)
-{
-  TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
-  TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
-
-  TyTy::BaseType *unified = unify_site (
-    constant.get_mappings ().get_hirid (),
-    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
-    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
-    constant.get_locus ());
-  context->insert_type (constant.get_mappings (), unified);
-}
-
-void
-TypeCheckTopLevelImplItem::visit (HIR::Function &function)
+TypeCheckImplItem::visit (HIR::Function &function)
 {
   if (function.has_generics ())
-    {
-      for (auto &generic_param : function.get_generic_params ())
-	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		auto param_type
-		  = TypeResolveGenericParam::Resolve (generic_param.get ());
-		context->insert_type (generic_param->get_mappings (),
-				      param_type);
-
-		substitutions.push_back (TyTy::SubstitutionParamMapping (
-		  static_cast<HIR::TypeParam &> (*generic_param), param_type));
-	      }
-	      break;
-	    }
-	}
-    }
+    resolve_generic_params (function.get_generic_params (), substitutions);
 
   for (auto &where_clause_item : function.get_where_clause ().get_items ())
     {
@@ -328,41 +299,10 @@ TypeCheckTopLevelImplItem::visit (HIR::Function &function)
 				  std::move (substitutions));
 
   context->insert_type (function.get_mappings (), fnType);
-}
-
-TypeCheckImplItem::TypeCheckImplItem (HIR::ImplBlock *parent,
-				      TyTy::BaseType *self)
-  : TypeCheckBase (), parent (parent), self (self)
-{}
-
-void
-TypeCheckImplItem::Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item,
-			    TyTy::BaseType *self)
-{
-  TypeCheckImplItem resolver (parent, self);
-  item->accept_vis (resolver);
-}
-
-void
-TypeCheckImplItem::visit (HIR::Function &function)
-{
-  TyTy::BaseType *lookup;
-  if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
-    {
-      rust_error_at (function.get_locus (), "failed to lookup function type");
-      return;
-    }
-
-  if (lookup->get_kind () != TyTy::TypeKind::FNDEF)
-    {
-      rust_error_at (function.get_locus (),
-		     "found invalid type for function [%s]",
-		     lookup->as_string ().c_str ());
-      return;
-    }
+  result = fnType;
 
   // need to get the return type from this
-  TyTy::FnType *resolve_fn_type = static_cast<TyTy::FnType *> (lookup);
+  TyTy::FnType *resolve_fn_type = fnType;
   auto expected_ret_tyty = resolve_fn_type->get_return_type ();
   context->push_return_type (TypeCheckContextItem (parent, &function),
 			     expected_ret_tyty);
@@ -383,20 +323,41 @@ TypeCheckImplItem::visit (HIR::Function &function)
 }
 
 void
-TypeCheckImplItem::visit (HIR::ConstantItem &const_item)
-{}
+TypeCheckImplItem::visit (HIR::ConstantItem &constant)
+{
+  TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
+  TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
+
+  TyTy::BaseType *unified = unify_site (
+    constant.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
+    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
+    constant.get_locus ());
+  context->insert_type (constant.get_mappings (), unified);
+  result = unified;
+}
 
 void
-TypeCheckImplItem::visit (HIR::TypeAlias &type_alias)
-{}
+TypeCheckImplItem::visit (HIR::TypeAlias &alias)
+{
+  TyTy::BaseType *actual_type
+    = TypeCheckType::Resolve (alias.get_type_aliased ().get ());
+
+  context->insert_type (alias.get_mappings (), actual_type);
+  result = actual_type;
+  for (auto &where_clause_item : alias.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
+    }
+}
 
 TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait (
   HIR::ImplBlock *parent, TyTy::BaseType *self,
   TyTy::TypeBoundPredicate &trait_reference,
   std::vector<TyTy::SubstitutionParamMapping> substitutions)
-  : TypeCheckImplItem (parent, self), trait_reference (trait_reference),
+  : TypeCheckBase (), trait_reference (trait_reference),
     resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
-    substitutions (substitutions)
+    parent (parent), self (self), substitutions (substitutions)
 {
   rust_assert (is_trait_impl_block ());
 }
@@ -417,10 +378,8 @@ void
 TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
 {
   // normal resolution of the item
-  TypeCheckImplItem::visit (constant);
-  TyTy::BaseType *lookup;
-  if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup))
-    return;
+  TyTy::BaseType *lookup
+    = TypeCheckImplItem::Resolve (parent, &constant, self, substitutions);
 
   // map the impl item to the associated trait item
   const auto tref = trait_reference.get ();
@@ -468,10 +427,8 @@ void
 TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
 {
   // normal resolution of the item
-  TypeCheckImplItem::visit (type);
-  TyTy::BaseType *lookup;
-  if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
-    return;
+  TyTy::BaseType *lookup
+    = TypeCheckImplItem::Resolve (parent, &type, self, substitutions);
 
   // map the impl item to the associated trait item
   const auto tref = trait_reference.get ();
@@ -528,11 +485,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
 void
 TypeCheckImplItemWithTrait::visit (HIR::Function &function)
 {
-  // we get the error checking from the base method here
-  TypeCheckImplItem::visit (function);
-  TyTy::BaseType *lookup;
-  if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
-    return;
+  // normal resolution of the item
+  TyTy::BaseType *lookup
+    = TypeCheckImplItem::Resolve (parent, &function, self, substitutions);
 
   // map the impl item to the associated trait item
   const auto tref = trait_reference.get ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index f2f3faab9e0..c4b27e50451 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -28,7 +28,8 @@ class TypeCheckTopLevelExternItem : public TypeCheckBase,
 				    public HIR::HIRExternalItemVisitor
 {
 public:
-  static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent);
+  static TyTy::BaseType *Resolve (HIR::ExternalItem *item,
+				  const HIR::ExternBlock &parent);
 
   void visit (HIR::ExternalStaticItem &item) override;
   void visit (HIR::ExternalFunctionItem &function) override;
@@ -37,47 +38,33 @@ private:
   TypeCheckTopLevelExternItem (const HIR::ExternBlock &parent);
 
   const HIR::ExternBlock &parent;
-};
-
-class TypeCheckTopLevelImplItem : public TypeCheckBase,
-				  public HIR::HIRImplVisitor
-{
-public:
-  static void
-  Resolve (HIR::ImplItem *item, TyTy::BaseType *self,
-	   std::vector<TyTy::SubstitutionParamMapping> substitutions);
-
-  void visit (HIR::TypeAlias &alias) override;
-  void visit (HIR::ConstantItem &constant) override;
-  void visit (HIR::Function &function) override;
-
-private:
-  TypeCheckTopLevelImplItem (
-    TyTy::BaseType *self,
-    std::vector<TyTy::SubstitutionParamMapping> substitutions);
-
-  TyTy::BaseType *self;
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+  TyTy::BaseType *resolved;
 };
 
 class TypeCheckImplItem : public TypeCheckBase, public HIR::HIRImplVisitor
 {
 public:
-  static void Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item,
-		       TyTy::BaseType *self);
+  static TyTy::BaseType *
+  Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self,
+	   std::vector<TyTy::SubstitutionParamMapping> substitutions);
 
   void visit (HIR::Function &function) override;
   void visit (HIR::ConstantItem &const_item) override;
   void visit (HIR::TypeAlias &type_alias) override;
 
 protected:
-  TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self);
+  TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self,
+		     std::vector<TyTy::SubstitutionParamMapping> substitutions);
 
   HIR::ImplBlock *parent;
   TyTy::BaseType *self;
+  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+
+  TyTy::BaseType *result;
 };
 
-class TypeCheckImplItemWithTrait : public TypeCheckImplItem
+class TypeCheckImplItemWithTrait : public TypeCheckBase,
+				   public HIR::HIRImplVisitor
 {
 public:
   static TyTy::TypeBoundPredicateItem
@@ -105,6 +92,9 @@ private:
 
   TyTy::TypeBoundPredicate &trait_reference;
   TyTy::TypeBoundPredicateItem resolved_trait_item;
+
+  HIR::ImplBlock *parent;
+  TyTy::BaseType *self;
   std::vector<TyTy::SubstitutionParamMapping> substitutions;
 };
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index fc2c0f27a74..ade6ab72053 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -16,59 +16,466 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-#include "rust-hir-type-check-item.h"
 #include "rust-hir-full.h"
+#include "rust-hir-type-check-item.h"
+#include "rust-hir-type-check-enumitem.h"
 #include "rust-hir-type-check-implitem.h"
 #include "rust-hir-type-check-type.h"
 #include "rust-hir-type-check-stmt.h"
 #include "rust-hir-type-check-expr.h"
+#include "rust-hir-type-check-pattern.h"
 #include "rust-hir-trait-resolve.h"
 
 namespace Rust {
 namespace Resolver {
 
-TypeCheckItem::TypeCheckItem () : TypeCheckBase () {}
+TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
 
-void
+TyTy::BaseType *
 TypeCheckItem::Resolve (HIR::Item &item)
 {
+  // is it already resolved?
+  auto context = TypeCheckContext::get ();
+  TyTy::BaseType *resolved = nullptr;
+  bool already_resolved
+    = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
+  if (already_resolved)
+    return resolved;
+
   rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
   HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
 
   TypeCheckItem resolver;
   vis_item.accept_vis (resolver);
+  return resolver.infered;
+}
+
+TyTy::BaseType *
+TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
+{
+  TypeCheckItem resolver;
+  return resolver.resolve_impl_item (impl_block, item);
+}
+
+TyTy::BaseType *
+TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
+{
+  TypeCheckItem resolver;
+
+  bool failed_flag = false;
+  std::vector<TyTy::SubstitutionParamMapping> substitutions
+    = resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
+  if (failed_flag)
+    {
+      return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
+    }
+
+  return resolver.resolve_impl_block_self (impl_block);
+}
+
+void
+TypeCheckItem::visit (HIR::TypeAlias &alias)
+{
+  TyTy::BaseType *actual_type
+    = TypeCheckType::Resolve (alias.get_type_aliased ().get ());
+
+  context->insert_type (alias.get_mappings (), actual_type);
+
+  for (auto &where_clause_item : alias.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
+    }
+  infered = actual_type;
+}
+
+void
+TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
+{
+  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+  if (struct_decl.has_generics ())
+    resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+
+  for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
+    }
+
+  std::vector<TyTy::StructFieldType *> fields;
+  size_t idx = 0;
+  for (auto &field : struct_decl.get_fields ())
+    {
+      TyTy::BaseType *field_type
+	= TypeCheckType::Resolve (field.get_field_type ().get ());
+      TyTy::StructFieldType *ty_field
+	= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
+				     std::to_string (idx), field_type,
+				     field.get_locus ());
+      fields.push_back (ty_field);
+      context->insert_type (field.get_mappings (), ty_field->get_field_type ());
+      idx++;
+    }
+
+  // get the path
+  const CanonicalPath *canonical_path = nullptr;
+  bool ok = mappings->lookup_canonical_path (
+    struct_decl.get_mappings ().get_nodeid (), &canonical_path);
+  rust_assert (ok);
+  RustIdent ident{*canonical_path, struct_decl.get_locus ()};
+
+  // its a single variant ADT
+  std::vector<TyTy::VariantDef *> variants;
+  variants.push_back (new TyTy::VariantDef (
+    struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
+    ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields)));
+
+  // Process #[repr(X)] attribute, if any
+  const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
+  TyTy::ADTType::ReprOptions repr
+    = parse_repr_options (attrs, struct_decl.get_locus ());
+
+  TyTy::BaseType *type
+    = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
+			 mappings->get_next_hir_id (),
+			 struct_decl.get_identifier (), ident,
+			 TyTy::ADTType::ADTKind::TUPLE_STRUCT,
+			 std::move (variants), std::move (substitutions), repr);
+
+  context->insert_type (struct_decl.get_mappings (), type);
+  infered = type;
+}
+
+void
+TypeCheckItem::visit (HIR::StructStruct &struct_decl)
+{
+  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+  if (struct_decl.has_generics ())
+    resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+
+  for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
+    }
+
+  std::vector<TyTy::StructFieldType *> fields;
+  for (auto &field : struct_decl.get_fields ())
+    {
+      TyTy::BaseType *field_type
+	= TypeCheckType::Resolve (field.get_field_type ().get ());
+      TyTy::StructFieldType *ty_field
+	= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
+				     field.get_field_name (), field_type,
+				     field.get_locus ());
+      fields.push_back (ty_field);
+      context->insert_type (field.get_mappings (), ty_field->get_field_type ());
+    }
+
+  // get the path
+  const CanonicalPath *canonical_path = nullptr;
+  bool ok = mappings->lookup_canonical_path (
+    struct_decl.get_mappings ().get_nodeid (), &canonical_path);
+  rust_assert (ok);
+  RustIdent ident{*canonical_path, struct_decl.get_locus ()};
+
+  // its a single variant ADT
+  std::vector<TyTy::VariantDef *> variants;
+  variants.push_back (new TyTy::VariantDef (
+    struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
+    ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
+
+  // Process #[repr(X)] attribute, if any
+  const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
+  TyTy::ADTType::ReprOptions repr
+    = parse_repr_options (attrs, struct_decl.get_locus ());
+
+  TyTy::BaseType *type
+    = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
+			 mappings->get_next_hir_id (),
+			 struct_decl.get_identifier (), ident,
+			 TyTy::ADTType::ADTKind::STRUCT_STRUCT,
+			 std::move (variants), std::move (substitutions), repr);
+
+  context->insert_type (struct_decl.get_mappings (), type);
+  infered = type;
+}
+
+void
+TypeCheckItem::visit (HIR::Enum &enum_decl)
+{
+  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+  if (enum_decl.has_generics ())
+    resolve_generic_params (enum_decl.get_generic_params (), substitutions);
+
+  std::vector<TyTy::VariantDef *> variants;
+  int64_t discriminant_value = 0;
+  for (auto &variant : enum_decl.get_variants ())
+    {
+      TyTy::VariantDef *field_type
+	= TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
+
+      discriminant_value++;
+      variants.push_back (field_type);
+    }
+
+  // get the path
+  const CanonicalPath *canonical_path = nullptr;
+  bool ok
+    = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
+				       &canonical_path);
+  rust_assert (ok);
+  RustIdent ident{*canonical_path, enum_decl.get_locus ()};
+
+  // multi variant ADT
+  TyTy::BaseType *type
+    = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
+			 mappings->get_next_hir_id (),
+			 enum_decl.get_identifier (), ident,
+			 TyTy::ADTType::ADTKind::ENUM, std::move (variants),
+			 std::move (substitutions));
+
+  context->insert_type (enum_decl.get_mappings (), type);
+  infered = type;
+}
+
+void
+TypeCheckItem::visit (HIR::Union &union_decl)
+{
+  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+  if (union_decl.has_generics ())
+    resolve_generic_params (union_decl.get_generic_params (), substitutions);
+
+  for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
+    }
+
+  std::vector<TyTy::StructFieldType *> fields;
+  for (auto &variant : union_decl.get_variants ())
+    {
+      TyTy::BaseType *variant_type
+	= TypeCheckType::Resolve (variant.get_field_type ().get ());
+      TyTy::StructFieldType *ty_variant
+	= new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
+				     variant.get_field_name (), variant_type,
+				     variant.get_locus ());
+      fields.push_back (ty_variant);
+      context->insert_type (variant.get_mappings (),
+			    ty_variant->get_field_type ());
+    }
+
+  // get the path
+  const CanonicalPath *canonical_path = nullptr;
+  bool ok
+    = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
+				       &canonical_path);
+  rust_assert (ok);
+  RustIdent ident{*canonical_path, union_decl.get_locus ()};
+
+  // there is only a single variant
+  std::vector<TyTy::VariantDef *> variants;
+  variants.push_back (new TyTy::VariantDef (
+    union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (),
+    ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
+
+  TyTy::BaseType *type
+    = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (),
+			 mappings->get_next_hir_id (),
+			 union_decl.get_identifier (), ident,
+			 TyTy::ADTType::ADTKind::UNION, std::move (variants),
+			 std::move (substitutions));
+
+  context->insert_type (union_decl.get_mappings (), type);
+  infered = type;
+}
+
+void
+TypeCheckItem::visit (HIR::StaticItem &var)
+{
+  TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
+  TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
+
+  TyTy::BaseType *unified
+    = coercion_site (var.get_mappings ().get_hirid (),
+		     TyTy::TyWithLocation (type, var.get_type ()->get_locus ()),
+		     TyTy::TyWithLocation (expr_type,
+					   var.get_expr ()->get_locus ()),
+		     var.get_locus ());
+  context->insert_type (var.get_mappings (), unified);
+  infered = unified;
+}
+
+void
+TypeCheckItem::visit (HIR::ConstantItem &constant)
+{
+  TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
+  TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
+
+  TyTy::BaseType *unified = unify_site (
+    constant.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
+    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
+    constant.get_locus ());
+  context->insert_type (constant.get_mappings (), unified);
+  infered = unified;
 }
 
 void
 TypeCheckItem::visit (HIR::ImplBlock &impl_block)
+{
+  bool failed_flag = false;
+  std::vector<TyTy::SubstitutionParamMapping> substitutions
+    = resolve_impl_block_substitutions (impl_block, failed_flag);
+  if (failed_flag)
+    {
+      infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
+      return;
+    }
+
+  TyTy::BaseType *self = resolve_impl_block_self (impl_block);
+
+  // resolve each impl_item
+  for (auto &impl_item : impl_block.get_impl_items ())
+    {
+      TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self,
+				  substitutions);
+    }
+
+  // validate the impl items
+  validate_trait_impl_block (impl_block, self, substitutions);
+}
+
+TyTy::BaseType *
+TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
+				  HIR::ImplItem &item)
+{
+  bool failed_flag = false;
+  std::vector<TyTy::SubstitutionParamMapping> substitutions
+    = resolve_impl_block_substitutions (impl_block, failed_flag);
+  if (failed_flag)
+    {
+      return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
+    }
+
+  TyTy::BaseType *self = resolve_impl_block_self (impl_block);
+
+  return TypeCheckImplItem::Resolve (&impl_block, &item, self, substitutions);
+}
+
+void
+TypeCheckItem::visit (HIR::Function &function)
 {
   std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (impl_block.has_generics ())
+  if (function.has_generics ())
+    resolve_generic_params (function.get_generic_params (), substitutions);
+
+  for (auto &where_clause_item : function.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
+    }
+
+  TyTy::BaseType *ret_type = nullptr;
+  if (!function.has_function_return_type ())
+    ret_type
+      = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
+  else
     {
-      for (auto &generic_param : impl_block.get_generic_params ())
+      auto resolved
+	= TypeCheckType::Resolve (function.get_return_type ().get ());
+      if (resolved->get_kind () == TyTy::TypeKind::ERROR)
 	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		TyTy::BaseType *l = nullptr;
-		bool ok = context->lookup_type (
-		  generic_param->get_mappings ().get_hirid (), &l);
-		if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
-		  {
-		    substitutions.push_back (TyTy::SubstitutionParamMapping (
-		      static_cast<HIR::TypeParam &> (*generic_param),
-		      static_cast<TyTy::ParamType *> (l)));
-		  }
-	      }
-	      break;
-	    }
+	  rust_error_at (function.get_locus (),
+			 "failed to resolve return type");
+	  return;
 	}
+
+      ret_type = resolved->clone ();
+      ret_type->set_ref (
+	function.get_return_type ()->get_mappings ().get_hirid ());
+    }
+
+  std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *>> params;
+  for (auto &param : function.get_function_params ())
+    {
+      // get the name as well required for later on
+      auto param_tyty = TypeCheckType::Resolve (param.get_type ());
+      params.push_back (
+	std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (),
+						     param_tyty));
+
+      context->insert_type (param.get_mappings (), param_tyty);
+      TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
+    }
+
+  const CanonicalPath *canonical_path = nullptr;
+  bool ok
+    = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (),
+				       &canonical_path);
+  rust_assert (ok);
+
+  RustIdent ident{*canonical_path, function.get_locus ()};
+  auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
+				  function.get_mappings ().get_defid (),
+				  function.get_function_name (), ident,
+				  TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST,
+				  std::move (params), ret_type,
+				  std::move (substitutions));
+
+  context->insert_type (function.get_mappings (), fnType);
+
+  // need to get the return type from this
+  TyTy::FnType *resolved_fn_type = fnType;
+  auto expected_ret_tyty = resolved_fn_type->get_return_type ();
+  context->push_return_type (TypeCheckContextItem (&function),
+			     expected_ret_tyty);
+
+  auto block_expr_ty
+    = TypeCheckExpr::Resolve (function.get_definition ().get ());
+
+  Location fn_return_locus = function.has_function_return_type ()
+			       ? function.get_return_type ()->get_locus ()
+			       : function.get_locus ();
+  coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
+		 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
+		 TyTy::TyWithLocation (block_expr_ty),
+		 function.get_definition ()->get_locus ());
+
+  context->pop_return_type ();
+
+  infered = fnType;
+}
+
+void
+TypeCheckItem::visit (HIR::Module &module)
+{
+  for (auto &item : module.get_items ())
+    TypeCheckItem::Resolve (*item.get ());
+}
+
+void
+TypeCheckItem::visit (HIR::Trait &trait)
+{
+  TraitResolver::Resolve (trait);
+}
+
+void
+TypeCheckItem::visit (HIR::ExternBlock &extern_block)
+{
+  for (auto &item : extern_block.get_extern_items ())
+    {
+      TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block);
+    }
+}
+
+std::vector<TyTy::SubstitutionParamMapping>
+TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
+						 bool &failure_flag)
+{
+  std::vector<TyTy::SubstitutionParamMapping> substitutions;
+  if (impl_block.has_generics ())
+    resolve_generic_params (impl_block.get_generic_params (), substitutions);
+
+  for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
+    {
+      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
     }
 
   auto specified_bound = TyTy::TypeBoundPredicate::error ();
@@ -84,14 +491,7 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
       specified_bound = get_predicate_from_bound (*ref.get ());
     }
 
-  TyTy::BaseType *self = nullptr;
-  if (!context->lookup_type (
-	impl_block.get_type ()->get_mappings ().get_hirid (), &self))
-    {
-      rust_error_at (impl_block.get_locus (),
-		     "failed to resolve Self for ImplBlock");
-      return;
-    }
+  TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ().get ());
 
   // inherit the bounds
   if (!specified_bound.is_error ())
@@ -103,20 +503,35 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
   const TyTy::SubstitutionArgumentMappings impl_constraints
     = GetUsedSubstArgs::From (self);
 
-  bool impl_block_has_unconstrained_typarams
-    = check_for_unconstrained (substitutions, trait_constraints,
-			       impl_constraints, self);
-  if (impl_block_has_unconstrained_typarams)
-    return;
+  failure_flag = check_for_unconstrained (substitutions, trait_constraints,
+					  impl_constraints, self);
+
+  return substitutions;
+}
+
+void
+TypeCheckItem::validate_trait_impl_block (
+  HIR::ImplBlock &impl_block, TyTy::BaseType *self,
+  std::vector<TyTy::SubstitutionParamMapping> &substitutions)
+{
+  auto specified_bound = TyTy::TypeBoundPredicate::error ();
+  TraitReference *trait_reference = &TraitReference::error_node ();
+  if (impl_block.has_trait_ref ())
+    {
+      std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
+      trait_reference = TraitResolver::Resolve (*ref.get ());
+      rust_assert (!trait_reference->is_error ());
+
+      // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
+      // for example
+      specified_bound = get_predicate_from_bound (*ref.get ());
+    }
 
-  // validate the impl items
   bool is_trait_impl_block = !trait_reference->is_error ();
   std::vector<const TraitItemReference *> trait_item_refs;
   for (auto &impl_item : impl_block.get_impl_items ())
     {
-      if (!is_trait_impl_block)
-	TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self);
-      else
+      if (!specified_bound.is_error ())
 	{
 	  auto trait_item_ref
 	    = TypeCheckImplItemWithTrait::Resolve (&impl_block,
@@ -128,7 +543,7 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
     }
 
   bool impl_block_missing_trait_items
-    = is_trait_impl_block
+    = !specified_bound.is_error ()
       && trait_reference->size () != trait_item_refs.size ();
   if (impl_block_missing_trait_items)
     {
@@ -187,55 +602,10 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block)
     }
 }
 
-void
-TypeCheckItem::visit (HIR::Function &function)
+TyTy::BaseType *
+TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
 {
-  TyTy::BaseType *lookup;
-  if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
-    {
-      rust_error_at (function.get_locus (), "failed to lookup function type");
-      return;
-    }
-
-  if (lookup->get_kind () != TyTy::TypeKind::FNDEF)
-    {
-      rust_error_at (function.get_locus (),
-		     "found invalid type for function [%s]",
-		     lookup->as_string ().c_str ());
-      return;
-    }
-
-  // need to get the return type from this
-  TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (lookup);
-  auto expected_ret_tyty = resolved_fn_type->get_return_type ();
-  context->push_return_type (TypeCheckContextItem (&function),
-			     expected_ret_tyty);
-
-  auto block_expr_ty
-    = TypeCheckExpr::Resolve (function.get_definition ().get ());
-
-  Location fn_return_locus = function.has_function_return_type ()
-			       ? function.get_return_type ()->get_locus ()
-			       : function.get_locus ();
-  coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
-		 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
-		 TyTy::TyWithLocation (block_expr_ty),
-		 function.get_definition ()->get_locus ());
-
-  context->pop_return_type ();
-}
-
-void
-TypeCheckItem::visit (HIR::Module &module)
-{
-  for (auto &item : module.get_items ())
-    TypeCheckItem::Resolve (*item.get ());
-}
-
-void
-TypeCheckItem::visit (HIR::Trait &trait)
-{
-  TraitResolver::Resolve (trait);
+  return TypeCheckType::Resolve (impl_block.get_type ().get ());
 }
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index ba4de19c9c7..3b88157f5ae 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -27,29 +27,48 @@ namespace Resolver {
 class TypeCheckItem : private TypeCheckBase, private HIR::HIRVisItemVisitor
 {
 public:
-  static void Resolve (HIR::Item &item);
+  static TyTy::BaseType *Resolve (HIR::Item &item);
+
+  static TyTy::BaseType *ResolveImplItem (HIR::ImplBlock &impl_block,
+					  HIR::ImplItem &item);
+
+  static TyTy::BaseType *ResolveImplBlockSelf (HIR::ImplBlock &impl_block);
 
-  void visit (HIR::ImplBlock &impl_block) override;
-  void visit (HIR::Function &function) override;
   void visit (HIR::Module &module) override;
-  void visit (HIR::Trait &trait) override;
-
-  // FIXME - get rid of toplevel pass
-  void visit (HIR::TypeAlias &alias) override{};
-  void visit (HIR::TupleStruct &struct_decl) override{};
-  void visit (HIR::StructStruct &struct_decl) override{};
-  void visit (HIR::Enum &enum_decl) override{};
-  void visit (HIR::Union &union_decl) override{};
-  void visit (HIR::StaticItem &var) override{};
-  void visit (HIR::ConstantItem &constant) override{};
-  void visit (HIR::ExternBlock &extern_block) override{};
+  void visit (HIR::Function &function) override;
+  void visit (HIR::TypeAlias &alias) override;
+  void visit (HIR::TupleStruct &struct_decl) override;
+  void visit (HIR::StructStruct &struct_decl) override;
+  void visit (HIR::Enum &enum_decl) override;
+  void visit (HIR::Union &union_decl) override;
+  void visit (HIR::StaticItem &var) override;
+  void visit (HIR::ConstantItem &constant) override;
+  void visit (HIR::ImplBlock &impl_block) override;
+  void visit (HIR::ExternBlock &extern_block) override;
+  void visit (HIR::Trait &trait_block) override;
 
   // nothing to do
   void visit (HIR::ExternCrate &crate) override {}
   void visit (HIR::UseDeclaration &use_decl) override {}
 
+protected:
+  std::vector<TyTy::SubstitutionParamMapping>
+  resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
+				    bool &failure_flag);
+
+  void validate_trait_impl_block (
+    HIR::ImplBlock &impl_block, TyTy::BaseType *self,
+    std::vector<TyTy::SubstitutionParamMapping> &substitutions);
+
+  TyTy::BaseType *resolve_impl_item (HIR::ImplBlock &impl_block,
+				     HIR::ImplItem &item);
+
+  TyTy::BaseType *resolve_impl_block_self (HIR::ImplBlock &impl_block);
+
 private:
   TypeCheckItem ();
+
+  TyTy::BaseType *infered;
 };
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index dba30562115..33be96b7867 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -235,7 +235,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
 	}
 
       TyTy::BaseType *lookup = nullptr;
-      if (!context->lookup_type (ref, &lookup))
+      if (!query_type (ref, &lookup))
 	{
 	  if (is_root)
 	    {
@@ -383,7 +383,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
 	  HirId impl_ty_id
 	    = associated_impl_block->get_type ()->get_mappings ().get_hirid ();
 	  TyTy::BaseType *impl_block_ty = nullptr;
-	  bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
+	  bool ok = query_type (impl_ty_id, &impl_block_ty);
 	  rust_assert (ok);
 
 	  if (impl_block_ty->needs_generic_substitutions ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
index ce8d97b2ecf..890901245ee 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
@@ -22,6 +22,7 @@
 #include "rust-hir-type-check-expr.h"
 #include "rust-hir-type-check-enumitem.h"
 #include "rust-hir-type-check-implitem.h"
+#include "rust-hir-type-check-item.h"
 #include "rust-hir-type-check-pattern.h"
 
 namespace Rust {
@@ -139,378 +140,74 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
 }
 
 void
-TypeCheckStmt::visit (HIR::TupleStruct &struct_decl)
+TypeCheckStmt::visit (HIR::TypePath &path)
 {
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (struct_decl.has_generics ())
-    {
-      for (auto &generic_param : struct_decl.get_generic_params ())
-	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		auto param_type
-		  = TypeResolveGenericParam::Resolve (generic_param.get ());
-		context->insert_type (generic_param->get_mappings (),
-				      param_type);
-
-		substitutions.push_back (TyTy::SubstitutionParamMapping (
-		  static_cast<HIR::TypeParam &> (*generic_param), param_type));
-	      }
-	      break;
-	    }
-	}
-    }
-
-  std::vector<TyTy::StructFieldType *> fields;
-  size_t idx = 0;
-  for (auto &field : struct_decl.get_fields ())
-    {
-      TyTy::BaseType *field_type
-	= TypeCheckType::Resolve (field.get_field_type ().get ());
-      TyTy::StructFieldType *ty_field
-	= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
-				     std::to_string (idx), field_type,
-				     field.get_locus ());
-      fields.push_back (ty_field);
-      context->insert_type (field.get_mappings (), ty_field->get_field_type ());
-      idx++;
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok = mappings->lookup_canonical_path (
-    struct_decl.get_mappings ().get_nodeid (), &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, struct_decl.get_locus ()};
-
-  // there is only a single variant
-  std::vector<TyTy::VariantDef *> variants;
-  variants.push_back (new TyTy::VariantDef (
-    struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
-    ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields)));
-
-  // Process #[repr(...)] attribute, if any
-  const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
-  TyTy::ADTType::ReprOptions repr
-    = parse_repr_options (attrs, struct_decl.get_locus ());
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 struct_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::TUPLE_STRUCT,
-			 std::move (variants), std::move (substitutions), repr);
+  infered = TypeCheckType::Resolve (&path);
+}
+void
+TypeCheckStmt::visit (HIR::QualifiedPathInType &path)
+{
+  infered = TypeCheckType::Resolve (&path);
+}
 
-  context->insert_type (struct_decl.get_mappings (), type);
-  infered = type;
+void
+TypeCheckStmt::visit (HIR::TupleStruct &struct_decl)
+{
+  infered = TypeCheckItem::Resolve (struct_decl);
 }
 
 void
 TypeCheckStmt::visit (HIR::Enum &enum_decl)
 {
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (enum_decl.has_generics ())
-    {
-      for (auto &generic_param : enum_decl.get_generic_params ())
-	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		auto param_type
-		  = TypeResolveGenericParam::Resolve (generic_param.get ());
-		context->insert_type (generic_param->get_mappings (),
-				      param_type);
-
-		substitutions.push_back (TyTy::SubstitutionParamMapping (
-		  static_cast<HIR::TypeParam &> (*generic_param), param_type));
-	      }
-	      break;
-	    }
-	}
-    }
-
-  std::vector<TyTy::VariantDef *> variants;
-  int64_t discriminant_value = 0;
-  for (auto &variant : enum_decl.get_variants ())
-    {
-      TyTy::VariantDef *field_type
-	= TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
-
-      discriminant_value++;
-      variants.push_back (field_type);
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok
-    = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
-				       &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, enum_decl.get_locus ()};
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 enum_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::ENUM, std::move (variants),
-			 std::move (substitutions));
-
-  context->insert_type (enum_decl.get_mappings (), type);
-  infered = type;
+  infered = TypeCheckItem::Resolve (enum_decl);
 }
 
 void
 TypeCheckStmt::visit (HIR::StructStruct &struct_decl)
 {
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (struct_decl.has_generics ())
-    {
-      for (auto &generic_param : struct_decl.get_generic_params ())
-	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		auto param_type
-		  = TypeResolveGenericParam::Resolve (generic_param.get ());
-		context->insert_type (generic_param->get_mappings (),
-				      param_type);
-
-		substitutions.push_back (TyTy::SubstitutionParamMapping (
-		  static_cast<HIR::TypeParam &> (*generic_param), param_type));
-	      }
-	      break;
-	    }
-	}
-    }
-
-  std::vector<TyTy::StructFieldType *> fields;
-  for (auto &field : struct_decl.get_fields ())
-    {
-      TyTy::BaseType *field_type
-	= TypeCheckType::Resolve (field.get_field_type ().get ());
-      TyTy::StructFieldType *ty_field
-	= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
-				     field.get_field_name (), field_type,
-				     field.get_locus ());
-      fields.push_back (ty_field);
-      context->insert_type (field.get_mappings (), ty_field->get_field_type ());
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok = mappings->lookup_canonical_path (
-    struct_decl.get_mappings ().get_nodeid (), &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, struct_decl.get_locus ()};
-
-  // there is only a single variant
-  std::vector<TyTy::VariantDef *> variants;
-  variants.push_back (new TyTy::VariantDef (
-    struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
-    ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
-
-  // Process #[repr(...)] attribute, if any
-  const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
-  TyTy::ADTType::ReprOptions repr
-    = parse_repr_options (attrs, struct_decl.get_locus ());
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 struct_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::STRUCT_STRUCT,
-			 std::move (variants), std::move (substitutions), repr);
-
-  context->insert_type (struct_decl.get_mappings (), type);
-  infered = type;
+  infered = TypeCheckItem::Resolve (struct_decl);
 }
 
 void
 TypeCheckStmt::visit (HIR::Union &union_decl)
 {
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (union_decl.has_generics ())
-    {
-      for (auto &generic_param : union_decl.get_generic_params ())
-	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		auto param_type
-		  = TypeResolveGenericParam::Resolve (generic_param.get ());
-		context->insert_type (generic_param->get_mappings (),
-				      param_type);
-
-		substitutions.push_back (TyTy::SubstitutionParamMapping (
-		  static_cast<HIR::TypeParam &> (*generic_param), param_type));
-	      }
-	      break;
-	    }
-	}
-    }
-
-  std::vector<TyTy::StructFieldType *> fields;
-  for (auto &variant : union_decl.get_variants ())
-    {
-      TyTy::BaseType *variant_type
-	= TypeCheckType::Resolve (variant.get_field_type ().get ());
-      TyTy::StructFieldType *ty_variant
-	= new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
-				     variant.get_field_name (), variant_type,
-				     variant.get_locus ());
-      fields.push_back (ty_variant);
-      context->insert_type (variant.get_mappings (),
-			    ty_variant->get_field_type ());
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok
-    = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
-				       &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, union_decl.get_locus ()};
-
-  // there is only a single variant
-  std::vector<TyTy::VariantDef *> variants;
-  variants.push_back (new TyTy::VariantDef (
-    union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (),
-    ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 union_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::UNION, std::move (variants),
-			 std::move (substitutions));
-
-  context->insert_type (union_decl.get_mappings (), type);
-  infered = type;
+  infered = TypeCheckItem::Resolve (union_decl);
 }
 
 void
 TypeCheckStmt::visit (HIR::Function &function)
 {
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (function.has_generics ())
-    {
-      for (auto &generic_param : function.get_generic_params ())
-	{
-	  switch (generic_param.get ()->get_kind ())
-	    {
-	    case HIR::GenericParam::GenericKind::LIFETIME:
-	    case HIR::GenericParam::GenericKind::CONST:
-	      // FIXME: Skipping Lifetime and Const completely until better
-	      // handling.
-	      break;
-
-	      case HIR::GenericParam::GenericKind::TYPE: {
-		auto param_type
-		  = TypeResolveGenericParam::Resolve (generic_param.get ());
-		context->insert_type (generic_param->get_mappings (),
-				      param_type);
-
-		substitutions.push_back (TyTy::SubstitutionParamMapping (
-		  static_cast<HIR::TypeParam &> (*generic_param), param_type));
-	      }
-	      break;
-	    }
-	}
-    }
-
-  TyTy::BaseType *ret_type = nullptr;
-  if (!function.has_function_return_type ())
-    ret_type
-      = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
-  else
-    {
-      auto resolved
-	= TypeCheckType::Resolve (function.get_return_type ().get ());
-      if (resolved == nullptr)
-	{
-	  rust_error_at (function.get_locus (),
-			 "failed to resolve return type");
-	  return;
-	}
-
-      ret_type = resolved->clone ();
-      ret_type->set_ref (
-	function.get_return_type ()->get_mappings ().get_hirid ());
-    }
-
-  std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
-  for (auto &param : function.get_function_params ())
-    {
-      // get the name as well required for later on
-      auto param_tyty = TypeCheckType::Resolve (param.get_type ());
-      params.push_back (
-	std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (),
-						     param_tyty));
-
-      context->insert_type (param.get_mappings (), param_tyty);
-      TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok
-    = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (),
-				       &canonical_path);
-  rust_assert (ok);
-
-  RustIdent ident{*canonical_path, function.get_locus ()};
-  auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
-				  function.get_mappings ().get_defid (),
-				  function.get_function_name (), ident,
-				  TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST,
-				  std::move (params), ret_type,
-				  std::move (substitutions));
-  context->insert_type (function.get_mappings (), fnType);
+  infered = TypeCheckItem::Resolve (function);
+}
 
-  TyTy::FnType *resolved_fn_type = fnType;
-  auto expected_ret_tyty = resolved_fn_type->get_return_type ();
-  context->push_return_type (TypeCheckContextItem (&function),
-			     expected_ret_tyty);
+void
+TypeCheckStmt::visit (HIR::Module &module)
+{
+  infered = TypeCheckItem::Resolve (module);
+}
 
-  auto block_expr_ty
-    = TypeCheckExpr::Resolve (function.get_definition ().get ());
+void
+TypeCheckStmt::visit (HIR::TypeAlias &type_alias)
+{
+  infered = TypeCheckItem::Resolve (type_alias);
+}
 
-  context->pop_return_type ();
+void
+TypeCheckStmt::visit (HIR::StaticItem &static_item)
+{
+  infered = TypeCheckItem::Resolve (static_item);
+}
 
-  Location fn_return_locus = function.has_function_return_type ()
-			       ? function.get_return_type ()->get_locus ()
-			       : function.get_locus ();
-  coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
-		 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
-		 TyTy::TyWithLocation (block_expr_ty),
-		 function.get_definition ()->get_locus ());
+void
+TypeCheckStmt::visit (HIR::Trait &trait)
+{
+  infered = TypeCheckItem::Resolve (trait);
+}
 
-  infered = fnType;
+void
+TypeCheckStmt::visit (HIR::ImplBlock &impl)
+{
+  infered = TypeCheckItem::Resolve (impl);
 }
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index a79f17a59ce..5d894a7e703 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -40,50 +40,32 @@ public:
   void visit (HIR::StructStruct &struct_decl) override;
   void visit (HIR::Union &union_decl) override;
   void visit (HIR::Function &function) override;
+  void visit (HIR::Module &module) override;
+  void visit (HIR::TypeAlias &type_alias) override;
+  void visit (HIR::StaticItem &static_item) override;
+  void visit (HIR::Trait &trait) override;
+  void visit (HIR::ImplBlock &impl) override;
+  void visit (HIR::TypePath &path) override;
+  void visit (HIR::QualifiedPathInType &path) override;
 
-  void visit (HIR::EnumItemTuple &) override
-  { /* TODO? */
-  }
-  void visit (HIR::EnumItemStruct &) override
-  { /* TODO? */
-  }
-  void visit (HIR::EnumItem &item) override
-  { /* TODO? */
-  }
-  void visit (HIR::EnumItemDiscriminant &) override
-  { /* TODO? */
-  }
+  // FIXME
+  // this seems like it should not be part of this visitor
   void visit (HIR::TypePathSegmentFunction &segment) override
-  { /* TODO? */
-  }
-  void visit (HIR::TypePath &path) override
-  { /* TODO? */
-  }
-  void visit (HIR::QualifiedPathInType &path) override
-  { /* TODO? */
-  }
-  void visit (HIR::Module &module) override
-  { /* TODO? */
-  }
-  void visit (HIR::ExternCrate &crate) override
-  { /* TODO? */
-  }
-  void visit (HIR::UseDeclaration &use_decl) override
-  { /* TODO? */
-  }
-  void visit (HIR::TypeAlias &type_alias) override
-  { /* TODO? */
-  }
-  void visit (HIR::StaticItem &static_item) override
-  { /* TODO? */
-  }
-  void visit (HIR::Trait &trait) override
-  { /* TODO? */
-  }
-  void visit (HIR::ImplBlock &impl) override
-  { /* TODO? */
+  {
+    gcc_unreachable ();
   }
 
+  // nothing to do for these
+  void visit (HIR::ExternCrate &crate) override {}
+  void visit (HIR::UseDeclaration &use_decl) override {}
+
+  // nothing to do for these as they are taken care of by the
+  // hir-type-check-enumitem.h
+  void visit (HIR::EnumItemTuple &) override {}
+  void visit (HIR::EnumItemStruct &) override {}
+  void visit (HIR::EnumItem &) override {}
+  void visit (HIR::EnumItemDiscriminant &) override {}
+
 private:
   TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {}
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc
deleted file mode 100644
index a2113d00a97..00000000000
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-hir-type-check-toplevel.h"
-#include "rust-hir-type-check-enumitem.h"
-#include "rust-hir-type-check-type.h"
-#include "rust-hir-type-check-expr.h"
-#include "rust-hir-type-check-pattern.h"
-#include "rust-hir-type-check-implitem.h"
-
-namespace Rust {
-namespace Resolver {
-
-TypeCheckTopLevel::TypeCheckTopLevel () : TypeCheckBase () {}
-
-void
-TypeCheckTopLevel::Resolve (HIR::Item &item)
-{
-  rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
-  HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
-
-  TypeCheckTopLevel resolver;
-  vis_item.accept_vis (resolver);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::TypeAlias &alias)
-{
-  TyTy::BaseType *actual_type
-    = TypeCheckType::Resolve (alias.get_type_aliased ().get ());
-
-  context->insert_type (alias.get_mappings (), actual_type);
-
-  for (auto &where_clause_item : alias.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-}
-
-void
-TypeCheckTopLevel::visit (HIR::TupleStruct &struct_decl)
-{
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (struct_decl.has_generics ())
-    resolve_generic_params (struct_decl.get_generic_params (), substitutions);
-
-  for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-
-  std::vector<TyTy::StructFieldType *> fields;
-  size_t idx = 0;
-  for (auto &field : struct_decl.get_fields ())
-    {
-      TyTy::BaseType *field_type
-	= TypeCheckType::Resolve (field.get_field_type ().get ());
-      TyTy::StructFieldType *ty_field
-	= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
-				     std::to_string (idx), field_type,
-				     field.get_locus ());
-      fields.push_back (ty_field);
-      context->insert_type (field.get_mappings (), ty_field->get_field_type ());
-      idx++;
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok = mappings->lookup_canonical_path (
-    struct_decl.get_mappings ().get_nodeid (), &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, struct_decl.get_locus ()};
-
-  // its a single variant ADT
-  std::vector<TyTy::VariantDef *> variants;
-  variants.push_back (new TyTy::VariantDef (
-    struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
-    ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields)));
-
-  // Process #[repr(X)] attribute, if any
-  const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
-  TyTy::ADTType::ReprOptions repr
-    = parse_repr_options (attrs, struct_decl.get_locus ());
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 struct_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::TUPLE_STRUCT,
-			 std::move (variants), std::move (substitutions), repr);
-
-  context->insert_type (struct_decl.get_mappings (), type);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::Module &module)
-{
-  for (auto &item : module.get_items ())
-    TypeCheckTopLevel::Resolve (*item.get ());
-}
-
-void
-TypeCheckTopLevel::visit (HIR::StructStruct &struct_decl)
-{
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (struct_decl.has_generics ())
-    resolve_generic_params (struct_decl.get_generic_params (), substitutions);
-
-  for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-
-  std::vector<TyTy::StructFieldType *> fields;
-  for (auto &field : struct_decl.get_fields ())
-    {
-      TyTy::BaseType *field_type
-	= TypeCheckType::Resolve (field.get_field_type ().get ());
-      TyTy::StructFieldType *ty_field
-	= new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
-				     field.get_field_name (), field_type,
-				     field.get_locus ());
-      fields.push_back (ty_field);
-      context->insert_type (field.get_mappings (), ty_field->get_field_type ());
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok = mappings->lookup_canonical_path (
-    struct_decl.get_mappings ().get_nodeid (), &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, struct_decl.get_locus ()};
-
-  // its a single variant ADT
-  std::vector<TyTy::VariantDef *> variants;
-  variants.push_back (new TyTy::VariantDef (
-    struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (),
-    ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
-
-  // Process #[repr(X)] attribute, if any
-  const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
-  TyTy::ADTType::ReprOptions repr
-    = parse_repr_options (attrs, struct_decl.get_locus ());
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 struct_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::STRUCT_STRUCT,
-			 std::move (variants), std::move (substitutions), repr);
-
-  context->insert_type (struct_decl.get_mappings (), type);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::Enum &enum_decl)
-{
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (enum_decl.has_generics ())
-    resolve_generic_params (enum_decl.get_generic_params (), substitutions);
-
-  std::vector<TyTy::VariantDef *> variants;
-  int64_t discriminant_value = 0;
-  for (auto &variant : enum_decl.get_variants ())
-    {
-      TyTy::VariantDef *field_type
-	= TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
-
-      discriminant_value++;
-      variants.push_back (field_type);
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok
-    = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
-				       &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, enum_decl.get_locus ()};
-
-  // multi variant ADT
-  TyTy::BaseType *type
-    = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 enum_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::ENUM, std::move (variants),
-			 std::move (substitutions));
-
-  context->insert_type (enum_decl.get_mappings (), type);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::Union &union_decl)
-{
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (union_decl.has_generics ())
-    resolve_generic_params (union_decl.get_generic_params (), substitutions);
-
-  for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-
-  std::vector<TyTy::StructFieldType *> fields;
-  for (auto &variant : union_decl.get_variants ())
-    {
-      TyTy::BaseType *variant_type
-	= TypeCheckType::Resolve (variant.get_field_type ().get ());
-      TyTy::StructFieldType *ty_variant
-	= new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
-				     variant.get_field_name (), variant_type,
-				     variant.get_locus ());
-      fields.push_back (ty_variant);
-      context->insert_type (variant.get_mappings (),
-			    ty_variant->get_field_type ());
-    }
-
-  // get the path
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok
-    = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
-				       &canonical_path);
-  rust_assert (ok);
-  RustIdent ident{*canonical_path, union_decl.get_locus ()};
-
-  // there is only a single variant
-  std::vector<TyTy::VariantDef *> variants;
-  variants.push_back (new TyTy::VariantDef (
-    union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (),
-    ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields)));
-
-  TyTy::BaseType *type
-    = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (),
-			 mappings->get_next_hir_id (),
-			 union_decl.get_identifier (), ident,
-			 TyTy::ADTType::ADTKind::UNION, std::move (variants),
-			 std::move (substitutions));
-
-  context->insert_type (union_decl.get_mappings (), type);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::StaticItem &var)
-{
-  TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
-  TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
-
-  TyTy::BaseType *unified
-    = coercion_site (var.get_mappings ().get_hirid (),
-		     TyTy::TyWithLocation (type, var.get_type ()->get_locus ()),
-		     TyTy::TyWithLocation (expr_type,
-					   var.get_expr ()->get_locus ()),
-		     var.get_locus ());
-  context->insert_type (var.get_mappings (), unified);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::ConstantItem &constant)
-{
-  TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
-  TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
-
-  TyTy::BaseType *unified = unify_site (
-    constant.get_mappings ().get_hirid (),
-    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
-    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
-    constant.get_locus ());
-  context->insert_type (constant.get_mappings (), unified);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::Function &function)
-{
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (function.has_generics ())
-    resolve_generic_params (function.get_generic_params (), substitutions);
-
-  for (auto &where_clause_item : function.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-
-  TyTy::BaseType *ret_type = nullptr;
-  if (!function.has_function_return_type ())
-    ret_type
-      = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
-  else
-    {
-      auto resolved
-	= TypeCheckType::Resolve (function.get_return_type ().get ());
-      if (resolved->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (function.get_locus (),
-			 "failed to resolve return type");
-	  return;
-	}
-
-      ret_type = resolved->clone ();
-      ret_type->set_ref (
-	function.get_return_type ()->get_mappings ().get_hirid ());
-    }
-
-  std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *>> params;
-  for (auto &param : function.get_function_params ())
-    {
-      // get the name as well required for later on
-      auto param_tyty = TypeCheckType::Resolve (param.get_type ());
-      params.push_back (
-	std::pair<HIR::Pattern *, TyTy::BaseType *> (param.get_param_name (),
-						     param_tyty));
-
-      context->insert_type (param.get_mappings (), param_tyty);
-      TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
-    }
-
-  const CanonicalPath *canonical_path = nullptr;
-  bool ok
-    = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (),
-				       &canonical_path);
-  rust_assert (ok);
-
-  RustIdent ident{*canonical_path, function.get_locus ()};
-  auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
-				  function.get_mappings ().get_defid (),
-				  function.get_function_name (), ident,
-				  TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST,
-				  std::move (params), ret_type,
-				  std::move (substitutions));
-
-  context->insert_type (function.get_mappings (), fnType);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::ImplBlock &impl_block)
-{
-  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  if (impl_block.has_generics ())
-    resolve_generic_params (impl_block.get_generic_params (), substitutions);
-
-  for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
-    {
-      ResolveWhereClauseItem::Resolve (*where_clause_item.get ());
-    }
-
-  auto self = TypeCheckType::Resolve (impl_block.get_type ().get ());
-  if (self->get_kind () == TyTy::TypeKind::ERROR)
-    return;
-
-  for (auto &impl_item : impl_block.get_impl_items ())
-    TypeCheckTopLevelImplItem::Resolve (impl_item.get (), self, substitutions);
-}
-
-void
-TypeCheckTopLevel::visit (HIR::ExternBlock &extern_block)
-{
-  for (auto &item : extern_block.get_extern_items ())
-    {
-      TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block);
-    }
-}
-
-} // namespace Resolver
-} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
deleted file mode 100644
index d0db07d7281..00000000000
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_HIR_TYPE_CHECK_TOPLEVEL
-#define RUST_HIR_TYPE_CHECK_TOPLEVEL
-
-#include "rust-hir-type-check-base.h"
-
-namespace Rust {
-namespace Resolver {
-
-class TypeCheckTopLevel : private TypeCheckBase, public HIR::HIRVisItemVisitor
-{
-public:
-  static void Resolve (HIR::Item &item);
-
-  void visit (HIR::Module &module) override;
-  void visit (HIR::Function &function) override;
-  void visit (HIR::TypeAlias &alias) override;
-  void visit (HIR::TupleStruct &struct_decl) override;
-  void visit (HIR::StructStruct &struct_decl) override;
-  void visit (HIR::Enum &enum_decl) override;
-  void visit (HIR::Union &union_decl) override;
-  void visit (HIR::StaticItem &var) override;
-  void visit (HIR::ConstantItem &constant) override;
-  void visit (HIR::ImplBlock &impl_block) override;
-  void visit (HIR::ExternBlock &extern_block) override;
-
-  // nothing to do
-  void visit (HIR::Trait &trait_block) override {}
-  void visit (HIR::ExternCrate &crate) override {}
-  void visit (HIR::UseDeclaration &use_decl) override {}
-
-private:
-  TypeCheckTopLevel ();
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_HIR_TYPE_CHECK_TOPLEVEL
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 37bcd47b105..a47d40e092f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -48,6 +48,14 @@ TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic)
 TyTy::BaseType *
 TypeCheckType::Resolve (HIR::Type *type)
 {
+  // is it already resolved?
+  auto context = TypeCheckContext::get ();
+  TyTy::BaseType *resolved = nullptr;
+  bool already_resolved
+    = context->lookup_type (type->get_mappings ().get_hirid (), &resolved);
+  if (already_resolved)
+    return resolved;
+
   TypeCheckType resolver (type->get_mappings ().get_hirid ());
   type->accept_vis (resolver);
   rust_assert (resolver.translated != nullptr);
@@ -103,77 +111,29 @@ TypeCheckType::visit (HIR::TupleType &tuple)
 void
 TypeCheckType::visit (HIR::TypePath &path)
 {
-  // lookup the Node this resolves to
-  NodeId ref;
-  auto nid = path.get_mappings ().get_nodeid ();
-  bool is_fully_resolved = resolver->lookup_resolved_type (nid, &ref);
-
-  TyTy::BaseType *lookup = nullptr;
-  if (!is_fully_resolved)
-    {
-      // this can happen so we need to look up the root then resolve the
-      // remaining segments if possible
-      size_t offset = 0;
-      NodeId resolved_node_id = UNKNOWN_NODEID;
-      TyTy::BaseType *root
-	= resolve_root_path (path, &offset, &resolved_node_id);
-
-      rust_assert (root != nullptr);
-      if (root->get_kind () == TyTy::TypeKind::ERROR)
-	return;
-
-      translated
-	= resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (),
-			    path.get_segments (), offset, root,
-			    path.get_mappings (), path.get_locus ());
-      return;
-    }
-
-  HirId hir_lookup;
-  if (!context->lookup_type_by_node_id (ref, &hir_lookup))
-    {
-      rust_error_at (path.get_locus (), "failed to lookup HIR %d for node '%s'",
-		     ref, path.as_string ().c_str ());
-      return;
-    }
-
-  if (!context->lookup_type (hir_lookup, &lookup))
-    {
-      rust_error_at (path.get_locus (), "failed to lookup HIR TyTy");
-      return;
-    }
+  // this can happen so we need to look up the root then resolve the
+  // remaining segments if possible
+  size_t offset = 0;
+  NodeId resolved_node_id = UNKNOWN_NODEID;
+  TyTy::BaseType *root = resolve_root_path (path, &offset, &resolved_node_id);
+  if (root->get_kind () == TyTy::TypeKind::ERROR)
+    return;
 
-  TyTy::BaseType *path_type = lookup->clone ();
+  TyTy::BaseType *path_type = root->clone ();
   path_type->set_ref (path.get_mappings ().get_hirid ());
+  context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type);
 
-  HIR::TypePathSegment *final_seg = path.get_final_segment ().get ();
-  HIR::GenericArgs args = TypeCheckResolveGenericArguments::resolve (final_seg);
-
-  bool is_big_self = final_seg->is_ident_only ()
-		     && (final_seg->as_string ().compare ("Self") == 0);
-
-  if (path_type->needs_generic_substitutions ())
-    {
-      if (is_big_self)
-	{
-	  translated = path_type;
-	  return;
-	}
-
-      translated = SubstMapper::Resolve (path_type, path.get_locus (), &args);
-    }
-  else if (!args.is_empty ())
-    {
-      rust_error_at (path.get_locus (),
-		     "TypePath %s declares generic arguments but "
-		     "the type %s does not have any",
-		     path.as_string ().c_str (),
-		     path_type->as_string ().c_str ());
-    }
-  else
+  bool fully_resolved = offset >= path.get_segments ().size ();
+  if (fully_resolved)
     {
       translated = path_type;
+      return;
     }
+
+  translated
+    = resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (),
+			path.get_segments (), offset, path_type,
+			path.get_mappings (), path.get_locus ());
 }
 
 void
@@ -389,7 +349,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
 	}
 
       TyTy::BaseType *lookup = nullptr;
-      if (!context->lookup_type (ref, &lookup))
+      if (!query_type (ref, &lookup))
 	{
 	  if (is_root)
 	    {
@@ -428,14 +388,22 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
 
 	  if (!lookup->can_substitute ())
 	    {
-	      rust_error_at (seg->get_locus (),
-			     "substitutions not supported for %s",
+	      rust_error_at (path.get_locus (),
+			     "TypePath %s declares generic arguments but the "
+			     "type %s does not have any",
+			     path.as_string ().c_str (),
 			     lookup->as_string ().c_str ());
 	      return new TyTy::ErrorType (lookup->get_ref ());
 	    }
 	  lookup = SubstMapper::Resolve (lookup, path.get_locus (),
 					 &generic_segment->get_generic_args ());
 	}
+      else if (lookup->needs_generic_substitutions ())
+	{
+	  HIR::GenericArgs empty
+	    = HIR::GenericArgs::create_empty (path.get_locus ());
+	  lookup = SubstMapper::Resolve (lookup, path.get_locus (), &empty);
+	}
 
       *root_resolved_node_id = ref_node_id;
       *offset = *offset + 1;
@@ -531,7 +499,7 @@ TypeCheckType::resolve_segments (
   context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
   if (tyseg->needs_generic_substitutions ())
     {
-      Location locus = segments.back ()->get_locus ();
+      // Location locus = segments.back ()->get_locus ();
       if (!prev_segment->needs_generic_substitutions ())
 	{
 	  auto used_args_in_prev_segment
@@ -540,10 +508,6 @@ TypeCheckType::resolve_segments (
 	    tyseg
 	      = SubstMapperInternal::Resolve (tyseg, used_args_in_prev_segment);
 	}
-      else
-	{
-	  tyseg = SubstMapper::InferSubst (tyseg, locus);
-	}
 
       if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
 	return new TyTy::ErrorType (expr_id);
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 2fe09c1fc7f..a85ea5c8491 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -18,7 +18,6 @@
 
 #include "rust-hir-type-check.h"
 #include "rust-hir-full.h"
-#include "rust-hir-type-check-toplevel.h"
 #include "rust-hir-type-check-item.h"
 #include "rust-hir-type-check-expr.h"
 #include "rust-hir-type-check-pattern.h"
@@ -35,7 +34,7 @@ void
 TypeResolution::Resolve (HIR::Crate &crate)
 {
   for (auto it = crate.items.begin (); it != crate.items.end (); it++)
-    TypeCheckTopLevel::Resolve (*it->get ());
+    TypeCheckItem::Resolve (*it->get ());
 
   if (saw_errors ())
     return;
@@ -44,12 +43,6 @@ TypeResolution::Resolve (HIR::Crate &crate)
   if (saw_errors ())
     return;
 
-  for (auto it = crate.items.begin (); it != crate.items.end (); it++)
-    TypeCheckItem::Resolve (*it->get ());
-
-  if (saw_errors ())
-    return;
-
   auto mappings = Analysis::Mappings::get ();
   auto context = TypeCheckContext::get ();
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 21694dd302b..c17db71aec7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -337,6 +337,41 @@ public:
     return true;
   }
 
+  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;
+  }
+
 private:
   TypeCheckContext ();
 
@@ -365,6 +400,12 @@ private:
 
   // variants
   std::map<HirId, HirId> variants;
+
+  // unconstrained type-params check
+  std::map<HirId, bool> unconstrained;
+
+  // predicates
+  std::map<HirId, TyTy::TypeBoundPredicate> predicates;
 };
 
 class TypeResolution
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 028e10c0efe..e326bbd94d9 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -102,7 +102,7 @@ public:
     if (!have_generic_args ())
       {
 	TyTy::BaseType *substs = type.infer_substitions (locus);
-	rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
+	rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
 	concrete = static_cast<TyTy::ProjectionType *> (substs);
       }
     else
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 811d64bd740..ec4a11fb592 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -18,6 +18,7 @@
 
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
+#include "rust-hir-type-check-item.h"
 
 namespace Rust {
 namespace Resolver {
@@ -33,11 +34,8 @@ TypeBoundsProbe::scan ()
       if (!impl->has_trait_ref ())
 	return true;
 
-      TyTy::BaseType *impl_type = nullptr;
-      bool ok
-	= context->lookup_type (impl->get_type ()->get_mappings ().get_hirid (),
-				&impl_type);
-      if (!ok)
+      TyTy::BaseType *impl_type = TypeCheckItem::ResolveImplBlockSelf (*impl);
+      if (impl_type->get_kind () == TyTy::TypeKind::ERROR)
 	return true;
 
       if (!receiver->can_eq (impl_type, false))
@@ -69,6 +67,13 @@ TypeCheckBase::resolve_trait_path (HIR::TypePath &path)
 TyTy::TypeBoundPredicate
 TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
 {
+  TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
+  bool already_resolved
+    = context->lookup_predicate (type_path.get_mappings ().get_hirid (),
+				 &lookup);
+  if (already_resolved)
+    return lookup;
+
   TraitReference *trait = resolve_trait_path (type_path);
   if (trait->is_error ())
     return TyTy::TypeBoundPredicate::error ();
@@ -94,6 +99,8 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
       predicate.apply_generic_arguments (&args);
     }
 
+  context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
+				      predicate);
   return predicate;
 }
 
@@ -470,6 +477,13 @@ TypeBoundsMappings::raw_bounds_as_name () const
 void
 TypeBoundsMappings::add_bound (TypeBoundPredicate predicate)
 {
+  for (auto &bound : specified_bounds)
+    {
+      bool same_trait_ref_p = bound.get_id () == predicate.get_id ();
+      if (same_trait_ref_p)
+	return;
+    }
+
   specified_bounds.push_back (predicate);
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index f99a90e11b7..1e5dcb5a2e3 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -1358,6 +1358,8 @@ public:
   // generic arguments
   void visit (const ParamType &) override { ok = true; }
 
+  void visit (const TupleType &) override { ok = true; }
+
   void visit (const InferType &) override { ok = true; }
 
   void visit (const FnType &) override { ok = true; }
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 7cb425458d6..b9a93186208 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -208,9 +208,6 @@ void
 BaseType::inherit_bounds (
   const std::vector<TyTy::TypeBoundPredicate> &specified_bounds)
 {
-  // FIXME
-  // 1. This needs to union the bounds
-  // 2. Do some checking for trait polarity to ensure compatibility
   for (auto &bound : specified_bounds)
     {
       add_bound (bound);
@@ -754,6 +751,40 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args)
   return SubstitutionArgumentMappings (mappings, args.get_locus ());
 }
 
+BaseType *
+SubstitutionRef::infer_substitions (Location locus)
+{
+  std::vector<SubstitutionArg> args;
+  std::map<std::string, BaseType *> argument_mappings;
+  for (auto &p : get_substs ())
+    {
+      if (p.needs_substitution ())
+	{
+	  const std::string &symbol = p.get_param_ty ()->get_symbol ();
+	  auto it = argument_mappings.find (symbol);
+	  bool have_mapping = it != argument_mappings.end ();
+
+	  if (have_mapping)
+	    {
+	      args.push_back (SubstitutionArg (&p, it->second));
+	    }
+	  else
+	    {
+	      TyVar infer_var = TyVar::get_implicit_infer_var (locus);
+	      args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+	      argument_mappings[symbol] = infer_var.get_tyty ();
+	    }
+	}
+      else
+	{
+	  args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
+	}
+    }
+
+  SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
+  return handle_substitions (std::move (infer_arguments));
+}
+
 SubstitutionArgumentMappings
 SubstitutionRef::adjust_mappings_for_this (
   SubstitutionArgumentMappings &mappings)
@@ -2479,7 +2510,13 @@ ParamType::resolve () const
 	break;
 
       TyVar v (rr->get_ty_ref ());
-      r = v.get_tyty ();
+      BaseType *n = v.get_tyty ();
+
+      // fix infinite loop
+      if (r == n)
+	break;
+
+      r = n;
     }
 
   if (r->get_kind () == TypeKind::PARAM && (r->get_ref () == r->get_ty_ref ()))
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 74c8c354897..cad1a1d01de 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -960,37 +960,7 @@ public:
   solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to);
 
   // TODO comment
-  BaseType *infer_substitions (Location locus)
-  {
-    std::vector<SubstitutionArg> args;
-    std::map<std::string, BaseType *> argument_mappings;
-    for (auto &p : get_substs ())
-      {
-	if (p.needs_substitution ())
-	  {
-	    const std::string &symbol = p.get_param_ty ()->get_symbol ();
-	    auto it = argument_mappings.find (symbol);
-	    if (it == argument_mappings.end ())
-	      {
-		TyVar infer_var = TyVar::get_implicit_infer_var (locus);
-		args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
-		argument_mappings[symbol] = infer_var.get_tyty ();
-	      }
-	    else
-	      {
-		args.push_back (SubstitutionArg (&p, it->second));
-	      }
-	  }
-	else
-	  {
-	    args.push_back (
-	      SubstitutionArg (&p, p.get_param_ty ()->resolve ()));
-	  }
-      }
-
-    SubstitutionArgumentMappings infer_arguments (std::move (args), locus);
-    return handle_substitions (std::move (infer_arguments));
-  }
+  BaseType *infer_substitions (Location locus);
 
   // TODO comment
   bool monomorphize ();
@@ -1059,6 +1029,8 @@ public:
 
   bool contains_associated_types () const;
 
+  DefId get_id () const { return reference; }
+
 private:
   DefId reference;
   Location locus;
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 8705fdcf381..3761d5f01d3 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -419,7 +419,9 @@ Mappings::insert_hir_impl_block (HIR::ImplBlock *item)
   auto id = item->get_mappings ().get_hirid ();
   rust_assert (lookup_hir_impl_block (id) == nullptr);
 
+  HirId impl_type_id = item->get_type ()->get_mappings ().get_hirid ();
   hirImplBlockMappings[id] = item;
+  hirImplBlockTypeMappings[impl_type_id] = item;
   insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
 }
 
@@ -433,6 +435,17 @@ Mappings::lookup_hir_impl_block (HirId id)
   return it->second;
 }
 
+bool
+Mappings::lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block)
+{
+  auto it = hirImplBlockTypeMappings.find (id);
+  if (it == hirImplBlockTypeMappings.end ())
+    return false;
+
+  *impl_block = it->second;
+  return true;
+}
+
 void
 Mappings::insert_module (HIR::Module *module)
 {
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 98fcfe6a6a7..44018489f45 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -123,6 +123,7 @@ public:
 
   void insert_hir_impl_block (HIR::ImplBlock *item);
   HIR::ImplBlock *lookup_hir_impl_block (HirId id);
+  bool lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block);
 
   void insert_module (HIR::Module *module);
   HIR::Module *lookup_module (HirId id);
@@ -314,6 +315,7 @@ private:
   std::map<HirId, HIR::SelfParam *> hirSelfParamMappings;
   std::map<HirId, HIR::ImplBlock *> hirImplItemsToImplMappings;
   std::map<HirId, HIR::ImplBlock *> hirImplBlockMappings;
+  std::map<HirId, HIR::ImplBlock *> hirImplBlockTypeMappings;
   std::map<HirId, HIR::TraitItem *> hirTraitItemMappings;
   std::map<HirId, HIR::ExternBlock *> hirExternBlockMappings;
   std::map<HirId, std::pair<HIR::ExternalItem *, HirId>> hirExternItemMappings;
diff --git a/gcc/testsuite/rust/compile/const_generics_5.rs b/gcc/testsuite/rust/compile/const_generics_5.rs
index 5344e31a140..46cf6c93968 100644
--- a/gcc/testsuite/rust/compile/const_generics_5.rs
+++ b/gcc/testsuite/rust/compile/const_generics_5.rs
@@ -1,12 +1,15 @@
+// bogus errors but shows the type checking system needs to support const
+// generics with defaults
+
 struct Foo<const N: usize = { 14 }>;
 
 const M: usize = 15;
-type N = Foo<3>;
+type N = Foo<3>; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
 
 fn main() {
-    let _: Foo<15> = Foo;
-    let _: Foo<{ M }> = Foo;
-    let _: Foo<M> = Foo;
-    // bogus error, but it means the above const generic gets disambiguated properly
+    let _: Foo<15> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
+    let _: Foo<{ M }> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
+    let _: Foo<M> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" }
+
     let _: Foo<N> = Foo; // { dg-error "TypePath Foo<N> declares generic arguments but the type Foo{Foo {}} does not have any" }
 }
diff --git a/gcc/testsuite/rust/compile/unconstrained_type_param.rs b/gcc/testsuite/rust/compile/unconstrained_type_param.rs
index c4aaa10146f..7fe74c2c798 100644
--- a/gcc/testsuite/rust/compile/unconstrained_type_param.rs
+++ b/gcc/testsuite/rust/compile/unconstrained_type_param.rs
@@ -9,4 +9,6 @@ impl<X, Y> Foo<X> {
 
 fn main() {
     let a = Foo::test();
+    // { dg-error "Failed to resolve expression of function call" "" { target *-*-* } .-1 }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
 }

                 reply	other threads:[~2022-09-27 15:49 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220927154958.451063858029@sourceware.org \
    --to=tschwinge@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).