aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc44
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc59
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h72
-rw-r--r--gcc/rust/util/rust-stacked-contexts.h9
4 files changed, 113 insertions, 71 deletions
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index a452d44..5ee3fa2 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -133,11 +133,11 @@ Late::visit (AST::ForLoopExpr &expr)
{
visit_outer_attrs (expr);
- ctx.bindings.new_binding (BindingSource::For);
+ ctx.bindings.enter (BindingSource::For);
visit (expr.get_pattern ());
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
visit (expr.get_iterator_expr ());
visit (expr.get_loop_label ());
@@ -149,12 +149,12 @@ Late::visit (AST::IfLetExpr &expr)
{
visit_outer_attrs (expr);
- ctx.bindings.new_binding (BindingSource::Let);
+ ctx.bindings.enter (BindingSource::Let);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
visit (expr.get_value_expr ());
visit (expr.get_if_block ());
@@ -165,12 +165,12 @@ Late::visit (AST::MatchArm &arm)
{
visit_outer_attrs (arm);
- ctx.bindings.new_binding (BindingSource::Match);
+ ctx.bindings.enter (BindingSource::Match);
for (auto &pattern : arm.get_patterns ())
visit (pattern);
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
if (arm.has_match_arm_guard ())
visit (arm.get_guard_expr ());
@@ -187,11 +187,11 @@ Late::visit (AST::LetStmt &let)
if (let.has_init_expr ())
visit (let.get_init_expr ());
- ctx.bindings.new_binding (BindingSource::Let);
+ ctx.bindings.enter (BindingSource::Let);
visit (let.get_pattern ());
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
if (let.has_else_expr ())
visit (let.get_init_expr ());
@@ -220,9 +220,9 @@ Late::visit (AST::IdentifierPattern &identifier)
// but values does not allow shadowing... since functions cannot shadow
// do we insert functions in labels as well?
- if (ctx.bindings.and_binded (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ()))
{
- if (ctx.bindings.get_source () == BindingSource::Param)
+ if (ctx.bindings.peek ().get_source () == BindingSource::Param)
rust_error_at (
identifier.get_locus (), ErrorCode::E0415,
"identifier %qs is bound more than once in the same parameter list",
@@ -235,9 +235,9 @@ Late::visit (AST::IdentifierPattern &identifier)
return;
}
- ctx.bindings.insert_ident (identifier.get_ident ());
+ ctx.bindings.peek ().insert_ident (identifier.get_ident ());
- if (ctx.bindings.or_binded (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ()))
{
// FIXME: map usage instead
std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
@@ -255,14 +255,14 @@ Late::visit (AST::IdentifierPattern &identifier)
void
Late::visit (AST::AltPattern &pattern)
{
- ctx.bindings.push (Binding::Kind::Or);
+ ctx.bindings.peek ().push (Binding::Kind::Or);
for (auto &alt : pattern.get_alts ())
{
- ctx.bindings.push (Binding::Kind::Product);
+ ctx.bindings.peek ().push (Binding::Kind::Product);
visit (alt);
- ctx.bindings.merge ();
+ ctx.bindings.peek ().merge ();
}
- ctx.bindings.merge ();
+ ctx.bindings.peek ().merge ();
}
void
@@ -276,12 +276,12 @@ Late::visit (AST::Function &function)
visit (generic);
// We only care about params
- ctx.bindings.new_binding (BindingSource::Param);
+ ctx.bindings.enter (BindingSource::Param);
for (auto &param : function.get_function_params ())
visit (param);
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
// Back to regular visit
@@ -652,12 +652,12 @@ Late::visit (AST::ClosureExprInner &closure)
visit_outer_attrs (closure);
- ctx.bindings.new_binding (BindingSource::Param);
+ ctx.bindings.enter (BindingSource::Param);
for (auto &param : closure.get_params ())
visit (param);
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
visit (closure.get_definition_expr ());
}
@@ -669,12 +669,12 @@ Late::visit (AST::ClosureExprInnerTyped &closure)
visit_outer_attrs (closure);
- ctx.bindings.new_binding (BindingSource::Param);
+ ctx.bindings.enter (BindingSource::Param);
for (auto &param : closure.get_params ())
visit (param);
- ctx.bindings.clear ();
+ ctx.bindings.exit ();
visit (closure.get_return_type ());
visit (closure.get_definition_block ());
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index 35befc1..7f47e85 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -23,6 +23,65 @@
namespace Rust {
namespace Resolver2_0 {
+BindingLayer::BindingLayer (BindingSource source) : source (source)
+{
+ push (Binding::Kind::Product);
+}
+
+bool
+BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
+{
+ for (auto &bind : bindings)
+ {
+ if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+BindingLayer::push (Binding::Kind kind)
+{
+ bindings.push_back (Binding (kind));
+}
+
+bool
+BindingLayer::is_and_bound (Identifier ident)
+{
+ return bind_test (ident, Binding::Kind::Product);
+}
+
+bool
+BindingLayer::is_or_bound (Identifier ident)
+{
+ return bind_test (ident, Binding::Kind::Or);
+}
+
+void
+BindingLayer::insert_ident (Identifier ident)
+{
+ bindings.back ().set.insert (ident);
+}
+
+void
+BindingLayer::merge ()
+{
+ auto last_binding = bindings.back ();
+ bindings.pop_back ();
+ for (auto &value : last_binding.set)
+ {
+ bindings.back ().set.insert (value);
+ }
+}
+
+BindingSource
+BindingLayer::get_source () const
+{
+ return source;
+}
+
NameResolutionContext::NameResolutionContext ()
: mappings (Analysis::Mappings::get ())
{}
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 10318b1..aab04cc 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -23,6 +23,7 @@
#include "rust-forever-stack.h"
#include "rust-hir-map.h"
#include "rust-rib.h"
+#include "rust-stacked-contexts.h"
namespace Rust {
namespace Resolver2_0 {
@@ -169,72 +170,47 @@ struct Binding
Binding (Binding::Kind kind) : kind (kind) {}
};
+/**
+ * Used to identify the source of a binding, and emit the correct error message.
+ */
enum class BindingSource
{
Match,
Let,
For,
+ /* Closure param or function param */
Param
};
-class BindingContext
+class BindingLayer
{
- // FIXME: Use std::vector<std::vector<Binding>> to handle nested patterns
- std::vector<Binding> bindings;
-
BindingSource source;
+ std::vector<Binding> bindings;
- bool bind_test (Identifier ident, Binding::Kind kind)
- {
- for (auto &bind : bindings)
- {
- if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
- {
- return true;
- }
- }
- return false;
- }
+ bool bind_test (Identifier ident, Binding::Kind kind);
public:
- bool and_binded (Identifier ident)
- {
- return bind_test (ident, Binding::Kind::Product);
- }
+ void push (Binding::Kind kind);
- bool or_binded (Identifier ident)
- {
- return bind_test (ident, Binding::Kind::Or);
- }
+ BindingLayer (BindingSource source);
- void insert_ident (Identifier ident) { bindings.back ().set.insert (ident); }
+ /**
+ * Identifies if the identifier has been used in a product binding context.
+ * eg. `let (a, a) = test();`
+ */
+ bool is_and_bound (Identifier ident);
- void push (Binding::Kind kind) { bindings.push_back (Binding (kind)); }
+ /**
+ * Identifies if the identifier has been used in a or context.
+ * eg. `let (a, 1) | (a, 2) = test()`
+ */
+ bool is_or_bound (Identifier ident);
- void new_binding (BindingSource source)
- {
- rust_assert (bindings.size () == 0);
- this->source = source;
- push (Binding::Kind::Product);
- }
+ void insert_ident (Identifier ident);
- void clear ()
- {
- rust_assert (bindings.size () == 1);
- bindings.clear ();
- }
-
- void merge ()
- {
- auto last_binding = bindings.back ();
- bindings.pop_back ();
- for (auto &value : last_binding.set)
- {
- bindings.back ().set.insert (value);
- }
- }
+ void merge ();
- BindingSource get_source () const { return source; }
+ BindingSource get_source () const;
};
// Now our resolver, which keeps track of all the `ForeverStack`s we could want
@@ -293,7 +269,7 @@ public:
ForeverStack<Namespace::Labels> labels;
Analysis::Mappings &mappings;
- BindingContext bindings;
+ StackedContexts<BindingLayer> bindings;
// TODO: Rename
// TODO: Use newtype pattern for Usage and Definition
diff --git a/gcc/rust/util/rust-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h
index d537d6e..cabc65d 100644
--- a/gcc/rust/util/rust-stacked-contexts.h
+++ b/gcc/rust/util/rust-stacked-contexts.h
@@ -71,7 +71,14 @@ public:
return last;
}
- const T &peek ()
+ const T &peek () const
+ {
+ rust_assert (!stack.empty ());
+
+ return stack.back ();
+ }
+
+ T &peek ()
{
rust_assert (!stack.empty ());