https://gcc.gnu.org/g:84f5e7b12e750e48051a9cc0bd969b2e2f73117b

commit r15-8423-g84f5e7b12e750e48051a9cc0bd969b2e2f73117b
Author: Owen Avery <powerboat9.ga...@gmail.com>
Date:   Fri Oct 4 17:33:42 2024 -0400

    gccrs: Improve Rib::Definition shadowing
    
    gcc/rust/ChangeLog:
    
            * resolve/rust-finalize-imports-2.0.cc
            (GlobbingVisitor::visit): Replace calls to insert_shadowable with
            insert_globbed.
            * resolve/rust-forever-stack.h
            (ForeverStack::insert_globbed): Add.
            * resolve/rust-forever-stack.hxx
            (ForeverStack::insert_globbed): Add.
            (ForeverStack::dfs): Handle modifications to Rib::Definition
            fields.
            * resolve/rust-late-name-resolver-2.0.cc
            (Late::visit): Make IdentifierPattern-based declarations
            shadowable.
            * resolve/rust-name-resolution-context.cc
            (NameResolutionContext::insert_globbed): Add.
            * resolve/rust-name-resolution-context.h
            (NameResolutionContext::insert_globbed): Add.
            * resolve/rust-rib.cc
            (Rib::Definition::Definition): Use Rib::Definition::Mode to
            indicate shadowing mode instead of boolean, handle modifications
            to Rib::Definition fields.
            (Rib::Definition::is_ambiguous): Handle modifications to
            Rib::Definition fields.
            (Rib::Definition::to_string): Likewise.
            (Rib::Definition::Shadowable): Handle changed constructor
            signature.
            (Rib::Definition::NonShadowable): Likewise.
            (Rib::Definition::Globbed): Add.
            (Rib::insert): Handle changes to Rib::Definition fields.
            * resolve/rust-rib.h
            (Rib::Definition::Globbed): Add.
            (Rib::Definition::ids): Remove.
            (Rib::Definition::ids_shadowable): Add.
            (Rib::Definition::ids_non_shadowable): Add.
            (Rib::Definition::ids_globbed): Add.
            (Rib::Definition::get_node_id): Handle modifications to
            Rib::Definition fields.
            (Rib::Definition::Mode): Add.
            (Rib::Definition::Definition): Use Rib::Definition::Mode to
            indicate shadowing mode instead of boolean.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/nr2/exclude: Remove shadow1.rs.
    
    Signed-off-by: Owen Avery <powerboat9.ga...@gmail.com>

Diff:
---
 gcc/rust/resolve/rust-finalize-imports-2.0.cc    |  44 +++++-----
 gcc/rust/resolve/rust-forever-stack.h            |  16 ++++
 gcc/rust/resolve/rust-forever-stack.hxx          |  24 +++++-
 gcc/rust/resolve/rust-late-name-resolver-2.0.cc  |   4 +-
 gcc/rust/resolve/rust-name-resolution-context.cc |  18 ++++
 gcc/rust/resolve/rust-name-resolution-context.h  |   3 +
 gcc/rust/resolve/rust-rib.cc                     | 103 +++++++++++++++++------
 gcc/rust/resolve/rust-rib.h                      |  30 ++++++-
 gcc/testsuite/rust/compile/nr2/exclude           |   1 -
 9 files changed, 187 insertions(+), 56 deletions(-)

diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc 
b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index 5ce05a9c6240..71916ae432bd 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
@@ -37,32 +37,32 @@ void
 GlobbingVisitor::visit (AST::Module &module)
 {
   if (module.get_visibility ().is_public ())
-    ctx.insert_shadowable (module.get_name (), module.get_node_id (),
-                          Namespace::Types);
+    ctx.insert_globbed (module.get_name (), module.get_node_id (),
+                       Namespace::Types);
 }
 
 void
 GlobbingVisitor::visit (AST::MacroRulesDefinition &macro)
 {
   if (macro.get_visibility ().is_public ())
-    ctx.insert_shadowable (macro.get_rule_name (), macro.get_node_id (),
-                          Namespace::Macros);
+    ctx.insert_globbed (macro.get_rule_name (), macro.get_node_id (),
+                       Namespace::Macros);
 }
 
 void
 GlobbingVisitor::visit (AST::Function &function)
 {
   if (function.get_visibility ().is_public ())
-    ctx.insert_shadowable (function.get_function_name (),
-                          function.get_node_id (), Namespace::Values);
+    ctx.insert_globbed (function.get_function_name (), function.get_node_id (),
+                       Namespace::Values);
 }
 
 void
 GlobbingVisitor::visit (AST::StaticItem &static_item)
 {
   if (static_item.get_visibility ().is_public ())
-    ctx.insert_shadowable (static_item.get_identifier (),
-                          static_item.get_node_id (), Namespace::Values);
+    ctx.insert_globbed (static_item.get_identifier (),
+                       static_item.get_node_id (), Namespace::Values);
 }
 
 void
