From: Philip Herron Date: Mon, 12 Jun 2023 15:07:13 +0000 (+0100) Subject: gccrs: ensure assoicated types are setup for concrete trait impl blocks X-Git-Tag: basepoints/gcc-15~2470 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=73a2f1b4d64dcef17aa26a82a6cddc41ad8c87ff;p=thirdparty%2Fgcc.git gccrs: ensure assoicated types are setup for concrete trait impl blocks We have been concentrating on generic impl blocks for so long that we have not handled the simple concrete impl block case where associated types need to be setup when compling a function/method on a trait impl block which uses associated types. Addresses #2019 gcc/rust/ChangeLog: * backend/rust-compile-item.cc (CompileItem::visit): ensure assoicated types are setup * typecheck/rust-hir-trait-reference.h: new interface for concrete impl block * typecheck/rust-hir-trait-resolve.cc (AssociatedImplTrait::setup_raw_associated_types): ensure we setup assoicated types for this impl block gcc/testsuite/ChangeLog: * rust/compile/issue-2019-1.rs: New test. Signed-off-by: Philip Herron --- diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 26f56c708867..b83ef56788b0 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -133,6 +133,23 @@ CompileItem::visit (HIR::Function &function) fntype->monomorphize (); } } + else + { + // if this is part of a trait impl block which is not generic we need to + // ensure associated types are setup + HirId parent_impl_block = UNKNOWN_HIRID; + HirId id = function.get_mappings ().get_hirid (); + HIR::ImplItem *impl_item + = ctx->get_mappings ()->lookup_hir_implitem (id, &parent_impl_block); + if (impl_item != nullptr) + { + Resolver::AssociatedImplTrait *impl = nullptr; + bool found = ctx->get_tyctx ()->lookup_associated_trait_impl ( + parent_impl_block, &impl); + if (found) + impl->setup_raw_associated_types (); + } + } const Resolver::CanonicalPath *canonical_path = nullptr; bool ok = ctx->get_mappings ()->lookup_canonical_path ( diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h index 76d2d8bae83d..c0a6f561ada2 100644 --- a/gcc/rust/typecheck/rust-hir-trait-reference.h +++ b/gcc/rust/typecheck/rust-hir-trait-reference.h @@ -249,6 +249,8 @@ public: TyTy::BaseType *get_self (); const TyTy::BaseType *get_self () const; + void setup_raw_associated_types (); + TyTy::BaseType * setup_associated_types (const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound); diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index cf8c9c978078..7c6ce4c7a2d7 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -400,6 +400,36 @@ TraitItemReference::associated_type_reset (bool only_projections) const } } +void +AssociatedImplTrait::setup_raw_associated_types () +{ + auto &impl_items = impl->get_impl_items (); + for (auto &impl_item : impl_items) + { + bool is_type_alias = impl_item->get_impl_item_type () + == HIR::ImplItem::ImplItemType::TYPE_ALIAS; + if (!is_type_alias) + continue; + + HIR::TypeAlias &type = *static_cast (impl_item.get ()); + + TraitItemReference *resolved_trait_item = nullptr; + bool ok = trait->lookup_trait_item (type.get_new_type_name (), + &resolved_trait_item); + if (!ok) + continue; + if (resolved_trait_item->get_trait_item_type () + != TraitItemReference::TraitItemType::TYPE) + continue; + + TyTy::BaseType *lookup; + ok = context->lookup_type (type.get_mappings ().get_hirid (), &lookup); + rust_assert (ok); + + resolved_trait_item->associated_type_set (lookup); + } +} + TyTy::BaseType * AssociatedImplTrait::setup_associated_types ( const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound) diff --git a/gcc/testsuite/rust/compile/issue-2019-1.rs b/gcc/testsuite/rust/compile/issue-2019-1.rs new file mode 100644 index 000000000000..f359ea4fb15d --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2019-1.rs @@ -0,0 +1,22 @@ +#[lang = "add"] +pub trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u32 { + type Output = u32; + + fn add(self, other: u32) -> u32 { + self + other + } +} + +impl<'a> Add for &'a u32 { + type Output = >::Output; + + fn add(self, other: u32) -> >::Output { + Add::add(*self, other) + } +}