public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] This patch implements complex Path resolution
@ 2022-06-14  8:03 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-14  8:03 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7ca7362602d4e827ecbc39d5cfdf56df9044633b

commit 7ca7362602d4e827ecbc39d5cfdf56df9044633b
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Fri Jun 3 15:12:00 2022 +0100

    This patch implements complex Path resolution
    
    This patch completely reimplements our name resolution process for Paths in
    general. This patch gets rid of the old Resolver::Definition structures
    which were used so that we can map patterns back to LetStmts and establish
    an hierarchy of nodes. This was not nessecary and complicated name/type
    resolution.
    
    TypePaths and PathInExpression are similar but have a slightl tweak in the
    order they lookup the relevant scopes for types. But overall work the same.
    There are several cases of paths you must consider in type resolution:
    
    - i32 (simple type path)
    - Self::A (associated type reference)
    - mod::foo::impl_item() (reference to impl item)
    - super::foo (reference to impl item)
    - crate::foo
    - T::bound()
    
    In name resolution we cannot always fully resolve a path but have to rely
    on the type-resolution to fully resolve a path as it may require careful
    thought. For example a path like:
    
      mod::foo::item()
    
    might be for a generic foo<T>(), which might have two specialized impl
    blocks so the best the name resolution can do is resolve mod::foo then
    leave it up to the type resolution to figure out which item this is. We
    might have i32 which is just a simple lookup.
    
    Apart from that this patch introduces a module parent child hierachy so
    that on paths such as super::foo we resolve super to be our parent module
    scope then foo can be resolved with the lookup in the items for that
    module.
    
    More over this patch gets rid of some but not all of the awkward name
    canonicalization to try and patch paths directly. More cleanup is still
    needed here to make the name resolution step easier to read. This was
    notable in the Qualified path handling where we can now rely on the type
    resolver to setup the associated types properly rather than the name
    resolver requiring us to resolve this directly.
    
    Fixes #1251 #1230
    Addresses #1227 #1153

Diff:
---
 gcc/rust/ast/rust-ast.h                           |  12 +-
 gcc/rust/ast/rust-path.h                          |  54 ++-
 gcc/rust/backend/rust-compile-base.cc             |  56 ++-
 gcc/rust/backend/rust-compile-expr.cc             |  10 -
 gcc/rust/backend/rust-compile-expr.h              |   4 +-
 gcc/rust/backend/rust-compile-resolve-path.cc     |  18 +-
 gcc/rust/backend/rust-compile-stmt.h              |   8 +-
 gcc/rust/backend/rust-compile-var-decl.h          |  70 +--
 gcc/rust/hir/rust-ast-lower.cc                    |   2 +-
 gcc/rust/lint/rust-lint-marklive.cc               |  23 +-
 gcc/rust/privacy/rust-visibility-resolver.cc      |   6 -
 gcc/rust/resolve/rust-ast-resolve-expr.cc         |  13 -
 gcc/rust/resolve/rust-ast-resolve-implitem.h      |  30 +-
 gcc/rust/resolve/rust-ast-resolve-item.cc         |   2 +
 gcc/rust/resolve/rust-ast-resolve-path.cc         | 533 +++++++++++-----------
 gcc/rust/resolve/rust-ast-resolve-path.h          |  14 -
 gcc/rust/resolve/rust-ast-resolve-pattern.cc      |   4 +-
 gcc/rust/resolve/rust-ast-resolve-pattern.h       |  11 +-
 gcc/rust/resolve/rust-ast-resolve-stmt.h          |   6 -
 gcc/rust/resolve/rust-ast-resolve-toplevel.h      |  27 +-
 gcc/rust/resolve/rust-ast-resolve-type.cc         | 186 +++++++-
 gcc/rust/resolve/rust-ast-resolve-type.h          |  94 +---
 gcc/rust/resolve/rust-ast-resolve.cc              |  34 +-
 gcc/rust/resolve/rust-name-resolver.cc            |  54 ++-
 gcc/rust/resolve/rust-name-resolver.h             |  47 +-
 gcc/rust/rust-session-manager.cc                  |   3 +
 gcc/rust/typecheck/rust-hir-type-check-expr.h     |  27 +-
 gcc/rust/typecheck/rust-hir-type-check-path.cc    | 147 +++---
 gcc/rust/typecheck/rust-hir-type-check-pattern.cc |   6 +
 gcc/rust/typecheck/rust-hir-type-check-pattern.h  |   2 +
 gcc/rust/typecheck/rust-hir-type-check-stmt.h     |  34 +-
 gcc/rust/typecheck/rust-hir-type-check-type.cc    |  92 ++--
 gcc/rust/typecheck/rust-tycheck-dump.h            |   2 +-
 gcc/rust/util/rust-hir-map.cc                     |  40 ++
 gcc/rust/util/rust-hir-map.h                      |   4 +
 gcc/testsuite/rust/compile/complex-path1.rs       |  18 +
 gcc/testsuite/rust/compile/issue-1251.rs          |  14 +
 37 files changed, 895 insertions(+), 812 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 69ad6eb13fd..8f5657f0960 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -350,8 +350,16 @@ public:
   Location get_locus () const { return locus; }
   NodeId get_node_id () const { return node_id; }
   const std::string &get_segment_name () const { return segment_name; }
-
-  // TODO: visitor pattern?
+  bool is_super_path_seg () const
+  {
+    return as_string ().compare ("super") == 0;
+  }
+  bool is_crate_path_seg () const
+  {
+    return as_string ().compare ("crate") == 0;
+  }
+  bool is_lower_self () const { return as_string ().compare ("self") == 0; }
+  bool is_big_self () const { return as_string ().compare ("Self") == 0; }
 };
 
 // A simple path without generic or type arguments
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 593f9791f90..45d08bfbaa9 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -38,12 +38,6 @@ public:
     : segment_name (std::move (segment_name)), locus (locus)
   {}
 
-  /* TODO: insert check in constructor for this? Or is this a semantic error
-   * best handled then? */
-
-  /* TODO: does this require visitor? pretty sure this isn't polymorphic, but
-   * not entirely sure */
-
   // Creates an error PathIdentSegment.
   static PathIdentSegment create_error ()
   {
@@ -54,6 +48,11 @@ public:
   bool is_error () const { return segment_name.empty (); }
 
   std::string as_string () const { return segment_name; }
+
+  bool is_super_segment () const { return as_string ().compare ("super") == 0; }
+  bool is_crate_segment () const { return as_string ().compare ("crate") == 0; }
+  bool is_lower_self () const { return as_string ().compare ("self") == 0; }
+  bool is_big_self () const { return as_string ().compare ("Self") == 0; }
 };
 
 // A binding of an identifier to a type used in generic arguments in paths
@@ -264,8 +263,23 @@ public:
   }
 
   PathIdentSegment &get_ident_segment () { return segment_name; }
+  const PathIdentSegment &get_ident_segment () const { return segment_name; }
 
   NodeId get_node_id () const { return node_id; }
+
+  bool is_super_path_seg () const
+  {
+    return !has_generic_args () && get_ident_segment ().is_super_segment ();
+  }
+
+  bool is_crate_path_seg () const
+  {
+    return !has_generic_args () && get_ident_segment ().is_crate_segment ();
+  }
+  bool is_lower_self_seg () const
+  {
+    return !has_generic_args () && get_ident_segment ().is_lower_self ();
+  }
 };
 
 // AST node representing a pattern that involves a "path" - abstract base class
@@ -397,6 +411,15 @@ protected:
  * ident-only segment) */
 class TypePathSegment
 {
+public:
+  enum SegmentType
+  {
+    REG,
+    GENERIC,
+    FUNCTION
+  };
+
+private:
   PathIdentSegment ident_segment;
   Location locus;
 
@@ -415,6 +438,8 @@ protected:
 public:
   virtual ~TypePathSegment () {}
 
+  virtual SegmentType get_type () const { return SegmentType::REG; }
+
   // Unique pointer custom clone function
   std::unique_ptr<TypePathSegment> clone_type_path_segment () const
   {
@@ -456,9 +481,20 @@ public:
     return has_separating_scope_resolution;
   }
 
-  PathIdentSegment get_ident_segment () { return ident_segment; };
+  PathIdentSegment &get_ident_segment () { return ident_segment; };
+  const PathIdentSegment &get_ident_segment () const { return ident_segment; };
 
   NodeId get_node_id () const { return node_id; }
+
+  bool is_crate_path_seg () const
+  {
+    return get_ident_segment ().is_crate_segment ();
+  }
+  bool is_super_path_seg () const
+  {
+    return get_ident_segment ().is_super_segment ();
+  }
+  bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
 };
 
 // Segment used in type path with generic args
@@ -467,6 +503,8 @@ class TypePathSegmentGeneric : public TypePathSegment
   GenericArgs generic_args;
 
 public:
+  SegmentType get_type () const override { return SegmentType::GENERIC; }
+
   bool has_generic_args () const { return generic_args.has_generic_args (); }
 
   bool is_ident_only () const override { return false; }
@@ -620,6 +658,8 @@ class TypePathSegmentFunction : public TypePathSegment
   TypePathFunction function_path;
 
 public:
+  SegmentType get_type () const override { return SegmentType::FUNCTION; }
+
   // Constructor with PathIdentSegment and TypePathFn
   TypePathSegmentFunction (PathIdentSegment ident_segment,
 			   bool has_separating_scope_resolution,
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 3de80d99532..8fa3fa18793 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -333,39 +333,33 @@ std::vector<Bvariable *>
 HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib,
 					  tree fndecl)
 {
+  CrateNum crate = ctx->get_mappings ()->get_current_crate ();
+
   std::vector<Bvariable *> locals;
   for (auto it : rib.get_declarations ())
     {
-      auto node_id = it.first;
-
-      Resolver::Definition d;
-      bool ok = ctx->get_resolver ()->lookup_definition (node_id, &d);
-      rust_assert (ok);
-
-      HIR::Stmt *decl = nullptr;
-      if (!ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl))
-	{
-	  // might be an extern block see fix for
-	  // https://github.com/Rust-GCC/gccrs/issues/976
-	  continue;
-	}
-
-      // if its a function we extract this out side of this fn context
-      // and it is not a local to this function
-      bool is_item = ctx->get_mappings ()->lookup_hir_item (
-		       decl->get_mappings ().get_crate_num (),
-		       decl->get_mappings ().get_hirid ())
-		     != nullptr;
-      if (is_item)
-	{
-	  HIR::Item *item = static_cast<HIR::Item *> (decl);
-	  CompileItem::compile (item, ctx);
-	}
-
-      Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
+      NodeId node_id = it.first;
+      HirId ref = UNKNOWN_HIRID;
+      if (!ctx->get_mappings ()->lookup_node_to_hir (crate, node_id, &ref))
+	continue;
+
+      // we only care about local patterns
+      HIR::Pattern *pattern
+	= ctx->get_mappings ()->lookup_hir_pattern (crate, ref);
+      if (pattern == nullptr)
+	continue;
+
+      // lookup the type
+      TyTy::BaseType *tyty = nullptr;
+      if (!ctx->get_tyctx ()->lookup_type (ref, &tyty))
+	continue;
+
+      // compile the local
+      tree type = TyTyResolveCompile::compile (ctx, tyty);
+      Bvariable *compiled
+	= CompileVarDecl::compile (fndecl, type, pattern, ctx);
       locals.push_back (compiled);
-    };
-
+    }
   return locals;
 }
 
@@ -482,7 +476,9 @@ HIRCompileBase::compile_function (
 				   compiled_param_type, param_locus);
 
       param_vars.push_back (compiled_param_var);
