From: Philip Herron <herron.phi...@googlemail.com>

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>
---
 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 --
 .../rust/execute/torture/issue-3126.rs        | 52 +++++++++++++++++++
 6 files changed, 78 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-3126.rs

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 98323f63132..58a0f014926 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 916abe6c9d0..b79fe17ee3e 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 7a39eb53710..4abfbae3665 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 9187fc63141..d7007879228 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 3951fa88da8..efad5f61322 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 00000000000..f5051467f02
--- /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
+}
-- 
2.45.2

Reply via email to