@@ -70,11 +70,11 @@ GlobbingVisitor::visit (AST::StructStruct &struct_item)
 {
   if (struct_item.get_visibility ().is_public ())
     {
-      ctx.insert_shadowable (struct_item.get_identifier (),
-                            struct_item.get_node_id (), Namespace::Types);
+      ctx.insert_globbed (struct_item.get_identifier (),
+                         struct_item.get_node_id (), Namespace::Types);
       if (struct_item.is_unit_struct ())
-       ctx.insert_shadowable (struct_item.get_identifier (),
-                              struct_item.get_node_id (), Namespace::Values);
+       ctx.insert_globbed (struct_item.get_identifier (),
+                           struct_item.get_node_id (), Namespace::Values);
     }
 }
 
@@ -83,11 +83,11 @@ GlobbingVisitor::visit (AST::TupleStruct &tuple_struct)
 {
   if (tuple_struct.get_visibility ().is_public ())
     {
-      ctx.insert_shadowable (tuple_struct.get_identifier (),
-                            tuple_struct.get_node_id (), Namespace::Types);
+      ctx.insert_globbed (tuple_struct.get_identifier (),
+                         tuple_struct.get_node_id (), Namespace::Types);
 
-      ctx.insert_shadowable (tuple_struct.get_identifier (),
-                            tuple_struct.get_node_id (), Namespace::Values);
+      ctx.insert_globbed (tuple_struct.get_identifier (),
+                         tuple_struct.get_node_id (), Namespace::Values);
     }
 }
 
@@ -95,24 +95,24 @@ void
 GlobbingVisitor::visit (AST::Enum &enum_item)
 {
   if (enum_item.get_visibility ().is_public ())
-    ctx.insert_shadowable (enum_item.get_identifier (),
-                          enum_item.get_node_id (), Namespace::Types);
+    ctx.insert_globbed (enum_item.get_identifier (), enum_item.get_node_id (),
+                       Namespace::Types);
 }
 
 void
 GlobbingVisitor::visit (AST::Union &union_item)
 {
   if (union_item.get_visibility ().is_public ())
-    ctx.insert_shadowable (union_item.get_identifier (),
-                          union_item.get_node_id (), Namespace::Values);
+    ctx.insert_globbed (union_item.get_identifier (), union_item.get_node_id 
(),
+                       Namespace::Values);
 }
 
 void
 GlobbingVisitor::visit (AST::ConstantItem &const_item)
 {
   if (const_item.get_visibility ().is_public ())
-    ctx.insert_shadowable (const_item.get_identifier (),
-                          const_item.get_node_id (), Namespace::Values);
+    ctx.insert_globbed (const_item.get_identifier (), const_item.get_node_id 
(),
+                       Namespace::Values);
 }
 
 void
diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index a9aca0f1af00..c24289d0c7e4 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -452,6 +452,22 @@ public:
   tl::expected<NodeId, DuplicateNameError> insert_shadowable (Identifier name,
                                                              NodeId id);
 