-      ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (),
+
+      const HIR::Pattern &param_pattern = *referenced_param.get_param_name ();
+      ctx->insert_var_decl (param_pattern.get_pattern_mappings ().get_hirid (),
 			    compiled_param_var);
     }
 
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index b7dad12edd4..b153451b470 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1432,16 +1432,6 @@ CompileExpr::visit (HIR::IdentifierExpr &expr)
   NodeId ref_node_id = UNKNOWN_NODEID;
   if (ctx->get_resolver ()->lookup_resolved_name (ast_node_id, &ref_node_id))
     {
-      // these ref_node_ids will resolve to a pattern declaration but we are
-      // interested in the definition that this refers to get the parent id
-      Resolver::Definition def;
-      if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def))
-	{
-	  rust_error_at (expr.get_locus (),
-			 "unknown reference for resolved name");
-	  return;
-	}
-      ref_node_id = def.parent;
       is_value = true;
     }
   else if (!ctx->get_resolver ()->lookup_resolved_type (ast_node_id,
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 593e1f978fe..3b729c78b37 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -512,8 +512,8 @@ public:
 
   void visit (HIR::FieldAccessExpr &expr) override
   {
-    tree receiver_ref
-      = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx);
+    HIR::Expr *receiver_expr = expr.get_receiver_expr ().get ();
+    tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx);
 
     // resolve the receiver back to ADT type
     TyTy::BaseType *receiver = nullptr;
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 44239122379..2cf81e0f9d7 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -53,22 +53,12 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
 
   // need to look up the reference for this identifier
   NodeId ref_node_id = UNKNOWN_NODEID;
-  if (ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
-						  &ref_node_id))
+  if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
+						   &ref_node_id))
     {
-      Resolver::Definition def;
-      if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def))
-	{
-	  rust_error_at (expr_locus, "unknown reference for resolved name");
-	  return error_mark_node;
-	}
-      ref_node_id = def.parent;
-    }
+      // this can fail because it might be a Constructor for something
+      // in that case the caller should attempt ResolvePathType::Compile
 
-  // this can fail because it might be a Constructor for something
-  // in that case the caller should attempt ResolvePathType::Compile
-  if (ref_node_id == UNKNOWN_NODEID)
-    {
       // it might be an enum data-less enum variant
       if (lookup->get_kind () != TyTy::TypeKind::ADT)
 	return error_mark_node;
diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h
index 5f1777736db..aa17a4a4941 100644
--- a/gcc/rust/backend/rust-compile-stmt.h
+++ b/gcc/rust/backend/rust-compile-stmt.h
@@ -51,9 +51,11 @@ public:
     if (!stmt.has_init_expr ())
       return;
 
+    const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
+    HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid ();
+
     TyTy::BaseType *ty = nullptr;
-    if (!ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (),
-					 &ty))
+    if (!ctx->get_tyctx ()->lookup_type (stmt_id, &ty))
       {
 	// FIXME this should be an assertion instead
 	rust_fatal_error (stmt.get_locus (),
@@ -62,7 +64,7 @@ public:
       }
 
     Bvariable *var = nullptr;
-    if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var))
+    if (!ctx->lookup_var_decl (stmt_id, &var))
       {
 	// FIXME this should be an assertion instead and use error mark node
 	rust_fatal_error (stmt.get_locus (),
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 2dab39ee374..e2ee05b8163 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -25,36 +25,19 @@
 namespace Rust {
 namespace Compile {
 
-class CompileVarDecl : public HIRCompileBase,
-		       public HIR::HIRPatternVisitor,
-		       public HIR::HIRStmtVisitor
+class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor
 {
   using HIR::HIRPatternVisitor::visit;
-  using HIR::HIRStmtVisitor::visit;
 
 public:
-  static ::Bvariable *compile (tree fndecl, HIR::Stmt *stmt, Context *ctx)
+  static ::Bvariable *compile (tree fndecl, tree translated_type,
+			       HIR::Pattern *pattern, Context *ctx)
   {
-    CompileVarDecl compiler (ctx, fndecl);
-    stmt->accept_vis (compiler);
-    ctx->insert_var_decl (stmt->get_mappings ().get_hirid (),
-			  compiler.compiled_variable);
+    CompileVarDecl compiler (ctx, fndecl, translated_type);
+    pattern->accept_vis (compiler);
     return compiler.compiled_variable;
   }
 
-  void visit (HIR::LetStmt &stmt) override
-  {
-    locus = stmt.get_locus ();
-    TyTy::BaseType *resolved_type = nullptr;
-    bool ok = ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (),
-					      &resolved_type);
-    rust_assert (ok);
-
-    translated_type = TyTyResolveCompile::compile (ctx, resolved_type);
-    stmt.get_pattern ()->accept_vis (
-      static_cast<HIR::HIRPatternVisitor &> (*this));
-  }
-
   void visit (HIR::IdentifierPattern &pattern) override
   {
     if (!pattern.is_mut ())
@@ -63,7 +46,10 @@ public:
     compiled_variable
       = ctx->get_backend ()->local_variable (fndecl, pattern.get_identifier (),
 					     translated_type, NULL /*decl_var*/,
-					     locus);
+					     pattern.get_locus ());
+
+    HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
+    ctx->insert_var_decl (stmt_id, compiled_variable);
   }
 
   void visit (HIR::WildcardPattern &pattern) override
@@ -72,7 +58,11 @@ public:
 
     compiled_variable
       = ctx->get_backend ()->local_variable (fndecl, "_", translated_type,
-					     NULL /*decl_var*/, locus);
+					     NULL /*decl_var*/,
+					     pattern.get_locus ());
+
+    HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
+    ctx->insert_var_decl (stmt_id, compiled_variable);
   }
 
   // Empty visit for unused Pattern HIR nodes.
@@ -87,41 +77,15 @@ public:
   void visit (HIR::TuplePattern &) override {}
   void visit (HIR::TupleStructPattern &) override {}
 
-  // Empty visit for unused Stmt HIR nodes.
-  void visit (HIR::EnumItemTuple &) override {}
-  void visit (HIR::EnumItemStruct &) override {}
-  void visit (HIR::EnumItem &item) override {}
-  void visit (HIR::TupleStruct &tuple_struct) override {}
-  void visit (HIR::EnumItemDiscriminant &) override {}
-  void visit (HIR::TypePathSegmentFunction &segment) override {}
-  void visit (HIR::TypePath &path) override {}
-  void visit (HIR::QualifiedPathInType &path) override {}
-  void visit (HIR::Module &module) override {}
-  void visit (HIR::ExternCrate &crate) override {}
-  void visit (HIR::UseDeclaration &use_decl) override {}
-  void visit (HIR::Function &function) override {}
-  void visit (HIR::TypeAlias &type_alias) override {}
-  void visit (HIR::StructStruct &struct_item) override {}
-  void visit (HIR::Enum &enum_item) override {}
-  void visit (HIR::Union &union_item) override {}
-  void visit (HIR::ConstantItem &const_item) override {}
-  void visit (HIR::StaticItem &static_item) override {}
-  void visit (HIR::Trait &trait) override {}
-  void visit (HIR::ImplBlock &impl) override {}
-  void visit (HIR::ExternBlock &block) override {}
-  void visit (HIR::EmptyStmt &stmt) override {}
-  void visit (HIR::ExprStmtWithoutBlock &stmt) override {}
-  void visit (HIR::ExprStmtWithBlock &stmt) override {}
-
 private:
-  CompileVarDecl (Context *ctx, tree fndecl)
-    : HIRCompileBase (ctx), fndecl (fndecl), translated_type (error_mark_node),
+  CompileVarDecl (Context *ctx, tree fndecl, tree translated_type)
+    : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type),
       compiled_variable (ctx->get_backend ()->error_variable ())
   {}
 
   tree fndecl;
   tree translated_type;
-  Location locus;
+
   Bvariable *compiled_variable;
 };
 
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index b3b0ee8c465..0072d30d858 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -79,7 +79,7 @@ ASTLowering::go ()
 
   auto mappings = Analysis::Mappings::get ();
   auto crate_num = mappings->get_current_crate ();
-  Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID,
+  Analysis::NodeMapping mapping (crate_num, astCrate.get_node_id (),
 				 mappings->get_next_hir_id (crate_num),
 				 UNKNOWN_LOCAL_DEFID);
 
diff --git a/gcc/rust/lint/rust-lint-marklive.cc b/gcc/rust/lint/rust-lint-marklive.cc
index 3776aea3dd3..2b01abcc06c 100644
--- a/gcc/rust/lint/rust-lint-marklive.cc
+++ b/gcc/rust/lint/rust-lint-marklive.cc
@@ -179,16 +179,10 @@ MarkLive::visit_path_segment (HIR::PathExprSegment seg)
   //
   // We should mark them alive all and ignoring other kind of segments.
   // If the segment we dont care then just return false is fine
-  if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+  if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
     {
-      Resolver::Definition def;
-      bool ok = resolver->lookup_definition (ref_node_id, &def);
-      rust_assert (ok);
-      ref_node_id = def.parent;
-    }
-  else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
-    {
-      return false;
+      if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
+	return false;
     }
   HirId ref;
   bool ok = mappings->lookup_node_to_hir (seg.get_mappings ().get_crate_num (),
@@ -300,16 +294,7 @@ MarkLive::mark_hir_id (HirId id)
 void
 MarkLive::find_ref_node_id (NodeId ast_node_id, NodeId &ref_node_id)
 {
-  if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
-    {
-      // these ref_node_ids will resolve to a pattern declaration but we are
-      // interested in the definition that this refers to get the parent id
-      Resolver::Definition def;
-      bool ok = resolver->lookup_definition (ref_node_id, &def);
-      rust_assert (ok);
-      ref_node_id = def.parent;
-    }
-  else
+  if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
     {
       bool ok = resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
       rust_assert (ok);
diff --git a/gcc/rust/privacy/rust-visibility-resolver.cc b/gcc/rust/privacy/rust-visibility-resolver.cc
index 421dff0ef3d..fdae5aa7a60 100644
--- a/gcc/rust/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/privacy/rust-visibility-resolver.cc
@@ -71,12 +71,6 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
   // TODO: For the hint, can we point to the original item's definition if
   // present?
 
-  Resolver::Definition def;
-  rust_assert (resolver.lookup_definition (ref_node_id, &def));
-
-  // FIXME: Is that what we want?
-  ref_node_id = def.parent;
-
   HirId ref;
   rust_assert (
     mappings.lookup_node_to_hir (restriction.get_mappings ().get_crate_num (),
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index 4bf35efdbbe..0ae1847e315 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -113,16 +113,12 @@ ResolveExpr::visit (AST::IdentifierExpr &expr)
 	&resolved_node))
     {
       resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
-      resolver->insert_new_definition (expr.get_node_id (),
-				       Definition{expr.get_node_id (), parent});
     }
   else if (resolver->get_type_scope ().lookup (
 	     CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
 	     &resolved_node))
     {
       resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
-      resolver->insert_new_definition (expr.get_node_id (),
-				       Definition{expr.get_node_id (), parent});
     }
   else
     {
@@ -352,9 +348,6 @@ ResolveExpr::visit (AST::LoopExpr &expr)
 	  rust_error_at (label.get_locus (), "label redefined multiple times");
 	  rust_error_at (locus, "was defined here");
 	});
-      resolver->insert_new_definition (label_lifetime_node_id,
-				       Definition{label_lifetime_node_id,
-						  label.get_node_id ()});
     }
   resolve_expr (expr.get_loop_block ().get (), expr.get_node_id ());
 }
