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> &params_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

Reply via email to