https://gcc.gnu.org/g:41302945e2a3f912535b7dce163b1e1acc5d2ba6

commit r15-8799-g41302945e2a3f912535b7dce163b1e1acc5d2ba6
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Thu Feb 13 17:01:31 2025 +0000

    gccrs: fix name resolution for generics where type param is declared later
    
    Rust allows you to use generics within type bounds when they are declared
    later on. This changes the name resolution to walk the genric params
    in two passes to ensure the type parameters are setup before drilling down
    into the type parameters
    
    This issue has exposed another type checking issue which needs fixed in
    a subseqent patch.
    
    Addresses Rust-GCC#3022
    
    gcc/rust/ChangeLog:
    
            * resolve/rust-ast-resolve-item.cc (ResolveTraitItems::visit): use 
new api
            (ResolveItem::visit): likewise
            (ResolveExternItem::visit): likewise
            * resolve/rust-ast-resolve-stmt.h: likewise
            * resolve/rust-ast-resolve-type.h (class ResolveGenericParam): 
remove
            (class ResolveGenericParams): added new api
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/rust/resolve/rust-ast-resolve-item.cc | 48 ++++++++---------
 gcc/rust/resolve/rust-ast-resolve-stmt.h  | 26 ++++-----
 gcc/rust/resolve/rust-ast-resolve-type.h  | 87 ++++++++++++++++++-------------
 3 files changed, 86 insertions(+), 75 deletions(-)

diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc 
b/gcc/rust/resolve/rust-ast-resolve-item.cc
index cecc8ad6857b..366716a22e2e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -64,8 +64,8 @@ ResolveTraitItems::visit (AST::Function &function)
   resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
 
   if (function.has_generics ())
