From: Philip Herron <herron.phi...@googlemail.com>

This was a small fix to sort out the segfault to check for nullptr on the
TypePath cases for query type. But when this happened opened up a few bugs
that were hidden under the carpet namely: compile/issue-2905-{1,2}.rs which
has a recursive type query which needs to ne handled but now and error
message is being output for the type path. This happens because we start
resolving a generic struct:

  struct Wierd<T>(A<(T,)>);

So the child field A is also generic and the generic argument of the tuple
of T needs to be applied to this generic field. This causes a chunk of
code to do bounds checking to ensure the bounds are ok, this is also
something that probably might change as generic types will have the bounds
secified anyway but thats besides the case right now. So once this bounds
checking occurs we endup looking at the impl block for Wierd<i32> which is
also grand but we still havent finished resolving the parent type of Wierd
which is recusive. But the query type system needs to check for that.

The other issue was: compile/issue-3022.rs which is a resolution issue:

  impl<T: Foo<U>, U> Foo<U> for Bar<T, U>

The bound of Foo<T> is added to T before U is resolved but this was hidden
before the new error message was added. So now we have a generic
arguements handler being used correctly all over the code base apart from
1 last case for Traits but we will deal with that later. This handles the
case by setting up the type parameters upfront then sorting out their
bounds.

Fixes Rust-GCC#3625

gcc/rust/ChangeLog:

        * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): 
new argument
        * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::TypeCheckBase): 
new helper
        * typecheck/rust-hir-type-check-base.h: new helper prototype
        * typecheck/rust-hir-type-check-implitem.cc 
(TypeCheckTopLevelExternItem::visit):
        remove comment out code
        * typecheck/rust-hir-type-check-path.cc 
(TypeCheckExpr::resolve_root_path): check for null
        * typecheck/rust-hir-type-check-type.cc 
(TypeCheckType::resolve_root_path): likewise
        (TypeResolveGenericParam::Resolve): new args
        (TypeResolveGenericParam::ApplyAnyTraitBounds): new helper
        (TypeResolveGenericParam::apply_trait_bounds): new field
        (TypeResolveGenericParam::visit): update
        * typecheck/rust-hir-type-check-type.h: new args
        * typecheck/rust-hir-type-check.cc 
(TraitItemReference::get_type_from_fn): reuse helper
        * typecheck/rust-type-util.cc (query_type): check for recursive query
        * typecheck/rust-tyty-subst.cc 
(SubstitutionParamMapping::SubstitutionParamMapping):
        remove const
        (SubstitutionParamMapping::get_generic_param): likewise
        * typecheck/rust-tyty-subst.h: likewise
        * typecheck/rust-tyty-variance-analysis.cc 
(GenericTyVisitorCtx::process_type): likewise

gcc/testsuite/ChangeLog:

        * rust/compile/issue-3625.rs: New test.

Signed-off-by: Philip Herron <herron.phi...@googlemail.com>
---
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  |   4 +-
 .../typecheck/rust-hir-type-check-base.cc     |  42 ++++-
 gcc/rust/typecheck/rust-hir-type-check-base.h |   8 +-
 .../typecheck/rust-hir-type-check-implitem.cc | 163 +-----------------
 .../typecheck/rust-hir-type-check-path.cc     |   2 +-
 .../typecheck/rust-hir-type-check-type.cc     |  44 +++--
 gcc/rust/typecheck/rust-hir-type-check-type.h |  11 +-
 gcc/rust/typecheck/rust-hir-type-check.cc     |  33 +---
 gcc/rust/typecheck/rust-type-util.cc          |  37 ++++
 gcc/rust/typecheck/rust-tyty-subst.cc         |   8 +-
 gcc/rust/typecheck/rust-tyty-subst.h          |   6 +-
 .../typecheck/rust-tyty-variance-analysis.cc  |   2 +-
 gcc/testsuite/rust/compile/issue-3625.rs      |   2 +
 13 files changed, 144 insertions(+), 218 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-3625.rs

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index a236fd78d7b..e78c19263dc 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -234,7 +234,9 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
            // The one exception is the implicit Self type of a trait
            bool apply_sized = !is_self;
            auto param_type
