diff options
author | Philip Herron <herron.philip@googlemail.com> | 2025-03-26 19:00:41 +0000 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-03-31 21:07:16 +0200 |
commit | 0b522745670e83ee4b5af0782982743b3f715c30 (patch) | |
tree | 441fd7ee25c5ca23b69fdb5efb5f22c394652938 /gcc | |
parent | e60632a2797cb40d301a7421011d2d974a3612df (diff) | |
download | gcc-0b522745670e83ee4b5af0782982743b3f715c30.zip gcc-0b522745670e83ee4b5af0782982743b3f715c30.tar.gz gcc-0b522745670e83ee4b5af0782982743b3f715c30.tar.bz2 |
gccrs: Add check for super traits being implemented by Self
We need to recursively check the super traits of the predicate the Self
type is trying to implement. Otherwise its cannot implement it.
Fixes Rust-GCC#3553
gcc/rust/ChangeLog:
* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::resolve_impl_block_substitutions):
Track the polarity
* typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::validate_type_implements_this):
new validator
* typecheck/rust-tyty.h: new prototypes
gcc/testsuite/ChangeLog:
* rust/compile/issue-3553.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-item.cc | 13 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-bounds.cc | 59 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/issue-3553.rs | 18 |
4 files changed, 95 insertions, 3 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index a003848..9774921 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -725,11 +725,11 @@ TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block, // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs // for example - specified_bound = get_predicate_from_bound (ref, impl_block.get_type ()); + specified_bound = get_predicate_from_bound (ref, impl_block.get_type (), + impl_block.get_polarity ()); } TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ()); - if (self->is<TyTy::ErrorType> ()) { // we cannot check for unconstrained type arguments when the Self type is @@ -771,7 +771,14 @@ TypeCheckItem::validate_trait_impl_block ( // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs // for example - specified_bound = get_predicate_from_bound (ref, impl_block.get_type ()); + specified_bound = get_predicate_from_bound (ref, impl_block.get_type (), + impl_block.get_polarity ()); + + // need to check that if this specified bound has super traits does this + // Self + // implement them? + specified_bound.validate_type_implements_super_traits ( + *self, impl_block.get_type (), impl_block.get_trait_ref ()); } bool is_trait_impl_block = !trait_reference->is_error (); diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 65f24c0..e028a0a 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -828,6 +828,65 @@ TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const return true; } +bool +TypeBoundPredicate::validate_type_implements_super_traits ( + TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const +{ + if (get_polarity () != BoundPolarity::RegularBound) + return true; + + auto &ptref = *get (); + for (auto &super : super_traits) + { + if (super.get_polarity () != BoundPolarity::RegularBound) + continue; + + if (!super.validate_type_implements_this (self, impl_type, trait)) + { + auto &sptref = *super.get (); + + // emit error + std::string fixit1 + = "required by this bound in: " + ptref.get_name (); + std::string fixit2 = "the trait " + sptref.get_name () + + " is not implemented for " + + impl_type.as_string (); + + rich_location r (line_table, trait.get_locus ()); + r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ()); + r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ()); + rust_error_at (r, ErrorCode::E0277, + "the trait bound %<%s: %s%> is not satisfied", + impl_type.as_string ().c_str (), + sptref.get_name ().c_str ()); + + return false; + } + + if (!super.validate_type_implements_super_traits (self, impl_type, trait)) + return false; + } + + return true; +} + +bool +TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self, + HIR::Type &impl_type, + HIR::Type &trait) const +{ + const auto &ptref = *get (); + auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self); + for (auto &elem : probed_bounds) + { + auto &tref = *(elem.first); + if (ptref.is_equal (tref)) + return true; + } + + return false; +} + // trait item reference const Resolver::TraitItemReference * diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 0bfd29d..e814f07 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -578,6 +578,14 @@ public: bool is_equal (const TypeBoundPredicate &other) const; + bool validate_type_implements_super_traits (TyTy::BaseType &self, + HIR::Type &impl_type, + HIR::Type &trait) const; + + bool validate_type_implements_this (TyTy::BaseType &self, + HIR::Type &impl_type, + HIR::Type &trait) const; + private: struct mark_is_error { diff --git a/gcc/testsuite/rust/compile/issue-3553.rs b/gcc/testsuite/rust/compile/issue-3553.rs new file mode 100644 index 0000000..546f3c1 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3553.rs @@ -0,0 +1,18 @@ +trait Foo { + fn f(&self) -> isize; +} + +trait Bar: Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize, +} + +impl Bar for A { + // { dg-error "the trait bound .A: Foo. is not satisfied .E0277." "" { target *-*-* } .-1 } + fn g(&self) -> isize { + self.f() + } +} |