-    for (auto &generic : function.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (function.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (function.has_return_type ())
     ResolveType::go (function.get_return_type ());
@@ -188,8 +188,8 @@ ResolveItem::visit (AST::TypeAlias &alias)
   resolver->get_type_scope ().push (scope_node_id);
 
   if (alias.has_generics ())
-    for (auto &generic : alias.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (alias.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (alias.has_where_clause ())
     ResolveWhereClause::Resolve (alias.get_where_clause ());
@@ -250,8 +250,8 @@ ResolveItem::visit (AST::TupleStruct &struct_decl)
   resolver->get_type_scope ().push (scope_node_id);
 
   if (struct_decl.has_generics ())
-    for (auto &generic : struct_decl.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (struct_decl.has_where_clause ())
     ResolveWhereClause::Resolve (struct_decl.get_where_clause ());
@@ -284,8 +284,8 @@ ResolveItem::visit (AST::Enum &enum_decl)
   resolver->get_type_scope ().push (scope_node_id);
 
   if (enum_decl.has_generics ())
-    for (auto &generic : enum_decl.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, cpath);
+    ResolveGenericParams::go (enum_decl.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (enum_decl.has_where_clause ())
     ResolveWhereClause::Resolve (enum_decl.get_where_clause ());
@@ -374,8 +374,8 @@ ResolveItem::visit (AST::StructStruct &struct_decl)
   resolver->get_type_scope ().push (scope_node_id);
 
   if (struct_decl.has_generics ())
-    for (auto &generic : struct_decl.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (struct_decl.has_where_clause ())
     ResolveWhereClause::Resolve (struct_decl.get_where_clause ());
@@ -409,8 +409,8 @@ ResolveItem::visit (AST::Union &union_decl)
   resolver->get_type_scope ().push (scope_node_id);
 
   if (union_decl.has_generics ())
-    for (auto &generic : union_decl.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (union_decl.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (union_decl.has_where_clause ())
     ResolveWhereClause::Resolve (union_decl.get_where_clause ());
@@ -476,8 +476,8 @@ ResolveItem::visit (AST::Function &function)
   resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
 
   if (function.has_generics ())
-    for (auto &generic : function.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (function.get_generic_params (), prefix,
+                             canonical_prefix);
 
   // resolve any where clause items
   if (function.has_where_clause ())
@@ -567,8 +567,8 @@ ResolveItem::visit (AST::InherentImpl &impl_block)
   resolve_visibility (impl_block.get_visibility ());
 
   if (impl_block.has_generics ())
-    for (auto &generic : impl_block.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (impl_block.get_generic_params (), prefix,
+                             canonical_prefix);
 
   // resolve any where clause items
   if (impl_block.has_where_clause ())
@@ -651,8 +651,8 @@ ResolveItem::visit (AST::TraitImpl &impl_block)
   resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
 
   if (impl_block.has_generics ())
-    for (auto &generic : impl_block.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (impl_block.get_generic_params (), prefix,
+                             canonical_prefix);
 
   // resolve any where clause items
   if (impl_block.has_where_clause ())
@@ -776,10 +776,10 @@ ResolveItem::visit (AST::Trait &trait)
   resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
   resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
 
-  ResolveGenericParam::go (trait.get_implicit_self (), prefix,
-                          canonical_prefix);
-  for (auto &generic : trait.get_generic_params ())
-    ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+  ResolveGenericParams::go_single (trait.get_implicit_self (), prefix,
+                                  canonical_prefix);
+  ResolveGenericParams::go (trait.get_generic_params (), prefix,
+                           canonical_prefix);
 
   // Self is an implicit TypeParam so lets mark it as such
   resolver->get_type_scope ().append_reference_for_def (
@@ -1044,8 +1044,8 @@ ResolveExternItem::visit (AST::Function &function)
 
   // resolve the generics
   if (function.has_generics ())
-    for (auto &generic : function.get_generic_params ())
-      ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+    ResolveGenericParams::go (function.get_generic_params (), prefix,
+                             canonical_prefix);
 
   if (function.has_return_type ())
     ResolveType::go (function.get_return_type ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h 
b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index eb82f566a228..5b425e841061 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -104,10 +104,8 @@ public:
     resolver->get_type_scope ().push (scope_node_id);
 
     if (struct_decl.has_generics ())
-      {
-       for (auto &generic : struct_decl.get_generic_params ())
-         ResolveGenericParam::go (*generic, prefix, canonical_prefix);
-      }
+      ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
+                               canonical_prefix);
 
     for (AST::TupleField &field : struct_decl.get_fields ())
       ResolveType::go (field.get_field_type ());
@@ -137,10 +135,8 @@ public:
     resolver->get_type_scope ().push (scope_node_id);
 
     if (enum_decl.has_generics ())
-      {
-       for (auto &generic : enum_decl.get_generic_params ())
-         ResolveGenericParam::go (*generic, prefix, canonical_prefix);
-      }
+      ResolveGenericParams::go (enum_decl.get_generic_params (), prefix,
+                               canonical_prefix);
 
     for (auto &variant : enum_decl.get_variants ())
       ResolveStmt::go (*variant, path, canonical_prefix, path);
@@ -262,10 +258,8 @@ public:
     resolver->get_type_scope ().push (scope_node_id);
 
     if (struct_decl.has_generics ())
-      {
-       for (auto &generic : struct_decl.get_generic_params ())
-         ResolveGenericParam::go (*generic, prefix, canonical_prefix);
-      }
+      ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
+                               canonical_prefix);
 
     for (AST::StructField &field : struct_decl.get_fields ())
       {
@@ -300,8 +294,8 @@ public:
     resolver->get_type_scope ().push (scope_node_id);
 
     if (union_decl.has_generics ())
-      for (auto &generic : union_decl.get_generic_params ())
-       ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+      ResolveGenericParams::go (union_decl.get_generic_params (), prefix,
+                               canonical_prefix);
 
     for (AST::StructField &field : union_decl.get_variants ())
       {
@@ -341,8 +335,8 @@ public:
     resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
 
     if (function.has_generics ())
-      for (auto &generic : function.get_generic_params ())
-       ResolveGenericParam::go (*generic, prefix, canonical_prefix);
+      ResolveGenericParams::go (function.get_generic_params (), prefix,
+                               canonical_prefix);
 
     if (function.has_return_type ())
       ResolveType::go (function.get_return_type ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h 
b/gcc/rust/resolve/rust-ast-resolve-type.h
index 662f2f5a6683..d3b60b6ce78d 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -142,66 +142,83 @@ private:
   ResolveTypeBound () : ResolverBase () {}
 };
 
-class ResolveGenericParam : public ResolverBase
+class ResolveGenericParams : public ResolverBase
 {
   using Rust::Resolver::ResolverBase::visit;
 
 public:
-  static NodeId go (AST::GenericParam &param, const CanonicalPath &prefix,
-                   const CanonicalPath &canonical_prefix)
+  static void go (std::vector<std::unique_ptr<AST::GenericParam>> &params,
+                 const CanonicalPath &prefix,
+                 const CanonicalPath &canonical_prefix)
   {
-    ResolveGenericParam resolver (prefix, canonical_prefix);
+    ResolveGenericParams resolver (prefix, canonical_prefix);
+
+    // this needs to be done in two phases as they can be used and defined 
later
+    // in bounds
+    for (auto &param : params)
+      param->accept_vis (resolver);
+
+    resolver.first_pass = false;
+
+    for (auto &param : params)
+      param->accept_vis (resolver);
+  }
+
+  static void go_single (AST::GenericParam &param, const CanonicalPath &prefix,
+                        const CanonicalPath &canonical_prefix)
+  {
+    ResolveGenericParams resolver (prefix, canonical_prefix);
+
+    param.accept_vis (resolver);
+    resolver.first_pass = false;
     param.accept_vis (resolver);
-    return resolver.resolved_node;
   }
 
   void visit (AST::ConstGenericParam &param) override
   {
-    ResolveType::go (param.get_type ());
-
-    if (param.has_default_value ())
+    if (first_pass)
+      ResolveType::go (param.get_type ());
+    else if (param.has_default_value ())
       ResolveExpr::go (param.get_default_value ().get_expression (), prefix,
                       canonical_prefix);
-
-    ok = true;
   }
 
   void visit (AST::TypeParam &param) override
   {
-    // if it has a type lets resolve it
-    if (param.has_type ())
-      ResolveType::go (param.get_type ());
-
-    if (param.has_type_param_bounds ())
+    if (first_pass)
+      {
+       // if it has a type lets resolve it
+       if (param.has_type ())
+         ResolveType::go (param.get_type ());
+
+       auto seg = CanonicalPath::new_seg (
+         param.get_node_id (), param.get_type_representation ().as_string ());
+       resolver->get_type_scope ().insert (
+         seg, param.get_node_id (), param.get_locus (), false,
+         Rib::ItemType::Type,
+         [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
+           rust_error_at (param.get_locus (),
+                          "generic param redefined multiple times");
+           rust_error_at (locus, "was defined here");
+         });
+
+       mappings.insert_canonical_path (param.get_node_id (), seg);
+      }
+    else if (param.has_type_param_bounds ())
       {
        for (auto &bound : param.get_type_param_bounds ())
-         {
-           ResolveTypeBound::go (*bound);
-         }
+         ResolveTypeBound::go (*bound);
       }
-
-    auto seg
-      = CanonicalPath::new_seg (param.get_node_id (),
-                               param.get_type_representation ().as_string ());
-    resolver->get_type_scope ().insert (
-      seg, param.get_node_id (), param.get_locus (), false, 
Rib::ItemType::Type,
-      [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
-       rust_error_at (param.get_locus (),
-                      "generic param redefined multiple times");
-       rust_error_at (locus, "was defined here");
-      });
-
-    mappings.insert_canonical_path (param.get_node_id (), seg);
   }
 
 private:
-  ResolveGenericParam (const CanonicalPath &prefix,
-                      const CanonicalPath &canonical_prefix)
-    : ResolverBase (), ok (false), prefix (prefix),
+  ResolveGenericParams (const CanonicalPath &prefix,
+                       const CanonicalPath &canonical_prefix)
+    : ResolverBase (), first_pass (true), prefix (prefix),
       canonical_prefix (canonical_prefix)
   {}
 
-  bool ok;
+  bool first_pass;
   const CanonicalPath &prefix;
   const CanonicalPath &canonical_prefix;
 };

Reply via email to