]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: fix name resolution for generics where type param is declared later
authorPhilip Herron <herron.philip@googlemail.com>
Thu, 13 Feb 2025 17:01:31 +0000 (17:01 +0000)
committerArthur Cohen <arthur.cohen@embecosm.com>
Mon, 24 Mar 2025 12:07:05 +0000 (13:07 +0100)
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.philip@googlemail.com>
gcc/rust/resolve/rust-ast-resolve-item.cc
gcc/rust/resolve/rust-ast-resolve-stmt.h
gcc/rust/resolve/rust-ast-resolve-type.h

index cecc8ad6857b529e5a29ca11e1e3372fa3fbfeeb..366716a22e2e627325800cebfe35bcad8d9a4306 100644 (file)
@@ -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 ());
index eb82f566a228a34034700c3e9472c8fb49fbb6cb..5b425e841061ec67d17fa8bb393a7eda2aa7f482 100644 (file)
@@ -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 ());
index 662f2f5a6683aee817f5a70644e82706d86df006..d3b60b6ce78d97660a4df814d678eeaee246720c 100644 (file)
@@ -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;
 };