@@ -412,9 +405,6 @@ ResolveExpr::visit (AST::WhileLoopExpr &expr)
 	  rust_error_at (label.get_locus (), "label redefined multiple times");
 	  rust_error_at (locus, "was defined here");
 	});
-      resolver->insert_new_definition (label_lifetime_node_id,
-				       Definition{label_lifetime_node_id,
-						  label.get_node_id ()});
     }
   resolve_expr (expr.get_predicate_expr ().get (), expr.get_node_id ());
   resolve_expr (expr.get_loop_block ().get (), expr.get_node_id ());
@@ -443,9 +433,6 @@ ResolveExpr::visit (AST::ForLoopExpr &expr)
 	  rust_error_at (label.get_locus (), "label redefined multiple times");
 	  rust_error_at (locus, "was defined here");
 	});
-      resolver->insert_new_definition (label_lifetime_node_id,
-				       Definition{label_lifetime_node_id,
-						  label.get_node_id ()});
     }
 
   // this needs a new rib to contain the pattern
diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h
index f17b2226a40..ba184e4a53e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-implitem.h
+++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h
@@ -76,9 +76,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (constant.get_node_id (),
-				     Definition{constant.get_node_id (),
-						constant.get_node_id ()});
   }
 
   void visit (AST::Function &function) override
@@ -93,9 +90,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (function.get_node_id (),
-				     Definition{function.get_node_id (),
-						function.get_node_id ()});
   }
 
   void visit (AST::Method &method) override
@@ -110,9 +104,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (method.get_node_id (),
-				     Definition{method.get_node_id (),
-						method.get_node_id ()});
   }
 
 private:
@@ -150,9 +141,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (function.get_node_id (),
-				     Definition{function.get_node_id (),
-						function.get_node_id ()});
 
     mappings->insert_canonical_path (mappings->get_current_crate (),
 				     function.get_node_id (), cpath);
@@ -171,9 +159,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (method.get_node_id (),
-				     Definition{method.get_node_id (),
-						method.get_node_id ()});
 
     mappings->insert_canonical_path (mappings->get_current_crate (),
 				     method.get_node_id (), cpath);
@@ -192,9 +177,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (constant.get_node_id (),
-				     Definition{constant.get_node_id (),
-						constant.get_node_id ()});
 
     mappings->insert_canonical_path (mappings->get_current_crate (),
 				     constant.get_node_id (), cpath);
@@ -253,9 +235,9 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (function.get_node_id (),
-				     Definition{function.get_node_id (),
-						function.get_node_id ()});
+
+    NodeId current_module = resolver->peek_current_module_scope ();
+    mappings->insert_module_child_item (current_module, decl);
   }
 
   void visit (AST::ExternalStaticItem &item) override
@@ -271,9 +253,9 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (item.get_node_id (),
-				     Definition{item.get_node_id (),
-						item.get_node_id ()});
+
+    NodeId current_module = resolver->peek_current_module_scope ();
+    mappings->insert_module_child_item (current_module, decl);
   }
 
 private:
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 198c9c0ca3d..9f550ad252b 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -528,6 +528,7 @@ ResolveItem::visit (AST::Function &function)
   auto decl = ResolveFunctionItemToCanonicalPath::resolve (function);
   auto path = prefix.append (decl);
   auto cpath = canonical_prefix.append (decl);
+
   mappings->insert_canonical_path (mappings->get_current_crate (),
 				   function.get_node_id (), cpath);
 
@@ -788,6 +789,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block)
       resolver->get_name_scope ().pop ();
       return;
     }
+  rust_assert (!canonical_impl_type.is_empty ());
 
   // setup paths
   bool canonicalize_type_args = !impl_block.has_generics ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index c7597a25070..dbf2df782f9 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -47,301 +47,326 @@ ResolvePath::go (AST::SimplePath *expr, NodeId parent)
 void
 ResolvePath::resolve_path (AST::PathInExpression *expr)
 {
-  // resolve root segment first then apply segments in turn
-  std::vector<AST::PathExprSegment> &segs = expr->get_segments ();
-  AST::PathExprSegment &root_segment = segs.at (0);
-  AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment ();
+  NodeId resolved_node_id = UNKNOWN_NODEID;
+  NodeId module_scope_id = resolver->peek_current_module_scope ();
+  NodeId previous_resolved_node_id = module_scope_id;
+  for (size_t i = 0; i < expr->get_segments ().size (); i++)
+    {
+      auto &segment = expr->get_segments ().at (i);
+      const AST::PathIdentSegment &ident_seg = segment.get_ident_segment ();
+      bool is_first_segment = i == 0;
+      resolved_node_id = UNKNOWN_NODEID;
 
-  bool segment_is_type = false;
-  CanonicalPath root_seg_path
-    = CanonicalPath::new_seg (root_segment.get_node_id (),
-			      root_ident_seg.as_string ());
+      NodeId crate_scope_id = resolver->peek_crate_module_scope ();
+      if (segment.is_crate_path_seg ())
+	{
+	  // what is the current crate scope node id?
+	  module_scope_id = crate_scope_id;
+	  previous_resolved_node_id = module_scope_id;
+	  resolver->insert_resolved_name (segment.get_node_id (),
+					  module_scope_id);
+	  continue;
+	}
+      else if (segment.is_super_path_seg ())
+	{
+	  if (module_scope_id == crate_scope_id)
+	    {
+	      rust_error_at (segment.get_locus (),
+			     "cannot use %<super%> at the crate scope");
+	      return;
+	    }
+
+	  module_scope_id = resolver->peek_parent_module_scope ();
+	  previous_resolved_node_id = module_scope_id;
+	  resolver->insert_resolved_name (segment.get_node_id (),
+					  module_scope_id);
+	  continue;
+	}
 
-  // name scope first
-  if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node))
-    {
-      segment_is_type = false;
-      resolver->insert_resolved_name (root_segment.get_node_id (),
-				      resolved_node);
-      resolver->insert_new_definition (root_segment.get_node_id (),
-				       Definition{expr->get_node_id (),
-						  parent});
-    }
-  // check the type scope
-  else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node))
-    {
-      segment_is_type = true;
-      resolver->insert_resolved_type (root_segment.get_node_id (),
-				      resolved_node);
-      resolver->insert_new_definition (root_segment.get_node_id (),
-				       Definition{expr->get_node_id (),
-						  parent});
-    }
-  else
-    {
-      rust_error_at (expr->get_locus (),
-		     "Cannot find path %<%s%> in this scope",
-		     root_segment.as_string ().c_str ());
-      return;
-    }
+      // resolve any generic args
+      if (segment.has_generic_args ())
+	{
+	  bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args (
+	    segment.get_generic_args ());
+	  if (!ok)
+	    {
+	      rust_error_at (segment.get_locus (),
+			     "failed to resolve generic arguments");
+	      return;
+	    }
+	}
 
-  if (root_segment.has_generic_args ())
-    {
-      bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args (
-	root_segment.get_generic_args ());
-      if (!ok)
+      // logic is awkward here there are a few cases
+      //
+      // T::Default
+      // mod::foo::impl_item
+      // super::super::module::item
+      // self
+      // self::foo
+      // self::foo::baz
+      //
+      // T::Default we can only resolve the T and cant do anything about Default
+      // its dependant on associated types
+      //
+      // mod::foo::impl_item
+      // we can resolve mod::foo but nothing about impl_item but we need to
+      // _always resolve generic arguments
+      //
+      // self is a simple single lookup
+      //
+      // we have module_scope_id for the next module_scope to lookup
+      // resolved_node_id is the thing we have resolve this segment to
+      //
+      // new algo?
+      // we can only use module resolution when the previous segment is either
+      // unknown or equal to this module_scope_id
+      //
+      // can only use old resolution when previous segment is unkown
+
+      if (previous_resolved_node_id == module_scope_id)
 	{
-	  rust_error_at (root_segment.get_locus (),
-			 "failed to resolve generic arguments");
-	  return;
+	  Optional<CanonicalPath &> resolved_child
+	    = mappings->lookup_module_child (module_scope_id,
+					     ident_seg.as_string ());
+	  if (resolved_child.is_some ())
+	    {
+	      NodeId resolved_node = resolved_child->get_node_id ();
+	      if (resolver->get_name_scope ().decl_was_declared_here (
+		    resolved_node))
+		{
+		  resolved_node_id = resolved_node;
+		  resolver->insert_resolved_name (segment.get_node_id (),
+						  resolved_node);
+		}
+	      else if (resolver->get_type_scope ().decl_was_declared_here (
+			 resolved_node))
+		{
+		  resolved_node_id = resolved_node;
+		  resolver->insert_resolved_type (segment.get_node_id (),
+						  resolved_node);
+		}
+	      else
+		{
+		  rust_error_at (segment.get_locus (),
+				 "Cannot find path %<%s%> in this scope",
+				 segment.as_string ().c_str ());
+		  return;
+		}
+	    }
+	}
+
+      if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
+	{
+	  // name scope first
+	  NodeId resolved_node = UNKNOWN_NODEID;
+	  const CanonicalPath path
+	    = CanonicalPath::new_seg (segment.get_node_id (),
+				      ident_seg.as_string ());
+	  if (resolver->get_name_scope ().lookup (path, &resolved_node))
+	    {
+	      resolver->insert_resolved_name (segment.get_node_id (),
+					      resolved_node);
+	    }
+	  // check the type scope
+	  else if (resolver->get_type_scope ().lookup (path, &resolved_node))
+	    {
+	      resolver->insert_resolved_type (segment.get_node_id (),
+					      resolved_node);
+	    }
+	  else
+	    {
+	      rust_error_at (segment.get_locus (),
+			     "Cannot find path %<%s%> in this scope",
+			     segment.as_string ().c_str ());
+	      return;
+	    }
+
+	  resolved_node_id = resolved_node;
+	}
+
+      if (resolved_node_id != UNKNOWN_NODEID)
+	{
+	  if (mappings->node_is_module (resolved_node_id))
+	    {
+	      module_scope_id = resolved_node_id;
+	    }
+	  previous_resolved_node_id = resolved_node_id;
 	}
     }
 
-  bool is_single_segment = segs.size () == 1;
-  if (is_single_segment)
+  resolved_node = resolved_node_id;
+  if (resolved_node_id != UNKNOWN_NODEID)
     {
-      if (segment_is_type)
-	resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
+      // name scope first
+      if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
+	{
+	  resolver->insert_resolved_name (expr->get_node_id (),
+					  resolved_node_id);
+	}
+      // check the type scope
+      else if (resolver->get_type_scope ().decl_was_declared_here (
+		 resolved_node_id))
+	{
+	  resolver->insert_resolved_type (expr->get_node_id (),
+					  resolved_node_id);
+	}
       else
-	resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
-
-      resolver->insert_new_definition (expr->get_node_id (),
-				       Definition{expr->get_node_id (),
-						  parent});
-      return;
+	{
+	  gcc_unreachable ();
+	}
     }
-
-  resolve_segments (root_seg_path, 1, expr->get_segments (),
-		    expr->get_node_id (), expr->get_locus ());
 }
 
 void
 ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr)
 {
   AST::QualifiedPathType &root_segment = expr->get_qualified_path_type ();
-
-  bool canonicalize_type_with_generics = false;
   ResolveType::go (&root_segment.get_as_type_path (),
-		   root_segment.get_node_id (),
-		   canonicalize_type_with_generics);
-
-  ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (),
-		   canonicalize_type_with_generics);
-
-  bool type_resolve_generic_args = true;
-  CanonicalPath impl_type_seg
-    = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (),
-					   canonicalize_type_with_generics,
-					   type_resolve_generic_args);
-
-  CanonicalPath trait_type_seg
-    = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (),
-					   canonicalize_type_with_generics,
-					   type_resolve_generic_args);
-  CanonicalPath root_seg_path
-    = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg,
-				    impl_type_seg);
-  bool segment_is_type = false;
+		   root_segment.get_node_id ());
+  ResolveType::go (root_segment.get_type ().get (),
+		   root_segment.get_node_id ());
 
