https://gcc.gnu.org/g:f388cac59df2704026b6a0585efba70154640b12

commit r15-9279-gf388cac59df2704026b6a0585efba70154640b12
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Wed Apr 2 18:21:46 2025 +0100

    gccrs: Fix recusive type query and nullptr on type path
    
    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>

Diff:
---
 gcc/rust/typecheck/rust-hir-trait-resolve.cc       |   4 +-
 gcc/rust/typecheck/rust-hir-type-check-base.cc     |  42 +++++-
 gcc/rust/typecheck/rust-hir-type-check-base.h      |   8 +-
 gcc/rust/typecheck/rust-hir-type-check-implitem.cc | 163 +--------------------
 gcc/rust/typecheck/rust-hir-type-check-path.cc     |   2 +-
 gcc/rust/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 +-
 gcc/rust/typecheck/rust-tyty-variance-analysis.cc  |   2 +-
 gcc/testsuite/rust/compile/issue-3625.rs           |   2 +
 13 files changed, 144 insertions(+), 218 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index a236fd78d7b1..e78c19263dc1 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 d3d688217348..beee91e79444 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 8a1bf6f4cb35..580082a6adfb 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 a5ae54bf4930..29864b0c8e6d 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 1fe39aaeb649..5662da5310e5 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 54f50ec41f18..6919093b0f5f 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 fc272e639a3f..cc991b66eb89 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 a198ad3d66da..49c19055300d 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 4abfbae36655..c6c5b4bb55fa 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 95f18b9d29fc..bdb6474aeeb4 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 3f0b912fa7b0..e6ed1fc42d67 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 1aba57631a29..38f9d526e045 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 000000000000..91e0dc9088da
--- /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 }

Reply via email to