Skip to content

Commit

Permalink
gccrs: fix unconstrained generics check to handle recursive generics
Browse files Browse the repository at this point in the history
Generics can be constrained within other generic types so this check needs
to be recursive.

Fixes #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 <[email protected]>
  • Loading branch information
philberty committed Feb 13, 2025
1 parent c005754 commit 5f7213e
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 18 deletions.
42 changes: 24 additions & 18 deletions gcc/rust/typecheck/rust-hir-type-check-base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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> &params_to_constrain,
Expand All @@ -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)
Expand Down
42 changes: 42 additions & 0 deletions gcc/rust/typecheck/rust-tyty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/typecheck/rust-tyty.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class BaseType : public TypeBoundsMappings

bool has_substitutions_defined () const;
bool needs_generic_substitutions () const;
const SubstitutionArgumentMappings &get_subst_argument_mappings () const;

std::string mangle_string () const
{
Expand Down
15 changes: 15 additions & 0 deletions gcc/testsuite/rust/compile/issue-3031.rs
Original file line number Diff line number Diff line change
@@ -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> {}

0 comments on commit 5f7213e

Please sign in to comment.