-  // name scope first
-  if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node))
+  for (auto &segment : expr->get_segments ())
     {
-      segment_is_type = false;
-      resolver->insert_resolved_name (root_segment.get_node_id (),
-				      resolved_node);
-      resolver->insert_new_definition (root_segment.get_node_id (),
-				       Definition{expr->get_node_id (),
-						  parent});
-    }
-  // check the type scope
-  else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node))
-    {
-      segment_is_type = true;
-      resolver->insert_resolved_type (root_segment.get_node_id (),
-				      resolved_node);
-      resolver->insert_new_definition (root_segment.get_node_id (),
-				       Definition{expr->get_node_id (),
-						  parent});
-    }
-  else
-    {
-      rust_error_at (expr->get_locus (),
-		     "Cannot find path %<%s%> in this scope",
-		     root_segment.as_string ().c_str ());
-      return;
-    }
-
-  bool is_single_segment = expr->get_segments ().empty ();
-  if (is_single_segment)
-    {
-      if (segment_is_type)
-	resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
-      else
-	resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
-
-      resolver->insert_new_definition (expr->get_node_id (),
-				       Definition{expr->get_node_id (),
-						  parent});
-      return;
+      // we cant actually do anything with the segment itself since this is all
+      // the job of the type system to figure it out but we can resolve any
+      // generic arguments used
+      if (segment.has_generic_args ())
+	{
+	  bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args (
+	    segment.get_generic_args ());
+	  if (!ok)
+	    {
+	      rust_error_at (segment.get_locus (),
+			     "failed to resolve generic arguments");
+	      return;
+	    }
+	}
     }
-
-  resolve_segments (root_seg_path, 0, expr->get_segments (),
-		    expr->get_node_id (), expr->get_locus ());
 }
 
 void
-ResolvePath::resolve_segments (CanonicalPath prefix, size_t offs,
-			       std::vector<AST::PathExprSegment> &segs,
-			       NodeId expr_node_id, Location expr_locus)
+ResolvePath::resolve_path (AST::SimplePath *expr)
 {
-  // we can attempt to resolve this path fully
-  CanonicalPath path = prefix;
-  bool segment_is_type = false;
-  for (size_t i = offs; i < segs.size (); i++)
-    {
-      AST::PathExprSegment &seg = segs.at (i);
-      auto s = ResolvePathSegmentToCanonicalPath::resolve (seg);
-      path = path.append (s);
+  NodeId crate_scope_id = resolver->peek_crate_module_scope ();
+  NodeId module_scope_id = resolver->peek_current_module_scope ();
 
-      // reset state
-      segment_is_type = false;
-      resolved_node = UNKNOWN_NODEID;
+  NodeId resolved_node_id = UNKNOWN_NODEID;
+  for (size_t i = 0; i < expr->get_segments ().size (); i++)
+    {
+      auto &segment = expr->get_segments ().at (i);
+      bool is_first_segment = i == 0;
+      resolved_node_id = UNKNOWN_NODEID;
 
-      if (resolver->get_name_scope ().lookup (path, &resolved_node))
+      if (segment.is_crate_path_seg ())
 	{
-	  resolver->insert_resolved_name (seg.get_node_id (), resolved_node);
-	  resolver->insert_new_definition (seg.get_node_id (),
-					   Definition{expr_node_id, parent});
+	  // what is the current crate scope node id?
+	  module_scope_id = crate_scope_id;
+	  resolver->insert_resolved_name (segment.get_node_id (),
+					  module_scope_id);
+	  continue;
 	}
-      // check the type scope
-      else if (resolver->get_type_scope ().lookup (path, &resolved_node))
+      else if (segment.is_super_path_seg ())
 	{
-	  segment_is_type = true;
-	  resolver->insert_resolved_type (seg.get_node_id (), resolved_node);
-	  resolver->insert_new_definition (seg.get_node_id (),
-					   Definition{expr_node_id, parent});
+	  if (module_scope_id == crate_scope_id)
+	    {
+	      rust_error_at (segment.get_locus (),
+			     "cannot use %<super%> at the crate scope");
+	      return;
+	    }
+
+	  module_scope_id = resolver->peek_parent_module_scope ();
+	  resolver->insert_resolved_name (segment.get_node_id (),
+					  module_scope_id);
+	  continue;
 	}
-      else
-	{
-	  // attempt to fully resolve the path which is allowed to fail given
-	  // the following scenario
-	  //
-	  // https://github.com/Rust-GCC/gccrs/issues/355 Paths are
-	  // resolved fully here, there are limitations though imagine:
-	  //
-	  // struct Foo<A> (A);
-	  //
-	  // impl Foo<isize> {
-	  //    fn test() -> ...
-	  //
-	  // impl Foo<f32> {
-	  //    fn test() -> ...
-	  //
-	  // fn main() {
-	  //    let a:i32 = Foo::test();
-	  //
-	  // there are multiple paths that test can resolve to Foo::<?>::test
-	  // here so we cannot resolve this case
-	  //
-	  // canonical names:
-	  //
-	  // struct Foo<A>            -> Foo
-	  // impl Foo<isize>::fn test -> Foo::isize::test
-	  // impl Foo<f32>::fn test   -> Foo::f32::test
-	  //
-	  // Since there is the case we have the following paths for test:
-	  //
-	  // Foo::isize::test
-	  // Foo::f32::test
-	  // vs
-	  // Foo::test
-	  //
-	  // but the lookup was simply Foo::test we must rely on type resolution
-	  // to figure this type out in a similar fashion to method resolution
-	  // with a probe phase
 
-	  // nothing more we can do we need the type resolver to try and resolve
-	  // this
-	  return;
+      Optional<CanonicalPath &> resolved_child
+	= mappings->lookup_module_child (module_scope_id,
+					 segment.get_segment_name ());
+      if (resolved_child.is_some ())
+	{
+	  NodeId resolved_node = resolved_child->get_node_id ();
+	  if (resolver->get_name_scope ().decl_was_declared_here (
+		resolved_node))
+	    {
+	      resolved_node_id = resolved_node;
+	      resolver->insert_resolved_name (segment.get_node_id (),
+					      resolved_node);
+	    }
+	  else if (resolver->get_type_scope ().decl_was_declared_here (
+		     resolved_node))
+	    {
+	      resolved_node_id = resolved_node;
+	      resolver->insert_resolved_type (segment.get_node_id (),
+					      resolved_node);
+	    }
+	  else
+	    {
+	      rust_error_at (segment.get_locus (),
+			     "Cannot find path %<%s%> in this scope",
+			     segment.as_string ().c_str ());
+	      return;
+	    }
 	}
-    }
-
-  // its fully resolved lets mark it as such
-  if (resolved_node != UNKNOWN_NODEID)
-    {
-      if (segment_is_type)
-	resolver->insert_resolved_type (expr_node_id, resolved_node);
-      else
-	resolver->insert_resolved_name (expr_node_id, resolved_node);
-
-      resolver->insert_new_definition (expr_node_id,
-				       Definition{expr_node_id, parent});
-    }
-}
-
-static bool
-lookup_and_insert_segment (Resolver *resolver, CanonicalPath path,
-			   NodeId segment_id, NodeId *to_resolve, bool &is_type)
-{
-  if (resolver->get_name_scope ().lookup (path, to_resolve))
-    {
-      resolver->insert_resolved_name (segment_id, *to_resolve);
-    }
-  else if (resolver->get_type_scope ().lookup (path, to_resolve))
-    {
-      is_type = true;
-      resolver->insert_resolved_type (segment_id, *to_resolve);
-    }
-  else
-    {
-      return false;
-    }
 
-  return true;
-}
-
-void
-ResolvePath::resolve_path (AST::SimplePath *simple_path)
-{
-  // resolve root segment first then apply segments in turn
-  auto expr_node_id = simple_path->get_node_id ();
-  auto is_type = false;
-
-  auto path = CanonicalPath::create_empty ();
-  for (const auto &seg : simple_path->get_segments ())
-    {
-      auto s = ResolveSimplePathSegmentToCanonicalPath::resolve (seg);
-      path = path.append (s);
-
-      // Reset state
-      resolved_node = UNKNOWN_NODEID;
-      is_type = false;
+      if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
+	{
+	  // name scope first
+	  NodeId resolved_node = UNKNOWN_NODEID;
+	  const CanonicalPath path
+	    = CanonicalPath::new_seg (segment.get_node_id (),
+				      segment.get_segment_name ());
+	  if (resolver->get_name_scope ().lookup (path, &resolved_node))
+	    {
+	      resolved_node_id = resolved_node;
+	      resolver->insert_resolved_name (segment.get_node_id (),
+					      resolved_node);
+	    }
+	  // check the type scope
+	  else if (resolver->get_type_scope ().lookup (path, &resolved_node))
+	    {
+	      resolved_node_id = resolved_node;
+	      resolver->insert_resolved_type (segment.get_node_id (),
+					      resolved_node);
+	    }
+	}
 
-      if (!lookup_and_insert_segment (resolver, path, seg.get_node_id (),
-				      &resolved_node, is_type))
+      if (resolved_node_id == UNKNOWN_NODEID)
 	{
-	  rust_error_at (seg.get_locus (),
-			 "cannot find simple path segment %qs",
-			 seg.as_string ().c_str ());
+	  rust_error_at (segment.get_locus (),
+			 "cannot find simple path segment %<%s%> in this scope",
+			 segment.as_string ().c_str ());
 	  return;
 	}
+
+      if (mappings->node_is_module (resolved_node_id))
+	{
+	  module_scope_id = resolved_node_id;
+	}
     }
 
-  if (resolved_node == UNKNOWN_NODEID)
+  resolved_node = resolved_node_id;
+  if (resolved_node_id != UNKNOWN_NODEID)
     {
-      rust_error_at (simple_path->get_locus (),
-		     "could not resolve simple path %qs",
-		     simple_path->as_string ().c_str ());
-      return;
+      // name scope first
+      if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
+	{
+	  resolver->insert_resolved_name (expr->get_node_id (),
+					  resolved_node_id);
+	}
+      // check the type scope
+      else if (resolver->get_type_scope ().decl_was_declared_here (
+		 resolved_node_id))
+	{
+	  resolver->insert_resolved_type (expr->get_node_id (),
+					  resolved_node_id);
+	}
+      else
+	{
+	  gcc_unreachable ();
+	}
     }
-
-  if (is_type)
-    resolver->insert_resolved_type (expr_node_id, resolved_node);
-  else
-    resolver->insert_resolved_name (expr_node_id, resolved_node);
-
-  resolver->insert_new_definition (expr_node_id,
-				   Definition{expr_node_id, parent});
 }
 
 } // namespace Resolver
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h
index cbfe967fdcc..fc8785f73d5 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.h
+++ b/gcc/rust/resolve/rust-ast-resolve-path.h
@@ -40,26 +40,12 @@ private:
   void resolve_path (AST::QualifiedPathInExpression *expr);
   void resolve_path (AST::SimplePath *expr);
 
-  void resolve_segments (CanonicalPath prefix, size_t offs,
-			 std::vector<AST::PathExprSegment> &segs,
-			 NodeId expr_node_id, Location expr_locus);
-
   void
   resolve_simple_path_segments (CanonicalPath prefix, size_t offs,
 				const std::vector<AST::SimplePathSegment> &segs,
 				NodeId expr_node_id, Location expr_locus);
 };
 