-             = TypeResolveGenericParam::Resolve (*generic_param, apply_sized);
+             = TypeResolveGenericParam::Resolve (*generic_param, true,
+                                                 apply_sized);
+
            context->insert_type (generic_param->get_mappings (), param_type);
            substitutions.push_back (
              TyTy::SubstitutionParamMapping (typaram, param_type));
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc 
b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index d3d68821734..beee91e7944 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -31,6 +31,16 @@ TypeCheckBase::TypeCheckBase ()
     context (TypeCheckContext::get ())
 {}
 
+void
+TypeCheckBase::ResolveGenericParams (
+  const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
+  std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
+  ABI abi)
+{
+  TypeCheckBase ctx;
+  ctx.resolve_generic_params (generic_params, substitutions, is_foreign, abi);
+}
+
 static void
 walk_types_to_constrain (std::set<HirId> &constrained_symbols,
                         const TyTy::SubstitutionArgumentMappings &constraints)
@@ -387,7 +397,8 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec 
&attrs, location_t locus)
 void
 TypeCheckBase::resolve_generic_params (
   const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
-  std::vector<TyTy::SubstitutionParamMapping> &substitutions)
+  std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
+  ABI abi)
 {
   for (auto &generic_param : generic_params)
     {
@@ -400,10 +411,15 @@ TypeCheckBase::resolve_generic_params (
            context->get_lifetime_resolver ().insert_mapping (
              context->intern_lifetime (lifetime));
          }
-
          break;
 
          case HIR::GenericParam::GenericKind::CONST: {
+           if (is_foreign && abi != Rust::ABI::INTRINSIC)
+             {
+               rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
+                              "foreign items may not have const parameters");
+             }
+
            auto &param
              = static_cast<HIR::ConstGenericParam &> (*generic_param);
            auto specified_type = TypeCheckType::Resolve (param.get_type ());
@@ -427,15 +443,31 @@ TypeCheckBase::resolve_generic_params (
          break;
 
          case HIR::GenericParam::GenericKind::TYPE: {
-           auto param_type = TypeResolveGenericParam::Resolve (*generic_param);
+           if (is_foreign && abi != Rust::ABI::INTRINSIC)
+             {
+               rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
+                              "foreign items may not have type parameters");
+             }
+
+           auto param_type = TypeResolveGenericParam::Resolve (
+             *generic_param, false /*resolve_trait_bounds*/);
            context->insert_type (generic_param->get_mappings (), param_type);
 
-           substitutions.push_back (TyTy::SubstitutionParamMapping (
-             static_cast<HIR::TypeParam &> (*generic_param), param_type));
+           auto &param = static_cast<HIR::TypeParam &> (*generic_param);
+           TyTy::SubstitutionParamMapping p (param, param_type);
+           substitutions.push_back (p);
          }
          break;
        }
     }
+
+  // now walk them to setup any specified type param bounds
+  for (auto &subst : substitutions)
+    {
+      auto pty = subst.get_param_ty ();
+      TypeResolveGenericParam::ApplyAnyTraitBounds (subst.get_generic_param (),
+                                                   pty);
+    }
 }
 
 TyTy::TypeBoundPredicate
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h 
b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 8a1bf6f4cb3..580082a6adf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -32,6 +32,11 @@ class TypeCheckBase
 public:
   virtual ~TypeCheckBase () {}
 
+  static void ResolveGenericParams (
+    const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
+    std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool 
is_foreign,
+    ABI abi);
+
 protected:
   TypeCheckBase ();
 
@@ -57,7 +62,8 @@ protected:
 
   void resolve_generic_params (
     const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
-    std::vector<TyTy::SubstitutionParamMapping> &substitutions);
+    std::vector<TyTy::SubstitutionParamMapping> &substitutions,
+    bool is_foreign = false, ABI abi = ABI::RUST);
 
   TyTy::TypeBoundPredicate get_marker_predicate (LangItem::Kind item_type,
                                                 location_t locus);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc 
