[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