-class ResolveSimplePathSegmentToCanonicalPath
-{
-public:
-  static CanonicalPath resolve (const AST::SimplePathSegment &seg)
-  {
-    // FIXME: Since this is so simple, maybe it can simply be a tiny function?
-    return CanonicalPath::new_seg (seg.get_node_id (), seg.get_segment_name ());
-  }
-};
-
 } // namespace Resolver
 } // namespace Rust
 
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index dc2cca41fef..1947212f431 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -87,9 +87,7 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
 	      CanonicalPath::new_seg (ident.get_node_id (),
 				      ident.get_identifier ()),
 	      ident.get_node_id (), ident.get_locus ());
-	    resolver->insert_new_definition (ident.get_node_id (),
-					     Definition{ident.get_node_id (),
-							ident.get_node_id ()});
+
 	    resolver->mark_decl_mutability (ident.get_node_id (),
 					    ident.is_mut ());
 	  }
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index dfb05d3a4af..b899754709e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -48,9 +48,6 @@ public:
 	  &resolved_node))
       {
 	resolver->insert_resolved_name (pattern.get_node_id (), resolved_node);
-	resolver->insert_new_definition (pattern.get_node_id (),
-					 Definition{pattern.get_node_id (),
-						    parent});
       }
   }
 
@@ -76,9 +73,7 @@ public:
     resolver->get_name_scope ().insert (
       CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()),
       pattern.get_node_id (), pattern.get_locus ());
-    resolver->insert_new_definition (pattern.get_node_id (),
-				     Definition{pattern.get_node_id (),
-						parent});
+
     resolver->mark_decl_mutability (pattern.get_node_id (),
 				    pattern.get_is_mut ());
   }
@@ -88,9 +83,7 @@ public:
     resolver->get_name_scope ().insert (
       CanonicalPath::new_seg (pattern.get_node_id (), "_"),
       pattern.get_node_id (), pattern.get_locus ());
-    resolver->insert_new_definition (pattern.get_node_id (),
-				     Definition{pattern.get_node_id (),
-						parent});
+
     resolver->mark_decl_mutability (pattern.get_node_id (), false);
   }
 
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index c8d42bcc7ca..3556b68fd02 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -71,9 +71,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (constant.get_node_id (),
-				     Definition{constant.get_node_id (),
-						constant.get_node_id ()});
 
     ResolveType::go (constant.get_type ().get (), constant.get_node_id ());
     ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id (),
@@ -361,9 +358,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (function.get_node_id (),
-				     Definition{function.get_node_id (),
-						function.get_node_id ()});
 
     NodeId scope_node_id = function.get_node_id ();
     resolver->get_name_scope ().push (scope_node_id);
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 7a1458e6143..78b786a3072 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -62,10 +62,6 @@ public:
 	rust_error_at (r, "redefined multiple times");
       });
 
-    resolver->insert_new_definition (module.get_node_id (),
-				     Definition{module.get_node_id (),
-						module.get_node_id ()});
-
     NodeId current_module = resolver->peek_current_module_scope ();
     mappings->insert_module_child_item (current_module, mod);
     mappings->insert_module_child (current_module, module.get_node_id ());
@@ -278,9 +274,7 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (var.get_node_id (),
-				     Definition{var.get_node_id (),
-						var.get_node_id ()});
+
     resolver->mark_decl_mutability (var.get_node_id (), var.is_mutable ());
 
     NodeId current_module = resolver->peek_current_module_scope ();
@@ -302,9 +296,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (constant.get_node_id (),
-				     Definition{constant.get_node_id (),
-						constant.get_node_id ()});
 
     NodeId current_module = resolver->peek_current_module_scope ();
     mappings->insert_module_child_item (current_module, decl);
@@ -325,17 +316,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (function.get_node_id (),
-				     Definition{function.get_node_id (),
-						function.get_node_id ()});
-
-    // if this does not get a reference it will be determined to be unused
-    // lets give it a fake reference to itself
-    if (function.get_function_name ().compare ("main") == 0)
-      {
-	resolver->insert_resolved_name (function.get_node_id (),
-					function.get_node_id ());
-      }
 
     NodeId current_module = resolver->peek_current_module_scope ();
     mappings->insert_module_child_item (current_module, decl);
@@ -386,11 +366,6 @@ public:
 	r.add_range (locus);
 	rust_error_at (r, "redefined multiple times");
       });
-    resolver->insert_new_definition (impl_block.get_node_id (),
-				     Definition{impl_block.get_node_id (),
-						impl_block.get_node_id ()});
-    resolver->insert_resolved_name (impl_block.get_node_id (),
-				    impl_block.get_node_id ());
 
     for (auto &impl_item : impl_block.get_impl_items ())
       ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 2b5c68447a0..ce9c0d19e14 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -133,15 +133,12 @@ ResolveType::visit (AST::ArrayType &type)
 void
 ResolveType::visit (AST::TraitObjectTypeOneBound &type)
 {
-  NodeId bound_resolved_id
-    = ResolveTypeBound::go (&type.get_trait_bound (), type.get_node_id ());
-  ok = bound_resolved_id != UNKNOWN_NODEID;
+  ResolveTypeBound::go (&type.get_trait_bound (), type.get_node_id ());
 }
 
 void
 ResolveType::visit (AST::TraitObjectType &type)
 {
-  ok = true;
   for (auto &bound : type.get_type_param_bounds ())
     {
       /* NodeId bound_resolved_id = */
@@ -270,30 +267,183 @@ ResolveRelativeTypePath::ResolveRelativeTypePath (CanonicalPath qualified_path)
 }
 
 bool
-ResolveRelativeTypePath::go (AST::QualifiedPathInType &path)
+ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
 {
-  // resolve the type and trait path
-  auto &qualified_path = path.get_qualified_path_type ();
   CanonicalPath result = CanonicalPath::create_empty ();
-  if (!resolve_qual_seg (qualified_path, result))
-    return false;
+  ResolveRelativeTypePath o (result);
+  auto &resolver = o.resolver;
+  auto &mappings = o.mappings;
 
-  // resolve the associated impl if available but it can also be from a trait
-  // and this is allowed to fail
-  auto resolver = Resolver::get ();
-  NodeId projection_resolved_id = UNKNOWN_NODEID;
-  if (resolver->get_name_scope ().lookup (result, &projection_resolved_id))
+  NodeId module_scope_id = resolver->peek_current_module_scope ();
+  NodeId previous_resolved_node_id = module_scope_id;
+  for (size_t i = 0; i < path.get_segments ().size (); i++)
     {
-      // mark the resolution for this
-      resolver->insert_resolved_name (qualified_path.get_node_id (),
-				      projection_resolved_id);
+      auto &segment = path.get_segments ().at (i);
+      const AST::PathIdentSegment &ident_seg = segment->get_ident_segment ();
+      bool is_first_segment = i == 0;
+      resolved_node_id = UNKNOWN_NODEID;
+
+      NodeId crate_scope_id = resolver->peek_crate_module_scope ();
+      if (segment->is_crate_path_seg ())
+	{
+	  // what is the current crate scope node id?
+	  module_scope_id = crate_scope_id;
+	  previous_resolved_node_id = module_scope_id;
+	  resolver->insert_resolved_name (segment->get_node_id (),
+					  module_scope_id);
+
+	  continue;
+	}
+      else if (segment->is_super_path_seg ())
+	{
+	  if (module_scope_id == crate_scope_id)
+	    {
+	      rust_error_at (segment->get_locus (),
+			     "cannot use super at the crate scope");
+	      return false;
+	    }
+
+	  module_scope_id = resolver->peek_parent_module_scope ();
+	  previous_resolved_node_id = module_scope_id;
+	  resolver->insert_resolved_name (segment->get_node_id (),
+					  module_scope_id);
+	  continue;
+	}
+
+      switch (segment->get_type ())
+	{
+	  case AST::TypePathSegment::SegmentType::GENERIC: {
+	    AST::TypePathSegmentGeneric *s
+	      = static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
+	    if (s->has_generic_args ())
+	      {
+		for (auto &gt : s->get_generic_args ().get_type_args ())
+		  {
+		    ResolveType::go (gt.get (), UNKNOWN_NODEID);
+		  }
+	      }
+	  }
+	  break;
+
+	case AST::TypePathSegment::SegmentType::REG:
+	  // nothing to do
+	  break;
+
+	case AST::TypePathSegment::SegmentType::FUNCTION:
+	  gcc_unreachable ();
+	  break;
+	}
+
+      if (previous_resolved_node_id == module_scope_id
+	  && path.get_segments ().size () > 1)
+	{
+	  Optional<CanonicalPath &> resolved_child
+	    = mappings->lookup_module_child (module_scope_id,
+					     ident_seg.as_string ());
+	  if (resolved_child.is_some ())
+	    {
+	      NodeId resolved_node = resolved_child->get_node_id ();
+	      if (resolver->get_name_scope ().decl_was_declared_here (
+		    resolved_node))
+		{
+		  resolved_node_id = resolved_node;
+		  resolver->insert_resolved_name (segment->get_node_id (),
+						  resolved_node);
+		}
+	      else if (resolver->get_type_scope ().decl_was_declared_here (
+			 resolved_node))
+		{
+		  resolved_node_id = resolved_node;
+		  resolver->insert_resolved_type (segment->get_node_id (),
+						  resolved_node);
+		}
+	      else
+		{
+		  rust_error_at (segment->get_locus (),
+				 "Cannot find path %<%s%> in this scope",
+				 segment->as_string ().c_str ());
+		  return false;
+		}
+	    }
+	}
+
+      if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
+	{
+	  // name scope first
+	  NodeId resolved_node = UNKNOWN_NODEID;
+	  const CanonicalPath path
+	    = CanonicalPath::new_seg (segment->get_node_id (),
+				      ident_seg.as_string ());
+	  if (resolver->get_type_scope ().lookup (path, &resolved_node))
+	    {
+	      resolver->insert_resolved_type (segment->get_node_id (),
+					      resolved_node);
+	    }
+	  else if (resolver->get_name_scope ().lookup (path, &resolved_node))
+	    {
+	      resolver->insert_resolved_name (segment->get_node_id (),
+					      resolved_node);
+	    }
+	  else
+	    {
+	      rust_error_at (segment->get_locus (),
+			     "failed to resolve TypePath: %s in this scope",
+			     segment->as_string ().c_str ());
+	      return false;
+	    }
+
+	  resolved_node_id = resolved_node;
+	}
+
+      if (resolved_node_id != UNKNOWN_NODEID)
+	{
+	  if (mappings->node_is_module (resolved_node_id))
+	    {
+	      module_scope_id = resolved_node_id;
+	    }
+	  previous_resolved_node_id = resolved_node_id;
+	}
     }
 
+  if (resolved_node_id != UNKNOWN_NODEID)
+    {
+      // name scope first
+      if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
+	{
+	  resolver->insert_resolved_name (path.get_node_id (),
+					  resolved_node_id);
+	}
+      // check the type scope
+      else if (resolver->get_type_scope ().decl_was_declared_here (
+		 resolved_node_id))
+	{
+	  resolver->insert_resolved_type (path.get_node_id (),
+					  resolved_node_id);
+	}
+      else
+	{
+	  gcc_unreachable ();
+	}
+    }
+
+  return true;
+}
+
+bool
+ResolveRelativeTypePath::go (AST::QualifiedPathInType &path)
+{
+  CanonicalPath result = CanonicalPath::create_empty ();
+  ResolveRelativeTypePath o (result);
+
+  // resolve the type and trait path
+  auto &qualified_path = path.get_qualified_path_type ();
+  if (!o.resolve_qual_seg (qualified_path, result))
+    return false;
+
   // qualified types are similar to other paths in that we cannot guarantee
   // that we can resolve the path at name resolution. We must look up
   // associated types and type information to figure this out properly
 
-  ResolveRelativeTypePath o (result);
   std::unique_ptr<AST::TypePathSegment> &associated
     = path.get_associated_segment ();
 
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index d10cec2835b..cc117ec4003 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -190,13 +190,13 @@ class ResolveRelativeTypePath : public ResolveTypeToCanonicalPath
   using ResolveTypeToCanonicalPath::visit;
 
 public:
+  static bool go (AST::TypePath &path, NodeId &resolved_node_id);
   static bool go (AST::QualifiedPathInType &path);
 
 private:
   ResolveRelativeTypePath (CanonicalPath qualified_path);
 
-  static bool resolve_qual_seg (AST::QualifiedPathType &seg,
-				CanonicalPath &result);
+  bool resolve_qual_seg (AST::QualifiedPathType &seg, CanonicalPath &result);
 };
 
 class ResolveType : public ResolverBase
@@ -211,7 +211,6 @@ public:
     ResolveType resolver (parent, canonicalize_type_with_generics,
 			  canonical_path);
     type->accept_vis (resolver);
-
     return resolver.resolved_node;
   };
 