b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index a5ae54bf493..29864b0c8e6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -73,44 +73,8 @@ TypeCheckTopLevelExternItem::visit 
(HIR::ExternalFunctionItem &function)
   std::vector<TyTy::SubstitutionParamMapping> substitutions;
   if (function.has_generics ())
     {
-      for (auto &generic_param : function.get_generic_params ())
-       {
-         switch (generic_param.get ()->get_kind ())
-           {
-           case HIR::GenericParam::GenericKind::LIFETIME:
-             context->intern_and_insert_lifetime (
-               static_cast<HIR::LifetimeParam &> (*generic_param)
-                 .get_lifetime ());
-             // TODO: handle bounds
-             break;
-           case HIR::GenericParam::GenericKind::CONST:
-             // FIXME: Skipping Lifetime and Const completely until better
-             // handling.
-             if (parent.get_abi () != Rust::ABI::INTRINSIC)
-               {
-                 rust_error_at (function.get_locus (), ErrorCode::E0044,
-                                "foreign items may not have const parameters");
-               }
-             break;
-
-             case HIR::GenericParam::GenericKind::TYPE: {
-               if (parent.get_abi () != Rust::ABI::INTRINSIC)
-                 {
-                   rust_error_at (
-                     function.get_locus (), ErrorCode::E0044,
-                     "foreign items may not have type parameters");
-                 }
-               auto param_type
-                 = TypeResolveGenericParam::Resolve (*generic_param);
-               context->insert_type (generic_param->get_mappings (),
-                                     param_type);
-
-               substitutions.push_back (TyTy::SubstitutionParamMapping (
-                 static_cast<HIR::TypeParam &> (*generic_param), param_type));
-             }
-             break;
-           }
-       }
+      resolve_generic_params (function.get_generic_params (), substitutions,
+                             true /*is_foreign*/, parent.get_abi ());
     }
 
   TyTy::RegionConstraints region_constraints;