+  /**
+   * Insert a new glob-originated definition in the innermost `Rib` in this
+   * stack
+   *
+   * @param name The name of the definition
+   * @param id Its NodeId
+   *
+   * @return `DuplicateNameError` if that node was already present in the Rib,
+   * the node's `NodeId` otherwise.
+   *
+   * @aborts if there are no `Rib`s inserted in the current map, this function
+   *         aborts the program.
+   */
+  tl::expected<NodeId, DuplicateNameError> insert_globbed (Identifier name,
+                                                          NodeId id);
+
   /**
    * Insert a new definition at the root of this stack
    *
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index a7d46ce0f4ee..4a8b6b59d17d 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -131,6 +131,16 @@ ForeverStack<N>::insert_shadowable (Identifier name, 
NodeId node)
                       Rib::Definition::Shadowable (node));
 }
 
+template <Namespace N>
+tl::expected<NodeId, DuplicateNameError>
+ForeverStack<N>::insert_globbed (Identifier name, NodeId node)
+{
+  auto &innermost_rib = peek ();
+
+  return insert_inner (innermost_rib, name.as_string (),
+                      Rib::Definition::Globbed (node));
+}
+
 template <Namespace N>
 tl::expected<NodeId, DuplicateNameError>
 ForeverStack<N>::insert_at_root (Identifier name, NodeId node)
@@ -474,9 +484,17 @@ ForeverStack<N>::dfs (ForeverStack<N>::Node 
&starting_point, NodeId to_find)
   auto values = starting_point.rib.get_values ();
 
   for (auto &kv : values)
-    for (auto id : kv.second.ids)
-      if (id == to_find)
-       return {{starting_point, kv.first}};
+    {
+      for (auto id : kv.second.ids_shadowable)
+       if (id == to_find)
+         return {{starting_point, kv.first}};
+      for (auto id : kv.second.ids_non_shadowable)
+       if (id == to_find)
+         return {{starting_point, kv.first}};
+      for (auto id : kv.second.ids_globbed)
+       if (id == to_find)
+         return {{starting_point, kv.first}};
+    }
 
   for (auto &child : starting_point.children)
     {
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 287972c34cef..c58cd967c97b 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -154,8 +154,8 @@ Late::visit (AST::IdentifierPattern &identifier)
   // do we insert functions in labels as well?
 
   // We do want to ignore duplicated data because some situations rely on it.
-  std::ignore
-    = ctx.values.insert (identifier.get_ident (), identifier.get_node_id ());
+  std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
+                                             identifier.get_node_id ());
 }
 
 void
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc 
b/gcc/rust/resolve/rust-name-resolution-context.cc
index d964684e4c21..d79f7b5f222a 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -64,6 +64,24 @@ NameResolutionContext::insert_shadowable (Identifier name, 
NodeId id,
     }
 }
 
+tl::expected<NodeId, DuplicateNameError>
+NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace 
ns)
+{
+  switch (ns)
+    {
+    case Namespace::Values:
+      return values.insert_globbed (name, id);
+    case Namespace::Types:
+      return types.insert_globbed (name, id);
+    case Namespace::Macros:
+      return macros.insert_globbed (name, id);
+    case Namespace::Labels:
+    default:
+      // return labels.insert (name, id);
+      rust_unreachable ();
+    }
+}
+
 void
 NameResolutionContext::map_usage (Usage usage, Definition definition)
 {
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index e06d9298abf9..e2652dc3b9eb 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -175,6 +175,9 @@ public:
   tl::expected<NodeId, DuplicateNameError>
   insert_shadowable (Identifier name, NodeId id, Namespace ns);
 
+  tl::expected<NodeId, DuplicateNameError>
+  insert_globbed (Identifier name, NodeId id, Namespace ns);
+
   /**
    * Run a lambda in a "scoped" context, meaning that a new `Rib` will be 
pushed
    * before executing the lambda and then popped. This is useful for all kinds
diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc
index 714507219e02..b0380bb0b78f 100644
--- a/gcc/rust/resolve/rust-rib.cc
+++ b/gcc/rust/resolve/rust-rib.cc
@@ -22,26 +22,51 @@
 namespace Rust {
 namespace Resolver2_0 {
 
-Rib::Definition::Definition (NodeId id, bool shadowable)
-  : ids ({id}), shadowable (shadowable)
-{}
+Rib::Definition::Definition (NodeId id, Mode mode)
+{
+  switch (mode)
+    {
+    case Mode::SHADOWABLE:
+      ids_shadowable.push_back (id);
+      return;
+    case Mode::NON_SHADOWABLE:
+      ids_non_shadowable.push_back (id);
+      return;
+    case Mode::GLOBBED:
+      ids_globbed.push_back (id);
+      return;
+    default:
+      gcc_unreachable ();
+    }
+}
 
 bool
 Rib::Definition::is_ambiguous () const
 {
-  return shadowable && ids.size () > 1;
+  if (!ids_shadowable.empty ())
+    return false;
+  else if (!ids_non_shadowable.empty ())
+    return ids_non_shadowable.size () > 1;
+  else
+    return ids_globbed.size () > 1;
 }
 
 std::string
 Rib::Definition::to_string () const
 {
   std::stringstream out;
-  out << (shadowable ? "(S)" : "(NS)") << "[";
-  std::string sep;
-  for (auto id : ids)
+  const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["};
+  const std::vector<NodeId> *id_lists[3]
+    = {&ids_shadowable, &ids_non_shadowable, &ids_globbed};
+  for (int i = 0; i < 3; i++)
     {
-      out << sep << id;
-      sep = ",";
+      out << headers[i];
+      std::string sep;
+      for (auto id : *id_lists[i])
+       {
+         out << sep << id;
+         sep = ",";
+       }
     }
   out << "]";
   return out.str ();
@@ -50,13 +75,19 @@ Rib::Definition::to_string () const
 Rib::Definition
 Rib::Definition::Shadowable (NodeId id)
 {
-  return Definition (id, true);
+  return Definition (id, Mode::SHADOWABLE);
 }
 
 Rib::Definition
 Rib::Definition::NonShadowable (NodeId id)
 {
-  return Definition (id, false);
+  return Definition (id, Mode::NON_SHADOWABLE);
+}
+
+Rib::Definition
+Rib::Definition::Globbed (NodeId id)
+{
+  return Definition (id, Mode::GLOBBED);
 }
 
 DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
@@ -85,29 +116,53 @@ Rib::insert (std::string name, Definition def)
       /* No old value */
       values[name] = def;
     }