@@ -226,7 +225,6 @@ public:
 
   void visit (AST::TupleType &tuple) override
   {
-    ok = true;
     if (tuple.is_unit_type ())
       {
 	resolved_node = resolver->get_unit_type_node_id ();
@@ -239,87 +237,16 @@ public:
 
   void visit (AST::TypePath &path) override
   {
-    auto rel_canonical_path
-      = ResolveTypeToCanonicalPath::resolve (path,
-					     canonicalize_type_with_generics,
-					     true);
-    if (rel_canonical_path.is_empty ())
-      {
-	rust_error_at (path.get_locus (),
-		       "Failed to resolve canonical path for TypePath");
-	return;
-      }
-
-    // lets try and resolve in one go else leave it up to the type resolver to
-    // figure outer
-
-    if (resolver->get_type_scope ().lookup (rel_canonical_path, &resolved_node))
-      {
-	resolver->insert_resolved_type (path.get_node_id (), resolved_node);
-	resolver->insert_new_definition (path.get_node_id (),
-					 Definition{path.get_node_id (),
-						    parent});
-
-	if (canonical_path != nullptr)
-	  {
-	    const CanonicalPath *cpath = nullptr;
-	    bool ok
-	      = mappings->lookup_canonical_path (mappings->get_current_crate (),
-						 resolved_node, &cpath);
-	    if (!ok)
-	      {
-		*canonical_path = rel_canonical_path;
-	      }
-	    else
-	      {
-		*canonical_path = *cpath;
-	      }
-	  }
-
-	return;
-      }
-
-    // lets resolve as many segments as we can and leave it up to the type
-    // resolver otherwise
-    size_t nprocessed = 0;
-    rel_canonical_path.iterate ([&] (const CanonicalPath &seg) -> bool {
-      resolved_node = UNKNOWN_NODEID;
-
-      if (!resolver->get_type_scope ().lookup (seg, &resolved_node))
-	return false;
-
-      resolver->insert_resolved_type (seg.get_node_id (), resolved_node);
-      resolver->insert_new_definition (seg.get_node_id (),
-				       Definition{path.get_node_id (), parent});
-      nprocessed++;
-      return true;
-    });
-
-    if (nprocessed == 0)
+    if (ResolveRelativeTypePath::go (path, resolved_node))
       {
-	rust_error_at (path.get_locus (), "failed to resolve TypePath: %s",
-		       path.as_string ().c_str ());
-	return;
-      }
-
-    // its ok if this fails since the type resolver sometimes will need to
-    // investigate the bounds of a type for the associated type for example see:
-    // https://github.com/Rust-GCC/gccrs/issues/746
-    if (nprocessed == rel_canonical_path.size ())
-      {
-	resolver->insert_resolved_type (path.get_node_id (), resolved_node);
-	resolver->insert_new_definition (path.get_node_id (),
-					 Definition{path.get_node_id (),
-						    parent});
+	if (canonical_path == nullptr)
+	  return;
 
-	if (canonical_path != nullptr)
+	const CanonicalPath *type_path = nullptr;
+	if (mappings->lookup_canonical_path (mappings->get_current_crate (),
+					     resolved_node, &type_path))
 	  {
-	    const CanonicalPath *cpath = nullptr;
-	    bool ok
-	      = mappings->lookup_canonical_path (mappings->get_current_crate (),
-						 resolved_node, &cpath);
-	    rust_assert (ok);
-	    *canonical_path = *cpath;
+	    *canonical_path = *type_path;
 	  }
       }
   }
@@ -350,11 +277,10 @@ private:
 	       CanonicalPath *canonical_path)
     : ResolverBase (parent),
       canonicalize_type_with_generics (canonicalize_type_with_generics),
-      ok (false), canonical_path (canonical_path)
+      canonical_path (canonical_path)
   {}
 
   bool canonicalize_type_with_generics;
-  bool ok;
   CanonicalPath *canonical_path;
 };
 
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 8465162b565..169237a598e 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -81,6 +81,11 @@ NameResolution::go (AST::Crate &crate)
     = CanonicalPath::new_seg (scope_node_id, crate_name);
   crate_prefix.set_crate_num (cnum);
 
+  // setup a dummy crate node
+  resolver->get_name_scope ().insert (
+    CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"),
+    crate.get_node_id (), Location ());
+
   // setup the root scope
   resolver->push_new_module_scope (scope_node_id);
 
@@ -167,19 +172,21 @@ ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg,
 		     seg.as_string ().c_str ());
       return false;
     }
-  bool include_generic_args_in_path = false;
 
-  NodeId type_resolved_node
-    = ResolveType::go (seg.get_type ().get (), seg.get_node_id ());
+  auto type = seg.get_type ().get ();
+  NodeId type_resolved_node = ResolveType::go (type, seg.get_node_id ());
   if (type_resolved_node == UNKNOWN_NODEID)
     return false;
 
-  CanonicalPath impl_type_seg
-    = ResolveTypeToCanonicalPath::resolve (*seg.get_type ().get (),
-					   include_generic_args_in_path);
+  const CanonicalPath *impl_type_seg = nullptr;
+  bool ok
+    = mappings->lookup_canonical_path (mappings->get_current_crate (),
+				       type_resolved_node, &impl_type_seg);
+  rust_assert (ok);
+
   if (!seg.has_as_clause ())
     {
-      result = result.append (impl_type_seg);
+      result = result.append (*impl_type_seg);
       return true;
     }
 
@@ -188,12 +195,15 @@ ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg,
   if (trait_resolved_node == UNKNOWN_NODEID)
     return false;
 
-  CanonicalPath trait_type_seg
-    = ResolveTypeToCanonicalPath::resolve (seg.get_as_type_path (),
-					   include_generic_args_in_path);
+  const CanonicalPath *trait_type_seg = nullptr;
+  ok = mappings->lookup_canonical_path (mappings->get_current_crate (),
+					trait_resolved_node, &trait_type_seg);
+  rust_assert (ok);
+
   CanonicalPath projection
-    = TraitImplProjection::resolve (seg.get_node_id (), trait_type_seg,
-				    impl_type_seg);
+    = TraitImplProjection::resolve (seg.get_node_id (), *trait_type_seg,
+				    *impl_type_seg);
+
   result = result.append (projection);
   return true;
 }
diff --git a/gcc/rust/resolve/rust-name-resolver.cc b/gcc/rust/resolve/rust-name-resolver.cc
index fc1f36154dd..fcf71907166 100644
--- a/gcc/rust/resolve/rust-name-resolver.cc
+++ b/gcc/rust/resolve/rust-name-resolver.cc
@@ -34,6 +34,12 @@
       _R.push_back (builtin_type);                                             \
       tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (),    \
 			     _TY);                                             \
+      mappings->insert_node_to_hir (mappings->get_current_crate (),            \
+				    builtin_type->get_node_id (),              \
+				    _TY->get_ref ());                          \
+      mappings->insert_canonical_path (                                        \
+	mappings->get_current_crate (), builtin_type->get_node_id (),          \
+	CanonicalPath::new_seg (builtin_type->get_node_id (), _X));            \
     }                                                                          \
   while (0)
 
@@ -165,6 +171,16 @@ Scope::iterate (std::function<bool (Rib *)> cb)
     }
 }
 
+void
+Scope::iterate (std::function<bool (const Rib *)> cb) const
+{
+  for (auto it = stack.rbegin (); it != stack.rend (); ++it)
+    {
+      if (!cb (*it))
+	return;
+    }
+}
+
 Rib *
 Scope::peek ()
 {
@@ -200,6 +216,21 @@ Scope::append_reference_for_def (NodeId refId, NodeId defId)
   rust_assert (ok);
 }
 
+bool
+Scope::decl_was_declared_here (NodeId def) const
+{
+  bool found = false;
+  iterate ([&] (const Rib *r) -> bool {
+    if (r->decl_was_declared_here (def))
+      {
+	found = true;
+	return false;
+      }
+    return true;
+  });
+  return found;
+}
+
 Resolver::Resolver ()
   : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()),
     name_scope (Scope (mappings->get_current_crate ())),
@@ -370,29 +401,6 @@ Resolver::generate_builtins ()
   set_unit_type_node_id (unit_type->get_node_id ());
 }
 
-void
-Resolver::insert_new_definition (NodeId id, Definition def)
-{
-  auto it = name_definitions.find (id);
-  if (it != name_definitions.end ())
-    {
-      rust_assert (it->second.is_equal (def));
-      return;
-    }
-  name_definitions[id] = def;
-}
-
-bool
-Resolver::lookup_definition (NodeId id, Definition *def)
-{
-  auto it = name_definitions.find (id);
-  if (it == name_definitions.end ())
-    return false;
-
-  *def = it->second;
-  return true;
-}
-
 void
 Resolver::insert_resolved_name (NodeId refId, NodeId defId)
 {
diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h
index 23a9d829b58..6b611b28977 100644
--- a/gcc/rust/resolve/rust-name-resolver.h
+++ b/gcc/rust/resolve/rust-name-resolver.h
@@ -73,11 +73,13 @@ public:
   bool lookup (const CanonicalPath &ident, NodeId *id);
 
   void iterate (std::function<bool (Rib *)> cb);
+  void iterate (std::function<bool (const Rib *)> cb) const;
 
   Rib *peek ();
   void push (NodeId id);
   Rib *pop ();
 
+  bool decl_was_declared_here (NodeId def) const;
   void append_reference_for_def (NodeId refId, NodeId defId);
 
   CrateNum get_crate_num () const { return crate_num; }
@@ -87,32 +89,6 @@ private:
   std::vector<Rib *> stack;
 };
 
-// This can map simple NodeIds for names to their parent node
-// for example:
-//
-// var x = y + 1;
-//
-// say y has node id=1 and the plus_expression has id=2
-// then the Definition will have
-// Definition { node=1, parent=2 }
-// this will be used later to gather the ribs for the type inferences context
-//
-// if parent is UNKNOWN_NODEID then this is a root declaration
-// say the var_decl hasa node_id=4;
-// the parent could be a BLOCK_Expr node_id but lets make it UNKNOWN_NODE_ID
-// so we know when it terminates
-struct Definition
-{
-  NodeId node;
-  NodeId parent;
-  // add kind ?
-
-  bool is_equal (const Definition &other)
-  {
-    return node == other.node && parent == other.parent;
-  }
-};
-
 class Resolver
 {
 public:
@@ -136,9 +112,6 @@ public:
   bool find_label_rib (NodeId id, Rib **rib);
   bool find_macro_rib (NodeId id, Rib **rib);
 
-  void insert_new_definition (NodeId id, Definition def);
-  bool lookup_definition (NodeId id, Definition *def);
-
   void insert_resolved_name (NodeId refId, NodeId defId);
   bool lookup_resolved_name (NodeId refId, NodeId *defId);
 
@@ -183,6 +156,18 @@ public:
     return current_module_stack.back ();
   }
 
