]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: nr2.0: Add more checks for alternate patterns
authorOwen Avery <powerboat9.gamer@gmail.com>
Sat, 24 May 2025 15:51:29 +0000 (11:51 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:52 +0000 (16:36 +0200)
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 <powerboat9.gamer@gmail.com>
gcc/rust/resolve/rust-late-name-resolver-2.0.cc
gcc/rust/resolve/rust-name-resolution-context.cc
gcc/rust/resolve/rust-name-resolution-context.h
gcc/testsuite/rust/compile/nr2/exclude

index 8ce69436f20bab827e89696ea271c266d7cdb3bb..a41aa593f47f3e4f874966bd645d53a14694d0c4 100644 (file)
@@ -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
index 34615ed97c323db33fb9a1ea2839a88b418db6a9..1b84f1d7cfa35b3b5da7883bd9e0ec8d7bf00a51 100644 (file)
@@ -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
index bb8519a049334de51c9e159fa6de779110383a5b..0180919db7e72f8592be8ccc8cc46263ed1c2b97 100644 (file)
@@ -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 ();
 
index dfaba888dc51a3008d1defa01bca01808aef485c..43d7a0dc9116fbe8b4a5648782a0a469b135d416 100644 (file)
@@ -1,3 +1,2 @@
 issue-3315-2.rs
-torture/alt_patterns1.rs
 # please don't delete the trailing newline