aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2025-03-26 19:00:41 +0000
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-31 21:07:16 +0200
commit0b522745670e83ee4b5af0782982743b3f715c30 (patch)
tree441fd7ee25c5ca23b69fdb5efb5f22c394652938 /gcc
parente60632a2797cb40d301a7421011d2d974a3612df (diff)
downloadgcc-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.cc13
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc59
-rw-r--r--gcc/rust/typecheck/rust-tyty.h8
-rw-r--r--gcc/testsuite/rust/compile/issue-3553.rs18
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()
+ }
+}