+  NodeId peek_crate_module_scope () const
+  {
+    rust_assert (!current_module_stack.empty ());
+    return current_module_stack.front ();
+  }
+
+  NodeId peek_parent_module_scope () const
+  {
+    rust_assert (current_module_stack.size () > 1);
+    return current_module_stack.at (current_module_stack.size () - 2);
+  }
+
 private:
   Resolver ();
 
@@ -207,10 +192,6 @@ private:
   std::map<NodeId, Rib *> label_ribs;
   std::map<NodeId, Rib *> macro_ribs;
 
-  // map any Node to its Definition
-  // ie any name or type usage
-  std::map<NodeId, Definition> name_definitions;
-
   // Rust uses DefIds to namespace these under a crate_num
   // but then it uses the def_collector to assign local_defids
   // to each ast node as well. not sure if this is going to fit
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 0b0e5af915f..57063753c24 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -737,6 +737,9 @@ Session::parse_file (const char *filename)
   if (saw_errors ())
     return;
 
+  // add the mappings to it
+  mappings->insert_hir_crate (&hir);
+
   // type resolve
   Resolver::TypeResolution::Resolve (hir);
   if (options.dump_option_enabled (CompileOptions::TYPE_RESOLUTION_DUMP))
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 8427cc9afc4..e84f5e899e3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -423,35 +423,14 @@ public:
 
     // then lookup the reference_node_id
     NodeId ref_node_id = UNKNOWN_NODEID;
-    if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+    if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
       {
-	// these ref_node_ids will resolve to a pattern declaration but we are
-	// interested in the definition that this refers to get the parent id
-	Definition def;
-	if (!resolver->lookup_definition (ref_node_id, &def))
-	  {
-	    // FIXME
-	    // this is an internal error
-	    rust_error_at (expr.get_locus (),
-			   "unknown reference for resolved name");
-	    return;
-	  }
-	ref_node_id = def.parent;
-      }
-    else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
-      {
-	// FIXME
-	// this is an internal error
-	rust_error_at (expr.get_locus (),
-		       "Failed to lookup type reference for node: %s",
-		       expr.as_string ().c_str ());
-	return;
+	resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
       }
 
     if (ref_node_id == UNKNOWN_NODEID)
       {
-	// FIXME
-	// this is an internal error
+	// FIXME this needs to go away and just return error node
 	rust_error_at (expr.get_locus (), "unresolved node: %s",
 		       expr.as_string ().c_str ());
 	return;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 3823c570d25..a0596116571 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -67,6 +67,36 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
   // inherit the bound
   root->inherit_bounds ({specified_bound});
 
+  // setup the associated types
+  const TraitReference *specified_bound_ref = specified_bound.get ();
+  auto candidates = TypeBoundsProbe::Probe (root);
+  AssociatedImplTrait *associated_impl_trait = nullptr;
+  for (auto &probed_bound : candidates)
+    {
+      const TraitReference *bound_trait_ref = probed_bound.first;
+      const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+      HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
+      AssociatedImplTrait *associated = nullptr;
+      bool found_impl_trait
+	= context->lookup_associated_trait_impl (impl_block_id, &associated);
+      if (found_impl_trait)
+	{
+	  bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
+	  bool found_self = associated->get_self ()->can_eq (root, false);
+	  if (found_trait && found_self)
+	    {
+	      associated_impl_trait = associated;
+	      break;
+	    }
+	}
+    }
+
+  if (associated_impl_trait != nullptr)
+    {
+      associated_impl_trait->setup_associated_types (root, specified_bound);
+    }
+
   // lookup the associated item from the specified bound
   HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
   HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
@@ -81,28 +111,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
   // infer the root type
   infered = item.get_tyty_for_receiver (root);
 
-  // we need resolve to the impl block
-  NodeId impl_resolved_id = UNKNOWN_NODEID;
-  bool have_associated_impl = resolver->lookup_resolved_name (
-    qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
-  AssociatedImplTrait *lookup_associated = nullptr;
-  if (have_associated_impl)
-    {
-      HirId impl_block_id;
-      bool ok
-	= mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
-					impl_resolved_id, &impl_block_id);
-      rust_assert (ok);
-
-      bool found_impl_trait
-	= context->lookup_associated_trait_impl (impl_block_id,
-						 &lookup_associated);
-      if (found_impl_trait)
-	{
-	  lookup_associated->setup_associated_types (root, specified_bound);
-	}
-    }
-
   // turbo-fish segment path::<ty>
   if (item_seg.has_generic_args ())
     {
@@ -145,7 +153,9 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr)
     return;
 
   if (tyseg->needs_generic_substitutions ())
-    tyseg = SubstMapper::InferSubst (tyseg, expr.get_locus ());
+    {
+      tyseg = SubstMapper::InferSubst (tyseg, expr.get_locus ());
+    }
 
   bool fully_resolved = offset == expr.get_segments ().size ();
   if (fully_resolved)
@@ -162,30 +172,19 @@ TyTy::BaseType *
 TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
 				  NodeId *root_resolved_node_id)
 {
+  TyTy::BaseType *root_tyty = nullptr;
   *offset = 0;
   for (size_t i = 0; i < expr.get_num_segments (); i++)
     {
       HIR::PathExprSegment &seg = expr.get_segments ().at (i);
+
       bool have_more_segments = (expr.get_num_segments () - 1 != i);
+      bool is_root = *offset == 0;
       NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
 
       // then lookup the reference_node_id
       NodeId ref_node_id = UNKNOWN_NODEID;
-      if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
-	{
-	  // these ref_node_ids will resolve to a pattern declaration but we
-	  // are interested in the definition that this refers to get the
-	  // parent id
-	  Definition def;
-	  if (!resolver->lookup_definition (ref_node_id, &def))
-	    {
-	      rust_error_at (expr.get_locus (),
-			     "unknown reference for resolved name");
-	      return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
-	    }
-	  ref_node_id = def.parent;
-	}
-      else
+      if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
 	{
 	  resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
 	}
@@ -193,6 +192,12 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
       // ref_node_id is the NodeId that the segments refers to.
       if (ref_node_id == UNKNOWN_NODEID)
 	{
+	  if (root_tyty != nullptr && *offset > 0)
+	    {
+	      // then we can let the impl path probe take over now
+	      return root_tyty;
+	    }
+
 	  rust_error_at (seg.get_locus (),
 			 "failed to type resolve root segment");
 	  return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
@@ -217,7 +222,8 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
 	= (nullptr
 	   != mappings->lookup_module (expr.get_mappings ().get_crate_num (),
 				       ref));
-      if (seg_is_module)
+      auto seg_is_crate = mappings->is_local_hirid_crate (ref);
+      if (seg_is_module || seg_is_crate)
 	{
 	  // A::B::C::this_is_a_module::D::E::F
 	  //          ^^^^^^^^^^^^^^^^
@@ -239,8 +245,33 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
       TyTy::BaseType *lookup = nullptr;
       if (!context->lookup_type (ref, &lookup))
 	{
-	  rust_error_at (seg.get_locus (), "failed to resolve root segment");
-	  return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
+	  if (is_root)
+	    {
+	      rust_error_at (seg.get_locus (),
+			     "failed to resolve root segment");
+	      return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
+	    }
+	  return root_tyty;
+	}
+
+      // if we have a previous segment type
+      if (root_tyty != nullptr)
+	{
+	  // if this next segment needs substitution we must apply the
+	  // previous type arguments
+	  //
+	  // such as: GenericStruct::<_>::new(123, 456)
+	  if (lookup->needs_generic_substitutions ())
+	    {
+	      if (!root_tyty->needs_generic_substitutions ())
+		{
+		  auto used_args_in_prev_segment
+		    = GetUsedSubstArgs::From (root_tyty);
+		  lookup
+		    = SubstMapperInternal::Resolve (lookup,
+						    used_args_in_prev_segment);
+		}
+	    }
 	}
 
       // turbo-fish segment path::<ty>
@@ -248,21 +279,24 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
 	{
 	  if (!lookup->can_substitute ())
 	    {
-	      rust_error_at (seg.get_locus (),
+	      rust_error_at (expr.get_locus (),
 			     "substitutions not supported for %s",
-			     lookup->as_string ().c_str ());
-	      return new TyTy::ErrorType (lookup->get_ref ());
+			     root_tyty->as_string ().c_str ());
+	      return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
 	    }
-	  lookup = SubstMapper::Resolve (lookup, seg.get_locus (),
+
+	  lookup = SubstMapper::Resolve (lookup, expr.get_locus (),
 					 &seg.get_generic_args ());
+	  if (lookup->get_kind () == TyTy::TypeKind::ERROR)
+	    return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
 	}
 
       *root_resolved_node_id = ref_node_id;
       *offset = *offset + 1;
-      return lookup;
+      root_tyty = lookup;
     }
 
-  return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
+  return root_tyty;
 }
 
 void
@@ -423,22 +457,17 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
 
   context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
 
-  // lookup if the name resolver was able to canonically resolve this or not
-  NodeId path_resolved_id = UNKNOWN_NODEID;
-  if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (),
-				      &path_resolved_id))
+  // name scope first
+  if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
     {
-      rust_assert (path_resolved_id == resolved_node_id);
+      resolver->insert_resolved_name (expr_mappings.get_nodeid (),
+				      resolved_node_id);
     }
   // check the type scope
-  else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (),
-					   &path_resolved_id))
+  else if (resolver->get_type_scope ().decl_was_declared_here (
+	     resolved_node_id))
     {
-      rust_assert (path_resolved_id == resolved_node_id);
-    }
-  else
-    {
-      resolver->insert_resolved_name (expr_mappings.get_nodeid (),
+      resolver->insert_resolved_type (expr_mappings.get_nodeid (),
 				      resolved_node_id);
     }
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index be3b8e4c011..1018f816ecb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -350,5 +350,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern)
   infered = upper->unify (lower);
 }
 
+void
+TypeCheckPattern::visit (HIR::IdentifierPattern &pattern)
+{
+  infered = parent;
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
index 03c4977d572..860aca9207f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
@@ -58,6 +58,8 @@ public:
 
   void visit (HIR::RangePattern &pattern) override;
 
+  void visit (HIR::IdentifierPattern &pattern) override;
+
 private:
   TypeCheckPattern (TyTy::BaseType *parent)
     : TypeCheckBase (), parent (parent), infered (nullptr)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index 327bffa6971..96e92b4458f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -79,6 +79,7 @@ public:
     infered
       = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ());
 
+    const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
     TyTy::BaseType *init_expr_ty = nullptr;
     if (stmt.has_init_expr ())
       {
@@ -86,10 +87,8 @@ public:
 	if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
 	  return;
 
-	init_expr_ty = init_expr_ty->clone ();
-	auto ref = init_expr_ty->get_ref ();
-	init_expr_ty->set_ref (stmt.get_mappings ().get_hirid ());
-	init_expr_ty->append_reference (ref);
+	init_expr_ty->append_reference (
+	  stmt_pattern.get_pattern_mappings ().get_hirid ());
       }
 
     TyTy::BaseType *specified_ty = nullptr;
