From: Philip Herron <herron.phi...@googlemail.com> Generics can be constrained within other generic types so this check needs to be recursive.
Fixes Rust-GCC#3031 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): recursive walker * typecheck/rust-tyty.cc (BaseType::get_subst_argument_mappings): new helper * typecheck/rust-tyty.h: prototype gcc/testsuite/ChangeLog: * rust/compile/issue-3031.rs: New test. Signed-off-by: Philip Herron <herron.phi...@googlemail.com> --- .../typecheck/rust-hir-type-check-base.cc | 42 +++++++++++-------- gcc/rust/typecheck/rust-tyty.cc | 42 +++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 1 + gcc/testsuite/rust/compile/issue-3031.rs | 15 +++++++ 4 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-3031.rs diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 34f629c0519..8f2471d54d5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -31,6 +31,26 @@ TypeCheckBase::TypeCheckBase () context (TypeCheckContext::get ()) {} +static void +walk_types_to_constrain (std::set<HirId> &constrained_symbols, + const TyTy::SubstitutionArgumentMappings &constraints) +{ + for (const auto &c : constraints.get_mappings ()) + { + const TyTy::BaseType *arg = c.get_tyty (); + if (arg != nullptr) + { + const TyTy::BaseType *p = arg->get_root (); + constrained_symbols.insert (p->get_ty_ref ()); + if (p->has_substitutions_defined ()) + { + walk_types_to_constrain (constrained_symbols, + p->get_subst_argument_mappings ()); + } + } + } +} + bool TypeCheckBase::check_for_unconstrained ( const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain, @@ -52,28 +72,14 @@ TypeCheckBase::check_for_unconstrained ( HirId ref = p.get_param_ty ()->get_ref (); symbols_to_constrain.insert (ref); symbol_to_location.insert ({ref, p.get_param_locus ()}); + + rust_debug_loc (p.get_param_locus (), "XX constrain THIS"); } // set up the set of constrained symbols std::set<HirId> constrained_symbols; - for (const auto &c : constraint_a.get_mappings ()) - { - const TyTy::BaseType *arg = c.get_tyty (); - if (arg != nullptr) - { - const TyTy::BaseType *p = arg->get_root (); - constrained_symbols.insert (p->get_ty_ref ()); - } - } - for (const auto &c : constraint_b.get_mappings ()) - { - const TyTy::BaseType *arg = c.get_tyty (); - if (arg != nullptr) - { - const TyTy::BaseType *p = arg->get_root (); - constrained_symbols.insert (p->get_ty_ref ()); - } - } + walk_types_to_constrain (constrained_symbols, constraint_a); + walk_types_to_constrain (constrained_symbols, constraint_b); const auto root = reference->get_root (); if (root->get_kind () == TyTy::TypeKind::PARAM) diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 8f388120a41..fe4b8fca139 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -888,6 +888,48 @@ BaseType::needs_generic_substitutions () const return false; } +const SubstitutionArgumentMappings & +BaseType::get_subst_argument_mappings () const +{ + static auto empty = SubstitutionArgumentMappings::empty (); + const TyTy::BaseType *x = destructure (); + switch (x->get_kind ()) + { + case PROJECTION: { + const auto &p = *static_cast<const ProjectionType *> (x); + const auto &ref = static_cast<const SubstitutionRef &> (p); + return ref.get_substitution_arguments (); + } + break; + + case FNDEF: { + const auto &fn = *static_cast<const FnType *> (x); + const auto &ref = static_cast<const SubstitutionRef &> (fn); + return ref.get_substitution_arguments (); + } + break; + + case ADT: { + const auto &adt = *static_cast<const ADTType *> (x); + const auto &ref = static_cast<const SubstitutionRef &> (adt); + return ref.get_substitution_arguments (); + } + break; + + case CLOSURE: { + const auto &closure = *static_cast<const ClosureType *> (x); + const auto &ref = static_cast<const SubstitutionRef &> (closure); + return ref.get_substitution_arguments (); + } + break; + + default: + return empty; + } + + return empty; +} + // InferType InferType::InferType (HirId ref, InferTypeKind infer_kind, TypeHint hint, diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 93c4a15a460..504a14e3773 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -174,6 +174,7 @@ public: bool has_substitutions_defined () const; bool needs_generic_substitutions () const; + const SubstitutionArgumentMappings &get_subst_argument_mappings () const; std::string mangle_string () const { diff --git a/gcc/testsuite/rust/compile/issue-3031.rs b/gcc/testsuite/rust/compile/issue-3031.rs new file mode 100644 index 00000000000..33f5bf07471 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3031.rs @@ -0,0 +1,15 @@ +#![feature(no_core)] +#![feature(lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +trait A<T: ?Sized> {} + +struct Cell<X> { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + x: X, +} + +impl<T, U> A<Cell<U>> for Cell<T> where T: A<U> {} -- 2.45.2