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, +{ +}
