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