From: Owen Avery <[email protected]>
gcc/rust/ChangeLog:
* resolve/rust-late-name-resolver-2.0.cc
(visit_identifier_as_pattern): Handle is_ref and is_mut.
(Late::visit): Likewise.
* resolve/rust-name-resolution-context.cc
(BindingLayer::insert_ident): Likewise.
(BindingLayer::bind_test): Handle changes to BindingLayer
fields.
(BindingLayer::merge): Likewise and emit more error messages.
* resolve/rust-name-resolution-context.h
(struct IdentifierMode): New.
(Binding::has_expected_bindings): New field.
(Binding::set): Rename field to...
(Binding::idents): ...here and convert from a set to a map.
(Binding::Binding): Initialize has_expected_bindings.
(BindingLayer::insert_ident): Adjust parameters.
gcc/testsuite/ChangeLog:
* rust/compile/nr2/exclude: Remove torture/alt_patterns1.rs.
Signed-off-by: Owen Avery <[email protected]>
---
.../resolve/rust-late-name-resolver-2.0.cc | 11 ++--
.../resolve/rust-name-resolution-context.cc | 59 +++++++++++++++++--
.../resolve/rust-name-resolution-context.h | 26 +++++++-
gcc/testsuite/rust/compile/nr2/exclude | 1 -
4 files changed, 83 insertions(+), 14 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 8ce69436f20..a41aa593f47 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -211,7 +211,7 @@ Late::visit (AST::LetStmt &let)
static void
visit_identifier_as_pattern (NameResolutionContext &ctx,
const Identifier &ident, location_t locus,
- NodeId node_id)
+ NodeId node_id, bool is_ref, bool is_mut)
{
// do we insert in labels or in values
// but values does not allow shadowing... since functions cannot shadow
@@ -232,7 +232,7 @@ visit_identifier_as_pattern (NameResolutionContext &ctx,
return;
}
- ctx.bindings.peek ().insert_ident (ident);
+ ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref,
is_mut);
if (ctx.bindings.peek ().is_or_bound (ident))
{
@@ -255,7 +255,9 @@ Late::visit (AST::IdentifierPattern &identifier)
visit_identifier_as_pattern (ctx, identifier.get_ident (),
identifier.get_locus (),
- identifier.get_node_id ());
+ identifier.get_node_id (),
+ identifier.get_is_ref (),
+ identifier.get_is_mut ());
}
void
@@ -286,7 +288,8 @@ void
Late::visit (AST::StructPatternFieldIdent &field)
{
visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus
(),
- field.get_node_id ());
+ field.get_node_id (), field.is_ref (),
+ field.is_mut ());
}
void
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc
b/gcc/rust/resolve/rust-name-resolution-context.cc
index 34615ed97c3..1b84f1d7cfa 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
{
for (auto &bind : bindings)
{
- if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
+ if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
+ && bind.kind == kind)
{
return true;
}
@@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident)
}
void
-BindingLayer::insert_ident (Identifier ident)
+BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut)
{
- bindings.back ().set.insert (ident);
+ bindings.back ().idents.emplace (
+ std::move (ident), std::make_pair (locus, IdentifierMode (is_ref,
is_mut)));
}
void
BindingLayer::merge ()
{
- auto last_binding = bindings.back ();
+ auto last_binding = std::move (bindings.back ());
bindings.pop_back ();
- for (auto &value : last_binding.set)
+
+ if (bindings.back ().has_expected_bindings)
{
- bindings.back ().set.insert (value);
+ for (auto &value : bindings.back ().idents)
+ {
+ auto ident = value.first;
+ if (last_binding.idents.find (ident) == last_binding.idents.end ())
+ {
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
}
+
+ for (auto &value : last_binding.idents)
+ {
+ auto res = bindings.back ().idents.emplace (value);
+ if (res.second)
+ {
+ if (bindings.back ().has_expected_bindings)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ else
+ {
+ auto this_mode = value.second.second;
+ auto other_mode = res.first->second.second;
+ if (this_mode != other_mode)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0409,
+ "variable %qs is bound inconsistently across "
+ "pattern alternatives",
+ ident.c_str ());
+ }
+ }
+ }
+
+ if (bindings.back ().kind == Binding::Kind::Or)
+ bindings.back ().has_expected_bindings = true;
}
BindingSource
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h
b/gcc/rust/resolve/rust-name-resolution-context.h
index bb8519a0493..0180919db7e 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -158,6 +158,22 @@ public:
NodeId id;
};
+struct IdentifierMode
+{
+ bool is_ref;
+ bool is_mut;
+
+ IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut)
+ {}
+
+ bool operator== (const IdentifierMode &other)
+ {
+ return other.is_ref == is_ref && other.is_mut == is_mut;
+ }
+
+ bool operator!= (const IdentifierMode &other) { return !(*this == other); }
+};
+
struct Binding
{
enum class Kind
@@ -166,9 +182,12 @@ struct Binding
Or,
} kind;
- std::unordered_set<Identifier> set;
+ // used to check the correctness of or-bindings
+ bool has_expected_bindings;
+
+ std::unordered_map<std::string, std::pair<location_t, IdentifierMode>>
idents;
- Binding (Binding::Kind kind) : kind (kind) {}
+ Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
};
/**
@@ -208,7 +227,8 @@ public:
*/
bool is_or_bound (Identifier ident);
- void insert_ident (Identifier ident);
+ void insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut);
void merge ();
diff --git a/gcc/testsuite/rust/compile/nr2/exclude
b/gcc/testsuite/rust/compile/nr2/exclude
index dfaba888dc5..43d7a0dc911 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -1,3 +1,2 @@
issue-3315-2.rs
-torture/alt_patterns1.rs
# please don't delete the trailing newline
--
2.49.0