https://gcc.gnu.org/g:93f32b3d49c2102980e56457d2a5276db2614345

commit r15-8798-g93f32b3d49c2102980e56457d2a5276db2614345
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Thu Feb 13 14:09:17 2025 +0000

    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 <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/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(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc 
b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 34f629c05193..8f2471d54d55 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 8f388120a41c..fe4b8fca1391 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 93c4a15a4607..504a14e3773b 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 000000000000..33f5bf074719
--- /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> {}

Reply via email to