From: Enes Cevik <[email protected]>

This patch adds support for structural auto-traits and fixes how negative
trait implementations are handled.

gcc/rust/ChangeLog:

        * typecheck/rust-tyty-bounds.cc
        (TypeBoundsProbe::add_trait_bound): Check all fields of an ADT.
        * typecheck/rust-tyty.cc (BaseType::satisfies_bound): Reject
        trait if there is a negative impl.

Signed-off-by: Enes Cevik <[email protected]>
---
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/4597a4c3229aa4a1484466f92aeab06c9bcc545a

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/4720

 gcc/rust/typecheck/rust-tyty-bounds.cc | 28 ++++++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty.cc        | 14 ++++++++++---
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc 
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 5ec3f0b40..21a55ac6c 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -181,6 +181,34 @@ TypeBoundsProbe::add_trait_bound (HIR::Trait *trait)
 {
   auto trait_ref = TraitResolver::Resolve (*trait);
 
+  for (const auto &existing : trait_references)
+    if (existing.first->is_equal (*trait_ref))
+      return;
+
+  if (receiver->get_kind () == TyTy::TypeKind::ADT)
+    {
+      TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver);
+      for (auto &variant : adt->get_variants ())
+       {
+         for (auto &field : variant->get_fields ())
+           {
+             TyTy::BaseType *field_ty = field->get_field_type ();
+
+             // TODO: A loop guard is needed here to prevent infinite
+             // recursion, but self-referential types currently crash due to
+             // issue Rust-GCC/gccrs#4709. Therefore, I avoided adding an
+             // untested guard for now.
+
+             if (!field_ty->satisfies_bound (
+                   TyTy::TypeBoundPredicate (*trait_ref,
+                                             BoundPolarity::RegularBound,
+                                             UNDEF_LOCATION),
+                   false))
+               return;
+           }
+       }
+    }
+
   trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ());
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index af43b1c12..65130ea25 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -324,10 +324,18 @@ BaseType::satisfies_bound (const TypeBoundPredicate 
&predicate, bool emit_error)
       if (!bound->is_equal (*query))
        continue;
 
-      // builtin ones have no impl-block this needs fixed and use a builtin 
node
-      // of somekind
+      // builtin ones have no impl-block this needs fixed and use a builtin
+      // node of somekind
       if (b.second == nullptr)
-       return true;
+       {
+         return predicate.get_polarity () == BoundPolarity::RegularBound;
+       }
+      else
+       {
+         const auto &impl = *(b.second);
+         if (predicate.get_polarity () != impl.get_polarity ())
+           continue;
+       }
 
       // need to check that associated types can match as well
       const HIR::ImplBlock &impl = *(b.second);

base-commit: 7a0c8beaa0c2cdd5607e561edeeebee196277ad9
-- 
2.54.0

Reply via email to