-  else if (it->second.shadowable && def.shadowable)
-    { /* Both shadowable */
+  else if (it->second.ids_non_shadowable.empty ()
+          || def.ids_non_shadowable.empty ())
+    { /* No non-shadowable conflict */
       auto &current = values[name];
-      for (auto id : def.ids)
+      for (auto id : def.ids_non_shadowable)
        {
-         if (std::find (current.ids.cbegin (), current.ids.cend (), id)
-             == current.ids.cend ())
-           current.ids.push_back (id);
+         if (std::find (current.ids_non_shadowable.cbegin (),
+                        current.ids_non_shadowable.cend (), id)
+             == current.ids_non_shadowable.cend ())
+           current.ids_non_shadowable.push_back (id);
          else
+           // TODO: should this produce an error?
+           return tl::make_unexpected (DuplicateNameError (name, id));
+       }
+      for (auto id : def.ids_shadowable)
+       {
+         if (std::find (current.ids_shadowable.cbegin (),
+                        current.ids_shadowable.cend (), id)
+             == current.ids_shadowable.cend ())
+           current.ids_shadowable.push_back (id);
+         else
+           // TODO: should this produce an error?
+           return tl::make_unexpected (DuplicateNameError (name, id));
+       }
+      for (auto id : def.ids_globbed)
+       {
+         if (std::find (current.ids_globbed.cbegin (),
+                        current.ids_globbed.cend (), id)
+             == current.ids_globbed.cend ())
+           current.ids_globbed.push_back (id);
+         else
+           // TODO: should this produce an error?
            return tl::make_unexpected (DuplicateNameError (name, id));
        }
     }
-  else if (it->second.shadowable)
-    { /* Only old shadowable : replace value */
-      values[name] = def;
-    }
-  else /* Neither are shadowable */
+  else /* Multiple non-shadowable */
     {
       return tl::make_unexpected (
-       DuplicateNameError (name, it->second.ids.back ()));
+       DuplicateNameError (name, it->second.ids_non_shadowable.back ()));
     }
 
-  return def.ids.back ();
+  if (!def.ids_shadowable.empty ())
+    return def.ids_shadowable.back ();
+  else if (!def.ids_non_shadowable.empty ())
+    return def.ids_non_shadowable.back ();
+  rust_assert (!def.ids_globbed.empty ());
+  return def.ids_globbed.back ();
 }
 
 tl::optional<Rib::Definition>
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index 11a6b56abced..2eb8de8f0efd 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -113,9 +113,16 @@ public:
   public:
     static Definition NonShadowable (NodeId id);
     static Definition Shadowable (NodeId id);
+    static Definition Globbed (NodeId id);
 
-    std::vector<NodeId> ids;
-    bool shadowable;
+    // checked shadowable -> non_shadowable -> globbed
+    // we have shadowable *and* globbed in order to control
+    // resolution priority
+    // we *could* use a single vector with 2 indices here
+    // but it's probably not worth it for now
+    std::vector<NodeId> ids_shadowable;
+    std::vector<NodeId> ids_non_shadowable;
+    std::vector<NodeId> ids_globbed;
 
     Definition () = default;
 
@@ -126,14 +133,29 @@ public:
 
     NodeId get_node_id () const
     {
+      if (!ids_shadowable.empty ())
+       return ids_shadowable.back ();
+
       rust_assert (!is_ambiguous ());
-      return ids[0];
+
+      if (!ids_non_shadowable.empty ())
+       return ids_non_shadowable.back ();
+
+      rust_assert (!ids_globbed.empty ());
+      return ids_globbed.back ();
     }
 
     std::string to_string () const;
 
   private:
-    Definition (NodeId id, bool shadowable);
+    enum class Mode
+    {
+      SHADOWABLE,
+      NON_SHADOWABLE,
+      GLOBBED
+    };
+
+    Definition (NodeId id, Mode mode);
   };
 
   enum class Kind
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index dec3bdd4d18e..f254c56eb526 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -194,7 +194,6 @@ redef_error6.rs
 rustc_attr1.rs
 self-path1.rs
 self-path2.rs
-shadow1.rs
 sizeof-stray-infer-var-bug.rs
 specify-crate-name.rs
 stmt_with_block_dot.rs

Reply via email to