https://gcc.gnu.org/g:41e36f5f9e1920b6ad5479e6d46c6f8548797be1

commit r17-4322-g41e36f5f9e1920b6ad5479e6d46c6f8548797be1
Author: Philip Herron <[email protected]>
Date:   Thu Sep 3 11:14:20 2026 +0100

    gccrs: Add new resolution mode CANONICAL/REFERNECE to type-check-type
    
    When handling where clause items such as:
    
      fn check<P>()
        where
          P: Deref,
          P::Target: Marker
    
    What happens is the first 'P' used to get resolved to a reference hir-id
    item which meant that adding the bound to this position had no effect what
    needed to occur was bind it to the parent which meant i used name resolution
    to reverse lookup as a hack. This new mode for canonical gives us that
    parent in the first place so we can just add the bound directly now so no
    need for name resolution here
    
    Fixes Rust-GCC/gccrs#4829
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-type-check-type.cc (TypeCheckType::Resolve): 
new mode
            (TypeCheckType::visit): likewise
            (ResolveWhereClauseItem::visit): remove nr usage
            * typecheck/rust-hir-type-check-type.h: new mode
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-4829-1.rs: New test.
            * rust/compile/issue-4829-2.rs: New test.
    
    Signed-off-by: Philip Herron <[email protected]>

Diff:
---
 gcc/rust/typecheck/rust-hir-type-check-type.cc | 64 ++++++--------------------
 gcc/rust/typecheck/rust-hir-type-check-type.h  | 14 ++++--
 gcc/testsuite/rust/compile/issue-4829-1.rs     | 23 +++++++++
 gcc/testsuite/rust/compile/issue-4829-2.rs     | 18 ++++++++
 4 files changed, 66 insertions(+), 53 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 112aba4c00f6..e44221a7e983 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -61,17 +61,17 @@ TypeCheckResolveGenericArguments::visit 
(HIR::TypePathSegmentGeneric &generic)
 }
 
 TyTy::BaseType *
-TypeCheckType::Resolve (HIR::Type &type)
+TypeCheckType::Resolve (HIR::Type &type, ResolutionMode mode)
 {
   // is it already resolved?
   auto context = TypeCheckContext::get ();
   TyTy::BaseType *resolved = nullptr;
   bool already_resolved
     = context->lookup_type (type.get_mappings ().get_hirid (), &resolved);
-  if (already_resolved)
+  if (already_resolved && mode == ResolutionMode::REFERENCE)
     return resolved;
 
-  TypeCheckType resolver (type.get_mappings ().get_hirid ());
+  TypeCheckType resolver (type.get_mappings ().get_hirid (), mode);
   type.accept_vis (resolver);
   rust_assert (resolver.translated != nullptr);
   resolver.context->insert_type (type.get_mappings (), resolver.translated);
@@ -153,9 +153,14 @@ TypeCheckType::visit (HIR::TypePath &path)
       return;
     }
 
-  TyTy::BaseType *path_type = root->clone ();
-  path_type->set_ref (path.get_mappings ().get_hirid ());
-  context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type);
+  TyTy::BaseType *path_type = root;
+  if (mode == ResolutionMode::REFERENCE)
+    {
+      path_type = root->clone ();
+      path_type->set_ref (path.get_mappings ().get_hirid ());
+      context->insert_implicit_type (path.get_mappings ().get_hirid (),
+                                    path_type);
+    }
 
   bool fully_resolved = offset >= path.get_segments ().size ();
   if (fully_resolved)
@@ -1048,7 +1053,9 @@ ResolveWhereClauseItem::visit 
(HIR::TypeBoundWhereClauseItem &item)
     }
 
   auto &binding_type_path = item.get_bound_type ();
-  TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path);
+  TyTy::BaseType *binding
+    = TypeCheckType::Resolve (binding_type_path,
+                             TypeCheckType::ResolutionMode::CANONICAL);
 
   // FIXME double check there might be a trait cycle here see TypeParam 
handling
 
@@ -1089,49 +1096,6 @@ ResolveWhereClauseItem::visit 
(HIR::TypeBoundWhereClauseItem &item)
        }
     }
   binding->inherit_bounds (specified_bounds);
