[gccrs COMMIT 16/17] gccrs: seperate implitem fntype and body resolution

gerris.rs@gmail.com gerris.rs@gmail.com
Sun Aug 30 21:46:12 GMT 2026


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

This builds upon the previous patch to seperate fn hir item body and
signiture resolution to stop crate cascades.

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit):
	check need to resolve body
	* typecheck/rust-hir-type-check-implitem.h: new resolve sig
	* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::Resolve): check recursion
	(TypeCheckItem::ResolveFunctionSignature): new helper
	(TypeCheckItem::ResolveImplBlockSelf): missing lifetime pin
	(TypeCheckItem::visit): likewise
	* typecheck/rust-hir-type-check-item.h: new helper
	* typecheck/rust-hir-type-check.h: track function body pending
	* typecheck/rust-type-util.cc (query_type): track associated self
	(normalize_projection): check compatable
	* typecheck/rust-typecheck-context.cc (TypeCheckContext::mark_function_body_pending):
	marker to make sure body gets resolved later
	(TypeCheckContext::clear_function_body_pending): clear market
	(TypeCheckContext::function_body_pending): new set

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: https://github.com/Rust-GCC/gccrs/commit/d55d6e8cbc504859abc497688751cd9bfbd2d1e1

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4816

 .../typecheck/rust-hir-type-check-implitem.cc | 29 ++++++-
 .../typecheck/rust-hir-type-check-implitem.h  |  4 +
 .../typecheck/rust-hir-type-check-item.cc     | 26 ++++++-
 gcc/rust/typecheck/rust-hir-type-check-item.h |  2 +
 gcc/rust/typecheck/rust-hir-type-check.h      |  6 ++
 gcc/rust/typecheck/rust-type-util.cc          | 77 +++++++++++++------
 gcc/rust/typecheck/rust-typecheck-context.cc  | 42 +++++++++-
 7 files changed, 159 insertions(+), 27 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index f8808351e..57f1718e9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -191,7 +191,14 @@ TypeCheckImplItem::Resolve (
   bool already_resolved
     = context->lookup_type (item.get_impl_mappings ().get_hirid (), &resolved);
   if (already_resolved)
-    return resolved;
+    {
+      bool function_body_pending = false;
+      if (auto fn = resolved->try_as<TyTy::FnType> ())
+	function_body_pending = context->function_body_pending (fn->get_id ());
+
+      if (!function_body_pending)
+	return resolved;
+    }
 
   // resolve
   TypeCheckImplItem resolver (parent, self, substitutions);
@@ -203,6 +210,22 @@ TypeCheckImplItem::Resolve (
   return resolver.result;
 }
 
+TyTy::FnType *
+TypeCheckImplItem::ResolveFunctionSignature (
+  HIR::ImplBlock &parent, HIR::Function &function, TyTy::BaseType *self,
+  std::vector<TyTy::SubstitutionParamMapping> substitutions)
+{
+  TypeCheckImplItem resolver (parent, self, std::move (substitutions));
+  auto binder_pin = resolver.context->push_lifetime_binder ();
+  resolver.context->block_context ().enter (
+    TypeCheckBlockContextItem (&parent));
+  TyTy::FnType *result = resolver.resolve_function_signature (function);
+  resolver.context->block_context ().exit ();
+  if (result != nullptr)
+    resolver.context->mark_function_body_pending (result->get_id ());
+  return result;
+}
+
 TyTy::FnType *
 TypeCheckImplItem::resolve_function_signature (HIR::Function &function)
 {
@@ -388,6 +411,10 @@ TypeCheckImplItem::visit (HIR::Function &function)
   if (resolve_fn_type == nullptr)
     return;
 
+  // Mark the body as claimed before resolving it.  Recursive queries from the
+  // body must reuse the cached signature rather than re-entering this body.
+  context->clear_function_body_pending (resolve_fn_type->get_id ());
+
   // need to get the return type from this
   auto expected_ret_tyty = resolve_fn_type->get_return_type ();
   context->push_return_type (TypeCheckContextItem (parent, &function),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index cba105434..6cef0353f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -50,6 +50,10 @@ public:
   Resolve (HIR::ImplBlock &parent, HIR::ImplItem &item, TyTy::BaseType *self,
 	   std::vector<TyTy::SubstitutionParamMapping> substitutions);
 
+  static TyTy::FnType *ResolveFunctionSignature (
+    HIR::ImplBlock &parent, HIR::Function &function, TyTy::BaseType *self,
+    std::vector<TyTy::SubstitutionParamMapping> substitutions);
+
   void visit (HIR::Function &function) override;
   void visit (HIR::ConstantItem &const_item) override;
   void visit (HIR::TypeAlias &type_alias) override;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index 25fa97a36..ba4017adc 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -93,7 +93,14 @@ TypeCheckItem::Resolve (HIR::Item &item)
   bool already_resolved
     = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
   if (already_resolved)
-    return resolved;
+    {
+      bool function_body_pending = false;
+      if (auto fn = resolved->try_as<TyTy::FnType> ())
+	function_body_pending = context->function_body_pending (fn->get_id ());
+
+      if (!function_body_pending)
+	return resolved;
+    }
 
   rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
   HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
@@ -103,6 +110,17 @@ TypeCheckItem::Resolve (HIR::Item &item)
   return resolver.infered;
 }
 
+TyTy::FnType *
+TypeCheckItem::ResolveFunctionSignature (HIR::Function &function)
+{
+  TypeCheckItem resolver;
+  auto lifetime_pin = resolver.context->push_clean_lifetime_resolver ();
+  TyTy::FnType *result = resolver.resolve_function_signature (function);
+  if (result != nullptr)
+    resolver.context->mark_function_body_pending (result->get_id ());
+  return result;
+}
+
 TyTy::BaseType *
 TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
 {
@@ -114,6 +132,7 @@ TyTy::BaseType *
 TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
 {
   TypeCheckItem resolver;
+  auto lifetime_pin = resolver.context->push_clean_lifetime_resolver (true);
 
   bool failed_flag = false;
   auto result
@@ -135,6 +154,7 @@ TypeCheckItem::ResolveImplBlockSelfWithInference (
   TyTy::SubstitutionArgumentMappings *infer_arguments)
 {
   TypeCheckItem resolver;
+  auto lifetime_pin = resolver.context->push_clean_lifetime_resolver (true);
 
   bool failed_flag = false;
   auto result = resolver.resolve_impl_block_substitutions (impl, failed_flag);
@@ -876,6 +896,10 @@ TypeCheckItem::visit (HIR::Function &function)
   if (resolved_fn_type == nullptr)
     return;
 
+  // Mark the body as claimed before resolving it.  Recursive queries from the
+  // body must reuse the cached signature rather than re-entering this body.
+  context->clear_function_body_pending (resolved_fn_type->get_id ());
+
   // need to get the return type from this
   auto expected_ret_tyty = resolved_fn_type->get_return_type ();
   context->push_return_type (TypeCheckContextItem (&function),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 389b0fd9a..9b223f291 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -30,6 +30,8 @@ class TypeCheckItem : private TypeCheckBase, private HIR::HIRVisItemVisitor
 public:
   static TyTy::BaseType *Resolve (HIR::Item &item);
 
+  static TyTy::FnType *ResolveFunctionSignature (HIR::Function &function);
+
   static TyTy::BaseType *ResolveImplItem (HIR::ImplBlock &impl_block,
 					  HIR::ImplItem &item);
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 916ee2f2d..1e830713e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -209,6 +209,10 @@ public:
   bool lookup_type (HirId id, TyTy::BaseType **type) const;
   void clear_type (TyTy::BaseType *ty);
 
+  void mark_function_body_pending (DefId id);
+  void clear_function_body_pending (DefId id);
+  bool function_body_pending (DefId id) const;
+
   void insert_implicit_type (HirId id, TyTy::BaseType *type);
 
   void insert_type_by_node_id (NodeId ref, HirId id);
@@ -239,6 +243,7 @@ public:
 
   bool
   find_matching_impl_trait_frame (const TraitReference &tref,
+				  TyTy::BaseType &self,
 				  struct ImplTraitContextFrame *find) const;
   bool have_impl_trait_context () const;
   void push_impl_trait_context (struct ImplTraitContextFrame frame);
@@ -329,6 +334,7 @@ private:
 
   std::map<NodeId, HirId> node_id_refs;
   std::map<HirId, TyTy::BaseType *> resolved;
+  std::set<DefId> function_bodies_pending;
   std::vector<std::unique_ptr<TyTy::BaseType>> builtins;
   std::vector<std::pair<TypeCheckContextItem, TyTy::BaseType *>>
     return_type_stack;
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index 97ff25d43..1ba486626 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-hir-item.h"
 #include "rust-system.h"
 #include "rust-type-util.h"
 #include "rust-diagnostics.h"
@@ -73,7 +74,21 @@ query_type (HirId reference, TyTy::BaseType **result)
     {
       rust_debug_loc (item.value ()->get_locus (), "resolved item {%u} to",
 		      reference);
-      *result = TypeCheckItem::Resolve (*item.value ());
+
+      DefId item_defid = item.value ()->get_mappings ().get_defid ();
+      bool is_local = item_defid.crateNum == mappings.get_current_crate ();
+      bool is_fn
+	= item.value ()->get_item_kind () == HIR::Item::ItemKind::Function;
+      if (is_fn && is_local)
+	{
+	  HIR::Function &fn = *static_cast<HIR::Function *> (item.value ());
+	  *result = TypeCheckItem::ResolveFunctionSignature (fn);
+	}
+      else
+	{
+	  *result = TypeCheckItem::Resolve (*item.value ());
+	}
+
       context->query_completed (reference);
       return true;
     }
@@ -82,30 +97,33 @@ query_type (HirId reference, TyTy::BaseType **result)
     {
       auto impl_block
 	= mappings.lookup_hir_impl_block (impl_item->second).value ();
+      auto lifetime_pin = context->push_clean_lifetime_resolver (true);
 
-      tl::optional<ImplTraitFrameGuard> guard;
-      if (impl_block->has_trait_ref ())
+      bool failure_flag = false;
+      auto substitutions
+	= TypeCheckItem::ResolveImplBlockSubstitutions (*impl_block,
+							failure_flag);
+      if (failure_flag)
 	{
-	  bool failure_flag = false;
-	  auto substitutions
-	    = TypeCheckItem::ResolveImplBlockSubstitutions (*impl_block,
-							    failure_flag);
-	  if (failure_flag)
-	    {
-	      context->query_completed (reference);
-	      return false;
-	    }
+	  *result
+	    = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item->first);
+	  context->query_completed (reference);
+	  return true;
+	}
 
-	  TyTy::BaseType *self = nullptr;
-	  bool ok
-	    = query_type (impl_block->get_type ().get_mappings ().get_hirid (),
-			  &self);
-	  if (!ok)
-	    {
-	      context->query_completed (reference);
-	      return false;
-	    }
+      TyTy::BaseType *self = nullptr;
+      bool ok
+	= query_type (impl_block->get_type ().get_mappings ().get_hirid (),
+		      &self);
+      if (!ok)
+	{
+	  context->query_completed (reference);
+	  return false;
+	}
 
+      tl::optional<ImplTraitFrameGuard> guard;
+      if (impl_block->has_trait_ref ())
+	{
 	  HIR::TypePath &ref = impl_block->get_trait_ref ();
 	  auto trait_reference = TraitResolver::Resolve (ref);
 	  if (trait_reference->is_error ())
@@ -132,7 +150,19 @@ query_type (HirId reference, TyTy::BaseType **result)
       rust_debug_loc (impl_item->first->get_locus (),
 		      "resolved impl-item {%u} to", reference);
 
-      *result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item->first);
+      DefId item_defid = impl_item->first->get_impl_mappings ().get_defid ();
+      bool is_local = item_defid.crateNum == mappings.get_current_crate ();
+      if (impl_item->first->get_impl_item_type () == HIR::ImplItem::FUNCTION
+	  && is_local)
+	{
+	  HIR::Function &fn = *static_cast<HIR::Function *> (impl_item->first);
+	  *result = TypeCheckImplItem::ResolveFunctionSignature (
+	    *impl_block, fn, self, std::move (substitutions));
+	}
+      else
+	*result = TypeCheckImplItem::Resolve (*impl_block, *impl_item->first,
+					      self, std::move (substitutions));
+
       context->query_completed (reference);
       return true;
     }
@@ -606,7 +636,8 @@ normalize_projection (TyTy::ProjectionType *proj, location_t locus,
     }
 
   ImplTraitContextFrame frame;
-  if (!ctx->find_matching_impl_trait_frame (*proj->get_trait_ref (), &frame))
+  if (!ctx->find_matching_impl_trait_frame (*proj->get_trait_ref (),
+					    *proj->get_self (), &frame))
     {
       // No concrete impl frame check WHERE clause bindings on the self type
       //
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
index 5b482dd9f..44744730b 100644
--- a/gcc/rust/typecheck/rust-typecheck-context.cc
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -109,6 +109,24 @@ TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
   return true;
 }
 
+void
+TypeCheckContext::mark_function_body_pending (DefId id)
+{
+  function_bodies_pending.insert (id);
+}
+
+void
+TypeCheckContext::clear_function_body_pending (DefId id)
+{
+  function_bodies_pending.erase (id);
+}
+
+bool
+TypeCheckContext::function_body_pending (DefId id) const
+{
+  return function_bodies_pending.find (id) != function_bodies_pending.end ();
+}
+
 void
 TypeCheckContext::clear_type (TyTy::BaseType *ty)
 {
@@ -253,7 +271,8 @@ TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
 
 bool
 TypeCheckContext::find_matching_impl_trait_frame (
-  const TraitReference &tref, struct ImplTraitContextFrame *find) const
+  const TraitReference &tref, TyTy::BaseType &self,
+  struct ImplTraitContextFrame *find) const
 {
   if (!have_impl_trait_context ())
     return false;
@@ -262,7 +281,26 @@ TypeCheckContext::find_matching_impl_trait_frame (
        it != impl_trait_frame_stack.rend (); ++it)
     {
       const auto &i = *it;
-      if (i.trait->is_equal (tref))
+      if (!i.trait->is_equal (tref))
+	continue;
+
+      TyTy::BaseType *resolved_self = &self;
+      bool unresolved_trait_self = false;
+      if (auto param = self.try_as<TyTy::ParamType> ())
+	{
+	  if (param->can_resolve ())
+	    resolved_self = param->resolve ();
+	  else
+	    unresolved_trait_self = param->is_implicit_self_trait ();
+	}
+
+      bool compatible_self
+	= unresolved_trait_self
+	  || types_compatable (TyTy::TyWithLocation (i.self),
+			       TyTy::TyWithLocation (resolved_self),
+			       UNDEF_LOCATION, false /* emit_errors */,
+			       false /* check_bounds */);
+      if (compatible_self)
 	{
 	  *find = i;
 	  return true;
-- 
2.55.0



More information about the Gcc-rust mailing list