public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] resolve: Handle multiple bindings to the same identifier
@ 2023-03-20 7:22 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-03-20 7:22 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:bed6308e5e5201f409b041ca5e712d1ed8839195
commit bed6308e5e5201f409b041ca5e712d1ed8839195
Author: Mahmoud Mohamed <mahadelr19@gmail.com>
Date: Mon Mar 13 17:18:11 2023 +0300
resolve: Handle multiple bindings to the same identifier
https://github.com/rust-lang/rust/blob/master/compiler/rustc_resolve/src/late.rs#L3168
This commit follows rustc's implementation of handling multiple bindings
to the same identifier in parameters.
gcc/rust/ChangeLog:
* resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit) :declare and
pass bindings to PatternDeclaration::go.
(ResolveExpr::resolve_closure_param): Likewise.
* resolve/rust-ast-resolve-expr.h: Likewise.
* resolve/rust-ast-resolve-item.cc (ResolveTraitItems::visit): Likewise.
(ResolveItem::visit): Likewise.
* resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::go): Likewise.
(PatternDeclaration::visit): check for previous identifier bindings
before inserting the new one.
* resolve/rust-ast-resolve-pattern.h (enum PatternBoundCtx): New enum.
* resolve/rust-ast-resolve-stmt.h: pass bindings to PatterDeclaration::go.
gcc/testsuite/ChangeLog:
* rust/compile/multiple_bindings1.rs: New test.
Signed-off-by: Mahmoud Mohamed <mahadelr19@gmail.com>
Diff:
---
gcc/rust/resolve/rust-ast-resolve-expr.cc | 30 ++++++++--
gcc/rust/resolve/rust-ast-resolve-expr.h | 4 +-
gcc/rust/resolve/rust-ast-resolve-item.cc | 28 ++++++---
gcc/rust/resolve/rust-ast-resolve-pattern.cc | 74 +++++++++++++++++++++++-
gcc/rust/resolve/rust-ast-resolve-pattern.h | 60 +++++++++----------
gcc/rust/resolve/rust-ast-resolve-stmt.h | 5 +-
gcc/testsuite/rust/compile/multiple_bindings1.rs | 29 ++++++++++
7 files changed, 183 insertions(+), 47 deletions(-)
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index 4dfc0833d91..ff9f7ef0cd1 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -207,9 +207,14 @@ ResolveExpr::visit (AST::IfLetExpr &expr)
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+ // FIXME: this declaration should be removed after refactoring
+ // parse_match_arm_patterns output into an AltPattern
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Or, std::set<Identifier> ())};
+
for (auto &pattern : expr.get_patterns ())
{
- PatternDeclaration::go (pattern.get (), Rib::ItemType::Var);
+ PatternDeclaration::go (pattern.get (), Rib::ItemType::Var, bindings);
}
ResolveExpr::go (expr.get_if_block ().get (), prefix, canonical_prefix);
@@ -517,10 +522,15 @@ ResolveExpr::visit (AST::MatchExpr &expr)
ResolveExpr::go (arm.get_guard_expr ().get (), prefix,
canonical_prefix);
+ // FIXME: this declaration should be removed after refactoring
+ // parse_match_arms_patterns output into a single AltPattern
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Or, std::set<Identifier> ())};
+
// insert any possible new patterns
for (auto &pattern : arm.get_patterns ())
{
- PatternDeclaration::go (pattern.get (), Rib::ItemType::Var);
+ PatternDeclaration::go (pattern.get (), Rib::ItemType::Var, bindings);
}
// resolve the body
@@ -576,9 +586,12 @@ ResolveExpr::visit (AST::ClosureExprInner &expr)
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
for (auto &p : expr.get_params ())
{
- resolve_closure_param (p);
+ resolve_closure_param (p, bindings);
}
resolver->push_closure_context (expr.get_node_id ());
@@ -604,9 +617,12 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
for (auto &p : expr.get_params ())
{
- resolve_closure_param (p);
+ resolve_closure_param (p, bindings);
}
ResolveType::go (expr.get_return_type ().get ());
@@ -624,9 +640,11 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
}
void
-ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m)
+ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m,
+ std::vector<PatternBinding> &bindings)
{
- PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param);
+ PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
+ bindings);
if (param.has_type_given ())
ResolveType::go (param.get_type ().get ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 9e3e7750119..07b029fabb3 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -20,6 +20,7 @@
#define RUST_AST_RESOLVE_EXPR_H
#include "rust-ast-resolve-base.h"
+#include "rust-ast-resolve-pattern.h"
#include "rust-ast-full.h"
namespace Rust {
@@ -79,7 +80,8 @@ public:
void visit (AST::ClosureExprInnerTyped &expr) override;
protected:
- void resolve_closure_param (AST::ClosureParam ¶m);
+ void resolve_closure_param (AST::ClosureParam ¶m,
+ std::vector<PatternBinding> &bindings);
private:
ResolveExpr (const CanonicalPath &prefix,
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 0be9a02a6f6..958ae49c810 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -77,13 +77,16 @@ ResolveTraitItems::visit (AST::TraitItemFunc &func)
if (function.has_return_type ())
ResolveType::go (function.get_return_type ().get ());
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto ¶m : function.get_function_params ())
{
ResolveType::go (param.get_type ().get ());
- PatternDeclaration::go (param.get_pattern ().get (),
- Rib::ItemType::Param);
+ PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
+ bindings);
}
if (function.has_where_clause ())
@@ -141,13 +144,16 @@ ResolveTraitItems::visit (AST::TraitItemMethod &func)
ResolveType::go (&self_type_path);
PatternDeclaration::go (&self_pattern, Rib::ItemType::Param);
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto ¶m : function.get_function_params ())
{
ResolveType::go (param.get_type ().get ());
- PatternDeclaration::go (param.get_pattern ().get (),
- Rib::ItemType::Param);
+ PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
+ bindings);
}
if (function.has_where_clause ())
@@ -496,13 +502,16 @@ ResolveItem::visit (AST::Function &function)
if (function.has_return_type ())
ResolveType::go (function.get_return_type ().get ());
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto ¶m : function.get_function_params ())
{
ResolveType::go (param.get_type ().get ());
- PatternDeclaration::go (param.get_pattern ().get (),
- Rib::ItemType::Param);
+ PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
+ bindings);
}
// resolve the function body
@@ -633,13 +642,16 @@ ResolveItem::visit (AST::Method &method)
ResolveType::go (&self_type_path);
PatternDeclaration::go (&self_pattern, Rib::ItemType::Param);
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto ¶m : method.get_function_params ())
{
ResolveType::go (param.get_type ().get ());
- PatternDeclaration::go (param.get_pattern ().get (),
- Rib::ItemType::Param);
+ PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param,
+ bindings);
}
// resolve any where clause items
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index 10f4fd8a61b..866745e098e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -23,6 +23,78 @@
namespace Rust {
namespace Resolver {
+void
+PatternDeclaration::go (AST::Pattern *pattern, Rib::ItemType type)
+{
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+ PatternDeclaration resolver (bindings, type);
+ pattern->accept_vis (resolver);
+};
+
+void
+PatternDeclaration::go (AST::Pattern *pattern, Rib::ItemType type,
+ std::vector<PatternBinding> &bindings)
+{
+ PatternDeclaration resolver (bindings, type);
+ pattern->accept_vis (resolver);
+}
+
+void
+PatternDeclaration::visit (AST::IdentifierPattern &pattern)
+{
+ bool has_binding_ctx = bindings.size () > 0;
+ rust_assert (has_binding_ctx);
+
+ auto &binding_idents = bindings.back ().idents;
+
+ bool current_ctx_is_product
+ = bindings.back ().ctx == PatternBoundCtx::Product;
+ bool identifier_is_product_bound
+ = current_ctx_is_product
+ && binding_idents.find (pattern.get_ident ()) != binding_idents.end ();
+
+ if (identifier_is_product_bound)
+ {
+ if (type == Rib::ItemType::Param)
+ {
+ rust_error_at (pattern.get_locus (), ErrorCode ("E0415"),
+ "identifier '%s' is bound more than once in the "
+ "same parameter list",
+ pattern.get_ident ().c_str ());
+ }
+ else
+ {
+ rust_error_at (
+ pattern.get_locus (), ErrorCode ("E0416"),
+ "identifier '%s' is bound more than once in the same pattern",
+ pattern.get_ident ().c_str ());
+ }
+
+ return;
+ }
+
+ // if we have a duplicate id this then allows for shadowing correctly
+ // as new refs to this decl will match back here so it is ok to overwrite
+ resolver->get_name_scope ().insert (
+ CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()),
+ pattern.get_node_id (), pattern.get_locus (), type);
+
+ binding_idents.insert (pattern.get_ident ());
+}
+
+void
+PatternDeclaration::visit (AST::GroupedPattern &pattern)
+{
+ pattern.get_pattern_in_parens ()->accept_vis (*this);
+}
+
+void
+PatternDeclaration::visit (AST::ReferencePattern &pattern)
+{
+ pattern.get_referenced_pattern ()->accept_vis (*this);
+}
+
void
PatternDeclaration::visit (AST::PathInExpression &pattern)
{
@@ -49,7 +121,7 @@ PatternDeclaration::visit (AST::TupleStructPattern &pattern)
for (auto &inner_pattern : items_no_range.get_patterns ())
{
- PatternDeclaration::go (inner_pattern.get (), type);
+ inner_pattern.get ()->accept_vis (*this);
}
}
break;
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index 12d2b5986e8..0ff500a4d99 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -25,6 +25,26 @@
namespace Rust {
namespace Resolver {
+// Specifies whether the set of already bound patterns are related by 'Or' or
+// 'Product'. Used to check for multiple bindings to the same identifier.
+enum PatternBoundCtx
+{
+ // A product pattern context (e.g. struct and tuple patterns)
+ Product,
+ // An or-pattern context (e.g. p_0 | p_1 | ...)
+ Or,
+};
+
+struct PatternBinding
+{
+ PatternBoundCtx ctx;
+ std::set<Identifier> idents;
+
+ PatternBinding (PatternBoundCtx ctx, std::set<Identifier> idents)
+ : ctx (ctx), idents (idents)
+ {}
+};
+
class ResolvePattern : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
@@ -55,45 +75,25 @@ class PatternDeclaration : public ResolverBase
using Rust::Resolver::ResolverBase::visit;
public:
- static void go (AST::Pattern *pattern, Rib::ItemType type)
- {
- PatternDeclaration resolver (type);
- pattern->accept_vis (resolver);
- };
+ static void go (AST::Pattern *pattern, Rib::ItemType type);
+ static void go (AST::Pattern *pattern, Rib::ItemType type,
+ std::vector<PatternBinding> &bindings);
- void visit (AST::IdentifierPattern &pattern) override
- {
- // if we have a duplicate id this then allows for shadowing correctly
- // as new refs to this decl will match back here so it is ok to overwrite
- resolver->get_name_scope ().insert (
- CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()),
- pattern.get_node_id (), pattern.get_locus (), type);
- }
-
- void visit (AST::GroupedPattern &pattern) override
- {
- pattern.get_pattern_in_parens ()->accept_vis (*this);
- }
-
- void visit (AST::ReferencePattern &pattern) override
- {
- pattern.get_referenced_pattern ()->accept_vis (*this);
- }
-
- // cases in a match expression
+ void visit (AST::IdentifierPattern &pattern) override;
+ void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::ReferencePattern &pattern) override;
void visit (AST::PathInExpression &pattern) override;
-
void visit (AST::StructPattern &pattern) override;
-
void visit (AST::TupleStructPattern &pattern) override;
-
void visit (AST::TuplePattern &pattern) override;
-
void visit (AST::RangePattern &pattern) override;
private:
- PatternDeclaration (Rib::ItemType type) : ResolverBase (), type (type) {}
+ PatternDeclaration (std::vector<PatternBinding> &bindings, Rib::ItemType type)
+ : ResolverBase (), bindings (bindings), type (type)
+ {}
+ std::vector<PatternBinding> &bindings;
Rib::ItemType type;
};
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index 28c547f410b..1336402d43e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -344,13 +344,16 @@ public:
if (function.has_return_type ())
ResolveType::go (function.get_return_type ().get ());
+ std::vector<PatternBinding> bindings
+ = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
+
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto ¶m : function.get_function_params ())
{
ResolveType::go (param.get_type ().get ());
PatternDeclaration::go (param.get_pattern ().get (),
- Rib::ItemType::Param);
+ Rib::ItemType::Param, bindings);
}
// resolve the function body
diff --git a/gcc/testsuite/rust/compile/multiple_bindings1.rs b/gcc/testsuite/rust/compile/multiple_bindings1.rs
new file mode 100644
index 00000000000..e73dc2ae7d9
--- /dev/null
+++ b/gcc/testsuite/rust/compile/multiple_bindings1.rs
@@ -0,0 +1,29 @@
+fn f1(i: i32, i: i32) {}
+// { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 }
+
+trait Foo {
+ fn f2(i: i32, i: i32) {}
+ // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 }
+}
+
+trait Bar {
+ fn f3(i: i32, j: i32) {}
+}
+
+struct S;
+
+impl S {
+ fn f4(i: i32, i: i32) {}
+ // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 }
+}
+
+impl Bar for S {
+ fn f3(i: i32, i: i32) {}
+ // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 }
+}
+
+fn main() {
+ let _ = |i, i| {};
+ // { dg-error "identifier .i. is bound more than once in the same parameter list .E0415." "" { target *-*-* } .-1 }
+}
+
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-03-20 7:22 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-20 7:22 [gcc/devel/rust/master] resolve: Handle multiple bindings to the same identifier Thomas Schwinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).