]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Add pattern bindings
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Sun, 6 Apr 2025 16:17:41 +0000 (18:17 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Mon, 28 Apr 2025 14:18:56 +0000 (16:18 +0200)
gcc/rust/ChangeLog:

* resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add binding
creation in visitor.
* resolve/rust-late-name-resolver-2.0.h: Add function prototypes.
* resolve/rust-name-resolution-context.h: Add binding context.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
gcc/rust/resolve/rust-late-name-resolver-2.0.cc
gcc/rust/resolve/rust-late-name-resolver-2.0.h
gcc/rust/resolve/rust-name-resolution-context.h

index 48e33c097de499cd939e6a2362642b6f728b6410..1ecf48152d84726e04ff38ca9de834e8b28cf1c7 100644 (file)
@@ -128,6 +128,54 @@ Late::new_label (Identifier name, NodeId id)
   rust_assert (ok);
 }
 
+void
+Late::visit (AST::ForLoopExpr &expr)
+{
+  visit_outer_attrs (expr);
+
+  ctx.bindings.new_binding (BindingSource::For);
+
+  visit (expr.get_pattern ());
+
+  ctx.bindings.clear ();
+
+  visit (expr.get_iterator_expr ());
+  visit (expr.get_loop_label ());
+  visit (expr.get_loop_block ());
+}
+
+void
+Late::visit (AST::IfLetExpr &expr)
+{
+  visit_outer_attrs (expr);
+
+  ctx.bindings.new_binding (BindingSource::Let);
+
+  for (auto &pattern : expr.get_patterns ())
+    visit (pattern);
+
+  ctx.bindings.clear ();
+
+  visit (expr.get_value_expr ());
+  visit (expr.get_if_block ());
+}
+
+void
+Late::visit (AST::MatchArm &arm)
+{
+  visit_outer_attrs (arm);
+
+  ctx.bindings.new_binding (BindingSource::Match);
+
+  for (auto &pattern : arm.get_patterns ())
+    visit (pattern);
+
+  ctx.bindings.clear ();
+
+  if (arm.has_match_arm_guard ())
+    visit (arm.get_guard_expr ());
+}
+
 void
 Late::visit (AST::LetStmt &let)
 {
@@ -138,8 +186,13 @@ Late::visit (AST::LetStmt &let)
   // this makes variable shadowing work properly
   if (let.has_init_expr ())
     visit (let.get_init_expr ());
+
+  ctx.bindings.new_binding (BindingSource::Let);
+
   visit (let.get_pattern ());
 
+  ctx.bindings.clear ();
+
   if (let.has_else_expr ())
     visit (let.get_init_expr ());
 
@@ -167,9 +220,80 @@ Late::visit (AST::IdentifierPattern &identifier)
   // but values does not allow shadowing... since functions cannot shadow
   // do we insert functions in labels as well?
 
-  // We do want to ignore duplicated data because some situations rely on it.
-  std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
-                                             identifier.get_node_id ());
+  if (ctx.bindings.and_binded (identifier.get_ident ()))
+    {
+      if (ctx.bindings.get_source () == BindingSource::Param)
+       rust_error_at (
+         identifier.get_locus (), ErrorCode::E0415,
+         "identifier %qs is bound more than once in the same parameter list",
+         identifier.as_string ().c_str ());
+      else
+       rust_error_at (
+         identifier.get_locus (), ErrorCode::E0416,
+         "identifier %qs is bound more than once in the same pattern",
+         identifier.as_string ().c_str ());
+      return;
+    }
+
+  ctx.bindings.insert_ident (identifier.get_ident ());
+
+  if (ctx.bindings.or_binded (identifier.get_ident ()))
+    {
+      // FIXME: map usage instead
+      std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
+                                                 identifier.get_node_id ());
+    }
+  else
+    {
+      // We do want to ignore duplicated data because some situations rely on
+      // it.
+      std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
+                                                 identifier.get_node_id ());
+    }
+}
+
+void
+Late::visit (AST::AltPattern &pattern)
+{
+  ctx.bindings.push (Binding::Kind::Or);
+  for (auto &alt : pattern.get_alts ())
+    {
+      ctx.bindings.push (Binding::Kind::Product);
+      visit (alt);
+      ctx.bindings.merge ();
+    }
+  ctx.bindings.merge ();
+}
+
+void
+Late::visit (AST::Function &function)
+{
+  auto def_fn = [this, &function] () {
+    visit_outer_attrs (function);
+    visit (function.get_visibility ());
+    visit (function.get_qualifiers ());
+    for (auto &generic : function.get_generic_params ())
+      visit (generic);
+
+    // We only care about params
+    ctx.bindings.new_binding (BindingSource::Param);
+
+    for (auto &param : function.get_function_params ())
+      visit (param);
+
+    ctx.bindings.clear ();
+
+    // Back to regular visit
+
+    if (function.has_return_type ())
+      visit (function.get_return_type ());
+    if (function.has_where_clause ())
+      visit (function.get_where_clause ());
+    if (function.has_body ())
+      visit (*function.get_definition ());
+  };
+
+  ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
 }
 
 void
@@ -525,14 +649,35 @@ void
 Late::visit (AST::ClosureExprInner &closure)
 {
   add_captures (closure, ctx);
-  DefaultResolver::visit (closure);
+
+  visit_outer_attrs (closure);
+
+  ctx.bindings.new_binding (BindingSource::Param);
+
+  for (auto &param : closure.get_params ())
+    visit (param);
+
+  ctx.bindings.clear ();
+
+  visit (closure.get_definition_expr ());
 }
 
 void
 Late::visit (AST::ClosureExprInnerTyped &closure)
 {
   add_captures (closure, ctx);
-  DefaultResolver::visit (closure);
+
+  visit_outer_attrs (closure);
+
+  ctx.bindings.new_binding (BindingSource::Param);
+
+  for (auto &param : closure.get_params ())
+    visit (param);
+
+  ctx.bindings.clear ();
+
+  visit (closure.get_return_type ());
+  visit (closure.get_definition_block ());
 }
 
 } // namespace Resolver2_0
index 2be932834d43f3964f3856635db259fb9a73b4fb..9e2bfdefaad6a9e98b035cee9e4c1e31a3a093c8 100644 (file)
@@ -43,7 +43,12 @@ public:
   // void visit (AST::Method &) override;
   void visit (AST::IdentifierPattern &) override;
   void visit (AST::StructPatternFieldIdent &) override;
+  void visit (AST::AltPattern &) override;
+  void visit (AST::Function &) override;
   void visit (AST::SelfParam &) override;
+  void visit (AST::MatchArm &) override;
+  void visit (AST::ForLoopExpr &) override;
+  void visit (AST::IfLetExpr &) override;
 
   // resolutions
   void visit (AST::IdentifierExpr &) override;
index d0736bcd1baa20c2bc8580b5316f4bf7182ca7d4..657d1512fe83b4e90ef386f78f7bcc000ab35797 100644 (file)
@@ -293,6 +293,7 @@ public:
   ForeverStack<Namespace::Labels> labels;
 
   Analysis::Mappings &mappings;
+  BindingContext bindings;
 
   // TODO: Rename
   // TODO: Use newtype pattern for Usage and Definition