https://gcc.gnu.org/g:31ee9259a71742a455ead61c8b6142dcfab28b0f

commit 31ee9259a71742a455ead61c8b6142dcfab28b0f
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Wed Mar 26 19:00:41 2025 +0000

    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.phi...@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-hir-type-check-item.cc | 13 ++++--
 gcc/rust/typecheck/rust-tyty-bounds.cc         | 59 ++++++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty.h                 |  8 ++++
 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 25da29b31786..f13e3a960d98 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 dc42941da233..853ed7ee3e87 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 a5840544de42..dc30d7dd0686 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 000000000000..546f3c17bedd
--- /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()
+    }
+}

Reply via email to