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