From: Philip Herron <[email protected]>
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 <[email protected]>
---
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