@@ -99,38 +98,35 @@ public:
     // let x:i32 = 123;
     if (specified_ty != nullptr && init_expr_ty != nullptr)
       {
-	auto unified_ty = specified_ty->coerce (init_expr_ty);
-	if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
-	  return;
-
-	context->insert_type (stmt.get_mappings (), specified_ty);
+	// FIXME use this result and look at the regressions
+	specified_ty->coerce (init_expr_ty);
+	context->insert_type (stmt_pattern.get_pattern_mappings (),
+			      specified_ty);
       }
     else
       {
 	// let x:i32;
 	if (specified_ty != nullptr)
 	  {
-	    context->insert_type (stmt.get_mappings (), specified_ty);
+	    context->insert_type (stmt_pattern.get_pattern_mappings (),
+				  specified_ty);
 	  }
 	// let x = 123;
 	else if (init_expr_ty != nullptr)
 	  {
-	    context->insert_type (stmt.get_mappings (), init_expr_ty);
+	    context->insert_type (stmt_pattern.get_pattern_mappings (),
+				  init_expr_ty);
 	  }
 	// let x;
 	else
 	  {
 	    context->insert_type (
-	      stmt.get_mappings (),
-	      new TyTy::InferType (stmt.get_mappings ().get_hirid (),
-				   TyTy::InferType::InferTypeKind::GENERAL,
-				   stmt.get_locus ()));
+	      stmt_pattern.get_pattern_mappings (),
+	      new TyTy::InferType (
+		stmt_pattern.get_pattern_mappings ().get_hirid (),
+		TyTy::InferType::InferTypeKind::GENERAL, stmt.get_locus ()));
 	  }
       }
-
-    TyTy::BaseType *lookup = nullptr;
-    bool ok = context->lookup_type (stmt.get_mappings ().get_hirid (), &lookup);
-    rust_assert (ok);
   }
 
   void visit (HIR::TupleStruct &struct_decl) override
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 85de3a1d07d..a5597beb185 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -151,6 +151,36 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
   // inherit the bound
   root->inherit_bounds ({specified_bound});
 
+  // setup the associated types
+  const TraitReference *specified_bound_ref = specified_bound.get ();
+  auto candidates = TypeBoundsProbe::Probe (root);
+  AssociatedImplTrait *associated_impl_trait = nullptr;
+  for (auto &probed_bound : candidates)
+    {
+      const TraitReference *bound_trait_ref = probed_bound.first;
+      const HIR::ImplBlock *associated_impl = probed_bound.second;
+
+      HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
+      AssociatedImplTrait *associated = nullptr;
+      bool found_impl_trait
+	= context->lookup_associated_trait_impl (impl_block_id, &associated);
+      if (found_impl_trait)
+	{
+	  bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
+	  bool found_self = associated->get_self ()->can_eq (root, false);
+	  if (found_trait && found_self)
+	    {
+	      associated_impl_trait = associated;
+	      break;
+	    }
+	}
+    }
+
+  if (associated_impl_trait != nullptr)
+    {
+      associated_impl_trait->setup_associated_types (root, specified_bound);
+    }
+
   // lookup the associated item from the specified bound
   std::unique_ptr<HIR::TypePathSegment> &item_seg
     = path.get_associated_segment ();
@@ -166,28 +196,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
   // infer the root type
   translated = item.get_tyty_for_receiver (root);
 
-  // we need resolve to the impl block
-  NodeId impl_resolved_id = UNKNOWN_NODEID;
-  bool have_associated_impl = resolver->lookup_resolved_name (
-    qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
-  AssociatedImplTrait *lookup_associated = nullptr;
-  if (have_associated_impl)
-    {
-      HirId impl_block_id;
-      bool ok
-	= mappings->lookup_node_to_hir (path.get_mappings ().get_crate_num (),
-					impl_resolved_id, &impl_block_id);
-      rust_assert (ok);
-
-      bool found_impl_trait
-	= context->lookup_associated_trait_impl (impl_block_id,
-						 &lookup_associated);
-      if (found_impl_trait)
-	{
-	  lookup_associated->setup_associated_types (root, specified_bound);
-	}
-    }
-
   // turbo-fish segment path::<ty>
   if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
     {
@@ -245,21 +253,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
 
       // then lookup the reference_node_id
       NodeId ref_node_id = UNKNOWN_NODEID;
-      if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
-	{
-	  // these ref_node_ids will resolve to a pattern declaration but we
-	  // are interested in the definition that this refers to get the
-	  // parent id
-	  Definition def;
-	  if (!resolver->lookup_definition (ref_node_id, &def))
-	    {
-	      rust_error_at (path.get_locus (),
-			     "unknown reference for resolved name");
-	      return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
-	    }
-	  ref_node_id = def.parent;
-	}
-      else
+      if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
 	{
 	  resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
 	}
@@ -270,14 +264,15 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
 	  if (is_root)
 	    {
 	      rust_error_at (seg->get_locus (),
-			     "failed to type resolve root segment");
+			     "unknown reference for resolved name: %<%s%>",
+			     seg->get_ident_segment ().as_string ().c_str ());
 	      return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
 	    }
 	  return root_tyty;
 	}
 
       // node back to HIR
-      HirId ref;
+      HirId ref = UNKNOWN_HIRID;
       if (!mappings->lookup_node_to_hir (path.get_mappings ().get_crate_num (),
 					 ref_node_id, &ref))
 	{
@@ -300,8 +295,8 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
 	= (nullptr
 	   != mappings->lookup_module (path.get_mappings ().get_crate_num (),
 				       ref));
-
-      if (seg_is_module)
+      auto seg_is_crate = mappings->is_local_hirid_crate (ref);
+      if (seg_is_module || seg_is_crate)
 	{
 	  // A::B::C::this_is_a_module::D::E::F
 	  //          ^^^^^^^^^^^^^^^^
@@ -498,8 +493,19 @@ TypeCheckType::resolve_segments (
     }
   else
     {
-      resolver->insert_resolved_type (expr_mappings.get_nodeid (),
-				      resolved_node_id);
+      // name scope first
+      if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
+	{
+	  resolver->insert_resolved_name (expr_mappings.get_nodeid (),
+					  resolved_node_id);
+	}
+      // check the type scope
+      else if (resolver->get_type_scope ().decl_was_declared_here (
+		 resolved_node_id))
+	{
+	  resolver->insert_resolved_type (expr_mappings.get_nodeid (),
+					  resolved_node_id);
+	}
     }
 
   return tyseg;
diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h
index ab7f59a349a..36963e5efa3 100644
--- a/gcc/rust/typecheck/rust-tycheck-dump.h
+++ b/gcc/rust/typecheck/rust-tycheck-dump.h
@@ -128,7 +128,7 @@ public:
   void visit (HIR::LetStmt &stmt) override
   {
     dump += "let " + stmt.get_pattern ()->as_string () + ":"
-	    + type_string (stmt.get_mappings ());
+	    + type_string (stmt.get_pattern ()->get_pattern_mappings ());
     if (stmt.has_init_expr ())
       {
 	dump += " = ";
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index f9932a4705e..c21b681f2f9 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -201,6 +201,18 @@ Mappings::get_hir_crate (CrateNum crateNum)
   return it->second;
 }
 
+bool
+Mappings::is_local_hirid_crate (HirId crateNum)
+{
+  for (const auto &it : hirCrateMappings)
+    {
+      const HIR::Crate *crate = it.second;
+      if (crate->get_mappings ().get_hirid () == crateNum)
+	return true;
+    }
+  return false;
+}
+
 void
 Mappings::insert_hir_crate (HIR::Crate *crate)
 {
@@ -208,6 +220,9 @@ Mappings::insert_hir_crate (HIR::Crate *crate)
   rust_assert (get_hir_crate (crateNum) == nullptr);
 
   hirCrateMappings[crateNum] = crate;
+  insert_node_to_hir (crate->get_mappings ().get_crate_num (),
+		      crate->get_mappings ().get_nodeid (),
+		      crate->get_mappings ().get_hirid ());
 }
 
 void
@@ -908,6 +923,25 @@ Mappings::lookup_module_chidren_items (NodeId module)
   return Optional<std::vector<Resolver::CanonicalPath> &>::some (it->second);
 }
 
+Optional<Resolver::CanonicalPath &>
+Mappings::lookup_module_child (NodeId module, const std::string &item_name)
+{
+  Optional<std::vector<Resolver::CanonicalPath> &> children
+    = lookup_module_chidren_items (module);
+  if (children.is_none ())
+    return Optional<Resolver::CanonicalPath &>::none ();
+
+  // lookup the children to match the name if we can
+  for (auto &child : children.get ())
+    {
+      const std::string &raw_identifier = child.get ();
+      bool found = raw_identifier.compare (item_name) == 0;
+      if (found)
+	return Optional<Resolver::CanonicalPath &>::some (child);
+    }
+  return Optional<Resolver::CanonicalPath &>::none ();
+}
+
 void
 Mappings::insert_child_item_to_parent_module_mapping (NodeId child_item,
 						      NodeId parent_module)
@@ -925,5 +959,11 @@ Mappings::lookup_parent_module (NodeId child_item)
   return Optional<NodeId>::some (it->second);
 }
 
+bool
+Mappings::node_is_module (NodeId query)
+{
+  return module_child_items.find (query) != module_child_items.end ();
+}
+
 } // namespace Analysis
 } // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index a48d4beace7..4360ae2e2a9 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -122,6 +122,7 @@ public:
   void insert_ast_crate (AST::Crate *crate);
 
   HIR::Crate *get_hir_crate (CrateNum crateNum);
+  bool is_local_hirid_crate (HirId crateNum);
   void insert_hir_crate (HIR::Crate *crate);
 
   void insert_defid_mapping (DefId id, HIR::Item *item);
@@ -329,10 +330,13 @@ public:
   void insert_module_child_item (NodeId module, Resolver::CanonicalPath item);
   Optional<std::vector<Resolver::CanonicalPath> &>
   lookup_module_chidren_items (NodeId module);
+  Optional<Resolver::CanonicalPath &>
+  lookup_module_child (NodeId module, const std::string &item_name);
 
   void insert_child_item_to_parent_module_mapping (NodeId child_item,
 						   NodeId parent_module);
   Optional<NodeId> lookup_parent_module (NodeId child_item);
+  bool node_is_module (NodeId query);
 
 private:
   Mappings ();
diff --git a/gcc/testsuite/rust/compile/complex-path1.rs b/gcc/testsuite/rust/compile/complex-path1.rs
new file mode 100644
index 00000000000..54011bd6976
--- /dev/null
+++ b/gcc/testsuite/rust/compile/complex-path1.rs
@@ -0,0 +1,18 @@
+// { dg-additional-options "-w" }
+mod a {
+    pub fn foo() {}
+}
+
+mod b {
+    pub fn foo() {
+        super::a::foo();
+    }
+}
+
+mod foo {
+    pub struct bar(pub i32);
+}
+
+fn test() -> crate::foo::bar {
+    foo::bar(123)
+}
diff --git a/gcc/testsuite/rust/compile/issue-1251.rs b/gcc/testsuite/rust/compile/issue-1251.rs
new file mode 100644
index 00000000000..b16e1e0b0d9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1251.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-w" }
+mod a {
+    pub mod b {
+        pub mod a {
+            pub fn foo() {}
+        }
+    }
+
+    pub fn bidule() {
+        crate::a::b::a::foo()
+    }
+}
+
+fn main() {}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-14  8:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-14  8:03 [gcc/devel/rust/master] This patch implements complex Path resolution Thomas Schwinge

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).