-
-  // When we apply these bounds we must lookup which type this binding
-  // resolves to, as this is the type which will be used during resolution
-  // of the block.
-  NodeId ast_node_id = binding_type_path.get_mappings ().get_nodeid ();
-
-  // then lookup the reference_node_id
-  NodeId ref_node_id = UNKNOWN_NODEID;
-
-  auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
-
-  if (auto id = nr_ctx.lookup (ast_node_id, Resolver2_0::Namespace::Types))
-    {
-      ref_node_id = *id;
-    }
-  else
-    {
-      // FIXME
-      rust_error_at (UNDEF_LOCATION,
-                    "Failed to lookup type reference for node: %s",
-                    binding_type_path.to_string ().c_str ());
-      return;
-    }
-
-  // node back to HIR
-  if (auto hid = mappings.lookup_node_to_hir (ref_node_id))
-    {
-      // the base reference for this name _must_ have a type set
-      TyTy::BaseType *lookup;
-      if (!context->lookup_type (*hid, &lookup))
-       {
-         rust_error_at (mappings.lookup_location (*hid),
-                        "Failed to resolve where-clause binding type: %s",
-                        binding_type_path.to_string ().c_str ());
-         return;
-       }
-
-      // FIXME
-      // rust_assert (binding->is_equal (*lookup));
-      lookup->inherit_bounds (specified_bounds);
-      return;
-    }
-  rust_error_at (UNDEF_LOCATION, "where-clause reverse lookup failure");
 }
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h 
b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 27d2ae40af0c..9cc0fdbc3e97 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -46,7 +46,14 @@ private:
 class TypeCheckType : public TypeCheckBase, public HIR::HIRTypeVisitor
 {
 public:
-  static TyTy::BaseType *Resolve (HIR::Type &type);
+  enum class ResolutionMode
+  {
+    REFERENCE,
+    CANONICAL
+  };
+
+  static TyTy::BaseType *Resolve (HIR::Type &type, ResolutionMode mode
+                                                  = ResolutionMode::REFERENCE);
 
   void visit (HIR::BareFunctionType &fntype) override;
   void visit (HIR::TupleType &tuple) override;
@@ -67,8 +74,8 @@ public:
   void visit (HIR::TraitBound &bound) override {}
 
 private:
-  TypeCheckType (HirId id)
-    : TypeCheckBase (), translated (new TyTy::ErrorType (id))
+  TypeCheckType (HirId id, ResolutionMode mode)
+    : TypeCheckBase (), translated (new TyTy::ErrorType (id)), mode (mode)
   {}
 
   TyTy::BaseType *resolve_root_path (HIR::TypePath &path, size_t *offset,
@@ -89,6 +96,7 @@ private:
     bool ty_seg_is_big_self, TyTy::BaseType **result);
 
   TyTy::BaseType *translated;
+  ResolutionMode mode;
 };
 
 class TypeResolveGenericParam : public TypeCheckBase
diff --git a/gcc/testsuite/rust/compile/issue-4829-1.rs 
b/gcc/testsuite/rust/compile/issue-4829-1.rs
new file mode 100644
index 000000000000..906beb596de7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4829-1.rs
@@ -0,0 +1,23 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+trait Iterator {
+    type Item;
+}
+
+trait IntoIterator {
+    type IntoIter;
+}
+
+pub struct FlattenCompat<I, U>(I, U);
+
+pub struct Flatten<I>
+where
+    I: Iterator,
+    I::Item: IntoIterator,
+{
+    pub inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
+}
diff --git a/gcc/testsuite/rust/compile/issue-4829-2.rs 
b/gcc/testsuite/rust/compile/issue-4829-2.rs
new file mode 100644
index 000000000000..fa3643ad85b0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4829-2.rs
@@ -0,0 +1,18 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+trait Deref {
+    type Target;
+}
+
+trait Marker {}
+
+pub fn check<P>()
+where
+    P: Deref,
+    P::Target: Marker,
+{
+}

Reply via email to