From: Philip Herron Date: Thu, 13 Feb 2025 14:09:17 +0000 (+0000) Subject: gccrs: fix unconstrained generics check to handle recursive generics X-Git-Tag: basepoints/gcc-16~755 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=93f32b3d49c2102980e56457d2a5276db2614345;p=thirdparty%2Fgcc.git gccrs: fix unconstrained generics check to handle recursive generics 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 --- 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 &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 ¶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 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 (x); + const auto &ref = static_cast (p); + return ref.get_substitution_arguments (); + } + break; + + case FNDEF: { + const auto &fn = *static_cast (x); + const auto &ref = static_cast (fn); + return ref.get_substitution_arguments (); + } + break; + + case ADT: { + const auto &adt = *static_cast (x); + const auto &ref = static_cast (adt); + return ref.get_substitution_arguments (); + } + break; + + case CLOSURE: { + const auto &closure = *static_cast (x); + const auto &ref = static_cast (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 {} + +struct Cell { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + x: X, +} + +impl A> for Cell where T: A {}