[COMMITTED 45/83] gccrs: Add new resolution mode CANONICAL/REFERNECE to type-check-type

arthur.cohen@opensrcsec.com arthur.cohen@opensrcsec.com
Wed Sep 16 12:30:04 GMT 2026


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

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 <herron.philip@googlemail.com>
---
 .../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(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-4829-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-4829-2.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 112aba4c00f..e44221a7e98 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 27d2ae40af0..9cc0fdbc3e9 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 00000000000..906beb596de
--- /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 00000000000..fa3643ad85b
--- /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,
+{
+}
-- 
2.50.1



More information about the Gcc-rust mailing list