]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: ensure assoicated types are setup for concrete trait impl blocks
authorPhilip Herron <herron.philip@googlemail.com>
Mon, 12 Jun 2023 15:07:13 +0000 (16:07 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:46:27 +0000 (18:46 +0100)
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 <herron.philip@googlemail.com>
gcc/rust/backend/rust-compile-item.cc
gcc/rust/typecheck/rust-hir-trait-reference.h
gcc/rust/typecheck/rust-hir-trait-resolve.cc
gcc/testsuite/rust/compile/issue-2019-1.rs [new file with mode: 0644]

index 26f56c70886795d840b062e9b985b05642bccfeb..b83ef56788b0f8c116ae7f888909de8794441b83 100644 (file)
@@ -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 (
index 76d2d8bae83db6c5eb4c645a07b08abe21ead77d..c0a6f561ada27b2e13e6ed7bfdb534415e23fe1f 100644 (file)
@@ -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);
index cf8c9c9780789018a1cfd774bd0d4bca65a12cfd..7c6ce4c7a2d79199c66fc36b6c743f5e50e72cd1 100644 (file)
@@ -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<HIR::TypeAlias *> (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 (file)
index 0000000..f359ea4
--- /dev/null
@@ -0,0 +1,22 @@
+#[lang = "add"]
+pub trait Add<RHS = Self> {
+    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<u32> for &'a u32 {
+    type Output = <u32 as Add<u32>>::Output;
+
+    fn add(self, other: u32) -> <u32 as Add<u32>>::Output {
+        Add::add(*self, other)
+    }
+}