https://gcc.gnu.org/g:1f650869b6b4d7505714618a294126aeaeac29c5

commit r15-8847-g1f650869b6b4d7505714618a294126aeaeac29c5
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Wed Mar 12 17:03:25 2025 +0000

    gccrs: check for recursion trait cycle with bounds checks
    
    We need to be careful when doing bounds check as to not create a recusive
    trait resolution. This patch checks for that case and fixes a bad type
    is equal check on ADT Types which was caught with a regression here.
    
    Fixes Rust-GCC#3126
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-trait-resolve.cc 
(TraitResolver::ResolveHirItem): new helper
            * typecheck/rust-hir-trait-resolve.h: add helper prototype
            * typecheck/rust-type-util.cc (query_type): add debug
            * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): check for 
recursion
            * typecheck/rust-tyty.cc (VariantDef::is_equal): fix is equal check
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/torture/issue-3126.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-hir-trait-resolve.cc     | 10 +++++
 gcc/rust/typecheck/rust-hir-trait-resolve.h      |  2 +
 gcc/rust/typecheck/rust-type-util.cc             |  7 +++-
 gcc/rust/typecheck/rust-tyty-bounds.cc           |  9 ++++
 gcc/rust/typecheck/rust-tyty.cc                  |  3 --
 gcc/testsuite/rust/execute/torture/issue-3126.rs | 52 ++++++++++++++++++++++++
 6 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 98323f63132b..58a0f0149265 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -107,6 +107,16 @@ TraitResolver::Lookup (HIR::TypePath &path)
   return resolver.lookup_path (path);
 }
 
+HIR::Trait *
+TraitResolver::ResolveHirItem (const HIR::TypePath &path)
+{
+  TraitResolver resolver;
+
+  HIR::Trait *lookup = nullptr;
+  bool ok = resolver.resolve_path_to_trait (path, &lookup);
+  return ok ? lookup : nullptr;
+}
+
 TraitResolver::TraitResolver () : TypeCheckBase () {}
 
 bool
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h 
b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 916abe6c9d09..b79fe17ee3ee 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -58,6 +58,8 @@ public:
 
   static TraitReference *Lookup (HIR::TypePath &path);
 
+  static HIR::Trait *ResolveHirItem (const HIR::TypePath &path);
+
 private:
   TraitResolver ();
 
diff --git a/gcc/rust/typecheck/rust-type-util.cc 
b/gcc/rust/typecheck/rust-type-util.cc
index 7a39eb53710f..4abfbae36655 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -87,8 +87,11 @@ query_type (HirId reference, TyTy::BaseType **result)
   // is it an impl_type?
   if (auto impl_block_by_type = mappings.lookup_impl_block_type (reference))
     {
-      *result
-       = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type.value ());
+      // found an impl item
+      HIR::ImplBlock *impl = impl_block_by_type.value ();
+      rust_debug_loc (impl->get_locus (), "resolved impl block type {%u} to",
+                     reference);
+      *result = TypeCheckItem::ResolveImplBlockSelf (*impl);
       context->query_completed (reference);
       return true;
     }
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc 
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 9187fc63141e..d70078792286 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -20,6 +20,7 @@
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
 #include "rust-substitution-mapper.h"
+#include "rust-hir-trait-resolve.h"
 #include "rust-type-util.h"
 
 namespace Rust {
@@ -71,6 +72,14 @@ TypeBoundsProbe::scan ()
       if (!impl->has_trait_ref ())
        return true;
 
+      // can be recursive trait resolution
+      HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
+      if (t == nullptr)
+       return true;
+      DefId trait_id = t->get_mappings ().get_defid ();
+      if (context->trait_query_in_progress (trait_id))
+       return true;
+
       HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
       TyTy::BaseType *impl_type = nullptr;
       if (!query_type (impl_ty_id, &impl_type))
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 3951fa88da84..efad5f613228 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -1566,9 +1566,6 @@ VariantDef::is_equal (const VariantDef &other) const
   if (identifier.compare (other.identifier) != 0)
     return false;
 
-  if (discriminant != other.discriminant)
-    return false;
-
   if (fields.size () != other.fields.size ())
     return false;
 
diff --git a/gcc/testsuite/rust/execute/torture/issue-3126.rs 
b/gcc/testsuite/rust/execute/torture/issue-3126.rs
new file mode 100644
index 000000000000..f5051467f027
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-3126.rs
@@ -0,0 +1,52 @@
+/* { dg-output "child\r*\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+struct Foo {
+    my_int: u32,
+    // { dg-warning "field is never read: .my_int." "" { target *-*-* } .-1 }
+}
+
+trait Parent<T> {
+    fn parent(&self) -> T;
+}
+
+trait Child: Parent<u32> {
+    fn child(&self);
+}
+
+impl Parent<u32> for Foo {
+    fn parent(&self) -> u32 {
+        unsafe {
+            let parent = "parent %i\n\0";
+            let msg = parent as *const str;
+            printf(msg as *const i8, self.my_int);
+            return self.my_int;
+        }
+    }
+}
+
+impl Child for Foo {
+    fn child(&self) {
+        let _ = self;
+        unsafe {
+            let child = "child\n\0";
+            let msg = child as *const str;
+            printf(msg as *const i8);
+        }
+    }
+}
+
+pub fn main() -> i32 {
+    let a = Foo { my_int: 0xf00dfeed };
+    let b: &dyn Child = &a;
+
+    // b.parent();
+    b.child();
+
+    0
+}

Reply via email to