From 76e776d7b281a292fcae9e72ee6a447651b93952 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Sat, 24 May 2025 11:51:29 -0400 Subject: [PATCH] nr2.0: Add more checks for alternate patterns 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 --- .../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 b66e525946e..7773c07fbc0 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)) { @@ -258,7 +258,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 @@ -289,7 +291,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 @@ class Definition 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 set; + // used to check the correctness of or-bindings + bool has_expected_bindings; + + std::unordered_map> idents; - Binding (Binding::Kind kind) : kind (kind) {} + Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {} }; /** @@ -208,7 +227,8 @@ class BindingLayer */ 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 58a20146091..2b7f0cee2ff 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,5 +1,4 @@ issue-3315-2.rs -torture/alt_patterns1.rs issue-1487.rs issue-2015.rs issue-3454.rs