@@ -200,128 +164,7 @@ void
 TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type)
 {
   rust_sorry_at (type.get_locus (), "extern types are not supported yet");
-  //  auto binder_pin = context->push_clean_lifetime_resolver ();
-
-  //  std::vector<TyTy::SubstitutionParamMapping> substitutions;
-  //  if (function.has_generics ())
-  //    {
-  //      for (auto &generic_param : function.get_generic_params ())
-  // {
-  //   switch (generic_param.get ()->get_kind ())
-  //     {
-  //     case HIR::GenericParam::GenericKind::LIFETIME:
-  //       context->intern_and_insert_lifetime (
-  //   static_cast<HIR::LifetimeParam &> (*generic_param)
-  //     .get_lifetime ());
-  //       // TODO: handle bounds
-  //       break;
-  //     case HIR::GenericParam::GenericKind::CONST:
-  //       // FIXME: Skipping Lifetime and Const completely until better
-  //       // handling.
-  //       break;
-
-  //       case HIR::GenericParam::GenericKind::TYPE: {
-  //   auto param_type
-  //     = TypeResolveGenericParam::Resolve (generic_param.get ());
-  //   context->insert_type (generic_param->get_mappings (),
-  //                         param_type);
-
-  //   substitutions.push_back (TyTy::SubstitutionParamMapping (
-  //     static_cast<HIR::TypeParam &> (*generic_param), param_type));
-  //       }
-  //       break;
-  //     }
-  // }
-  //    }
-
-  //  TyTy::RegionConstraints region_constraints;
-  //  if (function.has_where_clause ())
-  //    {
-  //      for (auto &where_clause_item : function.get_where_clause ().get_items
-  //      ())
-  // {
-  //   ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
-  //                              region_constraints);
-  // }
-  //    }
-
-  //  TyTy::BaseType *ret_type = nullptr;
-  //  if (!function.has_return_type ())
-  //    ret_type
-  //      = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid
-  //      ());
-  //  else
-  //    {
-  //      auto resolved
-  // = TypeCheckType::Resolve (function.get_return_type ().get ());
-  //      if (resolved == nullptr)
-  // {
-  //   rust_error_at (function.get_locus (),
-  //            "failed to resolve return type");
-  //   return;
-  // }
-
-  //      ret_type = resolved->clone ();
-  //      ret_type->set_ref (
-  // function.get_return_type ()->get_mappings ().get_hirid ());
-  //    }
-
-  //  std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
-  //  for (auto &param : function.get_function_params ())
-  //    {
-  //      // get the name as well required for later on
-  //      auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
-
-  //      // these are implicit mappings and not used
-  //      auto crate_num = mappings->get_current_crate ();
-  //      Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id
-  //      (),
-  //                        mappings->get_next_hir_id (crate_num),
-  //                        UNKNOWN_LOCAL_DEFID);
-
-  //      HIR::IdentifierPattern *param_pattern
-  // = new HIR::IdentifierPattern (mapping, param.get_param_name (),
-  //                         UNDEF_LOCATION, false, Mutability::Imm,
-  //                         std::unique_ptr<HIR::Pattern> (nullptr));
-
-  //      params.push_back (
-  // std::pair<HIR::Pattern *, TyTy::BaseType *> (param_pattern,
-  //                                        param_tyty));
-
-  //      context->insert_type (param.get_mappings (), param_tyty);
-
-  //      // FIXME do we need error checking for patterns here?
-  //      // see https://github.com/Rust-GCC/gccrs/issues/995
-  //    }
-
-  //  uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
-  //  if (function.is_variadic ())
-  //    {
-  //      flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG;
-  //      if (parent.get_abi () != Rust::ABI::C)
-  // {
-  //   rust_error_at (
-  //     function.get_locus (), ErrorCode::E0045,
-  //     "C-variadic function must have C or cdecl calling convention");
-  // }
-  //    }
-
-  //  RustIdent ident{
-  //    CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
-  //               function.get_item_name ().as_string ()),
-  //    function.get_locus ()};
-
-  //  auto fnType = new TyTy::FnType (
-  //    function.get_mappings ().get_hirid (),
-  //    function.get_mappings ().get_defid (),
-  //    function.get_item_name ().as_string (), ident, flags, parent.get_abi 
(),
-  //    std::move (params), ret_type, std::move (substitutions),
-  //    TyTy::SubstitutionArgumentMappings::empty (
-  //      context->get_lifetime_resolver ().get_num_bound_regions ()),
-  //    region_constraints);
-
-  //  context->insert_type (function.get_mappings (), fnType);
-  //  resolved = fnType;
+  // TODO
 }
 
 TypeCheckImplItem::TypeCheckImplItem (
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc 
b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 1fe39aaeb64..5662da5310e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -336,7 +336,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression 
&expr, size_t *offset,
       TyTy::BaseType *lookup = nullptr;
       if (!query_type (ref, &lookup))
        {
-         if (is_root)
+         if (is_root || root_tyty == nullptr)
            {
              rust_error_at (expr.get_locus (), ErrorCode::E0425,
                             "cannot find value %qs in this scope",
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 54f50ec41f1..6919093b0f5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -417,8 +417,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, 
size_t *offset,
       TyTy::BaseType *lookup = nullptr;
       if (!query_type (ref, &lookup))
        {
-         if (is_root)
-           return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+         if (is_root || root_tyty == nullptr)
+           {
+             rust_error_at (seg->get_locus (),
+                            "failed to resolve type path segment: %qs",
+                            seg->as_string ().c_str ());
+             return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+           }
 
          return root_tyty;
        }
@@ -573,6 +578,7 @@ TypeCheckType::resolve_segments (
                                        ignore_mandatory_trait_items);
              if (candidates.size () == 0)
                {
+                 prev_segment->debug ();
                  rust_error_at (
                    seg->get_locus (),
                    "failed to resolve path segment using an impl Probe");
@@ -797,9 +803,10 @@ TypeCheckType::visit (HIR::ImplTraitType &type)
 }
 
 TyTy::ParamType *
-TypeResolveGenericParam::Resolve (HIR::GenericParam &param, bool apply_sized)
+TypeResolveGenericParam::Resolve (HIR::GenericParam &param,
+                                 bool resolve_trait_bounds, bool apply_sized)
 {
-  TypeResolveGenericParam resolver (apply_sized);
+  TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds);
   switch (param.get_kind ())
     {
     case HIR::GenericParam::GenericKind::TYPE:
@@ -817,6 +824,14 @@ TypeResolveGenericParam::Resolve (HIR::GenericParam 
&param, bool apply_sized)
   return resolver.resolved;
 }
 
+void
+TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam &param,
+                                             TyTy::ParamType *pty)
+{
+  TypeResolveGenericParam resolver (true, true);
+  resolver.apply_trait_bounds (param, pty);
+}
+
 void
 TypeResolveGenericParam::visit (HIR::LifetimeParam &param)
 {
@@ -835,6 +850,19 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
   if (param.has_type ())
     TypeCheckType::Resolve (param.get_type ());
 
+  resolved
+    = new TyTy::ParamType (param.get_type_representation ().as_string (),
+                          param.get_locus (),
+                          param.get_mappings ().get_hirid (), param, {});
+
+  if (resolve_trait_bounds)
+    apply_trait_bounds (param, resolved);
+}
+
+void
+TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
+                                            TyTy::ParamType *pty)
+{
   std::unique_ptr<HIR::Type> implicit_self_bound = nullptr;
   if (param.has_type_param_bounds ())
     {
@@ -865,8 +893,6 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
   //
   // We can only do this when we are not resolving the implicit Self for Sized
   // itself
-  rust_debug_loc (param.get_locus (), "apply_sized: %s",
-                 apply_sized ? "true" : "false");
   if (apply_sized)
     {
       TyTy::TypeBoundPredicate sized_predicate
@@ -941,10 +967,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
        }
     }
 
-  resolved = new TyTy::ParamType (param.get_type_representation ().as_string 
(),
-                                 param.get_locus (),
-                                 param.get_mappings ().get_hirid (), param,
-                                 specified_bounds);
+  // inherit them
+  pty->inherit_bounds (specified_bounds);
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h 
b/gcc/rust/typecheck/rust-hir-type-check-type.h
index fc272e639a3..cc991b66eb8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -91,20 +91,27 @@ class TypeResolveGenericParam : public TypeCheckBase
 {
 public:
   static TyTy::ParamType *Resolve (HIR::GenericParam &param,
+                                  bool resolve_trait_bounds = true,
                                   bool apply_sized = true);
 
+  static void ApplyAnyTraitBounds (HIR::TypeParam &param, TyTy::ParamType 
*pty);
+
 protected:
   void visit (HIR::TypeParam &param);
   void visit (HIR::LifetimeParam &param);
   void visit (HIR::ConstGenericParam &param);
 
+  void apply_trait_bounds (HIR::TypeParam &param, TyTy::ParamType *pty);
+
 private:
-  TypeResolveGenericParam (bool apply_sized)
-    : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized)
+  TypeResolveGenericParam (bool apply_sized, bool resolve_trait_bounds)
+    : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized),
+      resolve_trait_bounds (resolve_trait_bounds)
   {}
 
   TyTy::ParamType *resolved;
   bool apply_sized;
+  bool resolve_trait_bounds;
 };
 
 class ResolveWhereClauseItem : public TypeCheckBase
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc 
b/gcc/rust/typecheck/rust-hir-type-check.cc
index a198ad3d66d..49c19055300 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -165,36 +165,9 @@ TraitItemReference::get_type_from_fn (/*const*/ 
HIR::TraitItemFunc &fn) const
   HIR::TraitFunctionDecl &function = fn.get_decl ();
   if (function.has_generics ())
     {
-      for (auto &generic_param : function.get_generic_params ())
-       {
-         switch (generic_param.get ()->get_kind ())
-           {
-             case HIR::GenericParam::GenericKind::LIFETIME: {
-               auto lifetime_param
-                 = static_cast<HIR::LifetimeParam &> (*generic_param);
-
-               context->intern_and_insert_lifetime (
-                 lifetime_param.get_lifetime ());
-               // TODO: Handle lifetime bounds
-             }
-             break;
-           case HIR::GenericParam::GenericKind::CONST:
-             // FIXME: Skipping Lifetime and Const completely until better
-             // handling.
-             break;
-
-             case HIR::GenericParam::GenericKind::TYPE: {
-               auto param_type
-                 = TypeResolveGenericParam::Resolve (*generic_param);
-               context->insert_type (generic_param->get_mappings (),
-                                     param_type);
-
-               substitutions.push_back (TyTy::SubstitutionParamMapping (
-                 static_cast<HIR::TypeParam &> (*generic_param), param_type));
-             }
-             break;
-           }
-       }
+      TypeCheckBase::ResolveGenericParams (function.get_generic_params (),
+                                          substitutions, false /*is_foreign*/,
+                                          ABI::RUST);
     }
 
   if (function.has_where_clause ())
diff --git a/gcc/rust/typecheck/rust-type-util.cc 
b/gcc/rust/typecheck/rust-type-util.cc
index 4abfbae3665..c6c5b4bb55f 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -22,10 +22,13 @@
 #include "rust-hir-type-check-implitem.h"
 #include "rust-hir-type-check-item.h"
 #include "rust-hir-type-check.h"
+#include "rust-hir-type-check-type.h"
 #include "rust-casts.h"
 #include "rust-unify.h"
 #include "rust-coercion.h"
 #include "rust-hir-type-bounds.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "options.h"
 
 namespace Rust {
 namespace Resolver {
@@ -34,6 +37,7 @@ bool
 query_type (HirId reference, TyTy::BaseType **result)
 {
   auto &mappings = Analysis::Mappings::get ();
+  auto &resolver = *Resolver::get ();
   TypeCheckContext *context = TypeCheckContext::get ();
 
   if (context->query_in_progress (reference))
@@ -91,6 +95,39 @@ query_type (HirId reference, TyTy::BaseType **result)
       HIR::ImplBlock *impl = impl_block_by_type.value ();
       rust_debug_loc (impl->get_locus (), "resolved impl block type {%u} to",
                      reference);
+
+      // this could be recursive to the root type
+      if (impl->has_type ())
+       {
+         HIR::Type &ty = impl->get_type ();
+         NodeId ref_node_id = UNKNOWN_NODEID;
+         NodeId ast_node_id = ty.get_mappings ().get_nodeid ();
+
+         if (flag_name_resolution_2_0)
+           {
+             auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ()
+                              .resolver ();
+
+             // assign the ref_node_id if we've found something
+             nr_ctx.lookup (ast_node_id)
+               .map (
+                 [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
+           }
+         else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
+           resolver.lookup_resolved_type (ast_node_id, &ref_node_id);
+
+         if (ref_node_id != UNKNOWN_NODEID)
+           {
+             tl::optional<HirId> hid
+               = mappings.lookup_node_to_hir (ref_node_id);
+             if (hid.has_value () && context->query_in_progress (hid.value ()))
+               {
+                 context->query_completed (reference);
+                 return false;
+               }
+           }
+       }
+
       *result = TypeCheckItem::ResolveImplBlockSelf (*impl);
       context->query_completed (reference);
       return true;
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index 95f18b9d29f..bdb6474aeeb 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -28,8 +28,8 @@
 namespace Rust {
 namespace TyTy {
 
-SubstitutionParamMapping::SubstitutionParamMapping (
-  const HIR::TypeParam &generic, ParamType *param)
+SubstitutionParamMapping::SubstitutionParamMapping (HIR::TypeParam &generic,
+                                                   ParamType *param)
   : generic (generic), param (param)
 {}
 
@@ -66,8 +66,8 @@ SubstitutionParamMapping::get_param_ty () const
   return param;
 }
 
-const HIR::TypeParam &
-SubstitutionParamMapping::get_generic_param () const
+HIR::TypeParam &
+SubstitutionParamMapping::get_generic_param ()
 {
   return generic;
 }
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h 
b/gcc/rust/typecheck/rust-tyty-subst.h
index 3f0b912fa7b..e6ed1fc42d6 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -44,7 +44,7 @@ class SubstitutionArgumentMappings;
 class SubstitutionParamMapping
 {
 public:
-  SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
+  SubstitutionParamMapping (HIR::TypeParam &generic, ParamType *param);
 
   SubstitutionParamMapping (const SubstitutionParamMapping &other);
 
@@ -59,7 +59,7 @@ public:
 
   const ParamType *get_param_ty () const;
 
-  const HIR::TypeParam &get_generic_param () const;
+  HIR::TypeParam &get_generic_param ();
 
   // this is used for the backend to override the HirId ref of the param to
   // what the concrete type is for the rest of the context
@@ -76,7 +76,7 @@ public:
   bool need_substitution () const;
 
 private:
-  const HIR::TypeParam &generic;
+  HIR::TypeParam &generic;
   ParamType *param;
 };
 
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc 
b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
index 1aba57631a2..38f9d526e04 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
@@ -238,7 +238,7 @@ GenericTyVisitorCtx::process_type (ADTType &ty)
   first_lifetime = lookup_or_add_type (ty.get_orig_ref ());
   first_type = first_lifetime + ty.get_used_arguments ().get_regions ().size 
();
 
-  for (const auto &param : ty.get_substs ())
+  for (auto &param : ty.get_substs ())
     param_names.push_back (
       param.get_generic_param ().get_type_representation ().as_string ());
 
diff --git a/gcc/testsuite/rust/compile/issue-3625.rs 
b/gcc/testsuite/rust/compile/issue-3625.rs
new file mode 100644
index 00000000000..91e0dc9088d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3625.rs
@@ -0,0 +1,2 @@
+type A = crate::A;
+// { dg-error "failed to resolve type path segment: .A." "" { target *-*-* } 
.-2 }
-- 
2.49.0

Reply via email to