https://gcc.gnu.org/g:8b178586c7ec1be0391c98c1f2361e41e002c459

commit r15-8840-g8b178586c7ec1be0391c98c1f2361e41e002c459
Author: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>
Date:   Tue Mar 4 16:41:48 2025 +0100

    gccrs: Keep definition provenance to skip enum variants
    
    Enum variants shouldn't be accessed directly even from within an enum.
    This commit keeps the provenance for enum variants definition so we
    can skip them when resolving a value within an enum definition.
    
    gcc/rust/ChangeLog:
    
            * resolve/rust-forever-stack.h: Add new function to insert enum
            variants and add argument to resolver's get function to explicitely
            skip enum variants.
            * resolve/rust-forever-stack.hxx: Update function
            definitions.
            * resolve/rust-name-resolution-context.cc 
(NameResolutionContext::insert_variant):
            Add function to insert enum variants.
            * resolve/rust-name-resolution-context.h: Add function's prototype.
            * resolve/rust-rib.cc (Rib::Definition::Definition): Add new 
boolean to
            hint at enum variant provenance.
            (Rib::Definition::is_variant): New getter for variant status.
            (Rib::Definition::Shadowable): Update constructor to opt out of enum
            variants.
            (Rib::Definition::Globbed): Likewise.
            (Rib::Definition::NonShadowable): Change constructor to forward enum
            variant provenance status.
            * resolve/rust-rib.h: Update function prototypes.
            * resolve/rust-toplevel-name-resolver-2.0.cc 
(TopLevel::insert_enum_variant_or_error_out):
            Add function to insert enum variants in the name resolver.
            (TopLevel::visit): Update several enum variant's visitor function
            with the new enum variant name resolving code.
            * resolve/rust-toplevel-name-resolver-2.0.h: Update function
            prototypes.
    
    Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>

Diff:
---
 gcc/rust/resolve/rust-forever-stack.h              |  3 ++
 gcc/rust/resolve/rust-forever-stack.hxx            | 18 ++++++--
 gcc/rust/resolve/rust-name-resolution-context.cc   |  6 +++
 gcc/rust/resolve/rust-name-resolution-context.h    |  3 ++
 gcc/rust/resolve/rust-rib.cc                       | 17 +++++--
 gcc/rust/resolve/rust-rib.h                        | 14 +++++-
 .../resolve/rust-toplevel-name-resolver-2.0.cc     | 54 ++++++++++++++++------
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h | 17 ++++++-
 8 files changed, 106 insertions(+), 26 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index 64e8a0f0f2c9..22efc9731977 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -591,6 +591,9 @@ public:
    */
   tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id);
 
+  tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
+                                                          NodeId id);
+
   /**
    * Insert a new shadowable definition in the innermost `Rib` in this stack
    *
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 9e66c802d5f2..628b8c5b6fe8 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -173,6 +173,14 @@ ForeverStack<Namespace::Labels>::insert (Identifier name, 
NodeId node)
                       Rib::Definition::Shadowable (node));
 }
 
+template <>
+inline tl::expected<NodeId, DuplicateNameError>
+ForeverStack<Namespace::Types>::insert_variant (Identifier name, NodeId node)
+{
+  return insert_inner (peek (), name.as_string (),
+                      Rib::Definition::NonShadowable (node, true));
+}
+
 template <Namespace N>
 Rib &
 ForeverStack<N>::peek ()
@@ -275,10 +283,12 @@ ForeverStack<N>::get (const Identifier &name)
 
     return candidate.map_or (
       [&resolved_definition] (Rib::Definition found) {
-       // for most namespaces, we do not need to care about various ribs - they
-       // are available from all contexts if defined in the current scope, or
-       // an outermore one. so if we do have a candidate, we can return it
-       // directly and stop iterating
+       if (found.is_variant ())
+         return KeepGoing::Yes;
+       // for most namespaces, we do not need to care about various ribs -
+       // they are available from all contexts if defined in the current
+       // scope, or an outermore one. so if we do have a candidate, we can
+       // return it directly and stop iterating
        resolved_definition = found;
 
        return KeepGoing::No;
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc 
b/gcc/rust/resolve/rust-name-resolution-context.cc
index 1b3752138785..517a4836aafd 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -45,6 +45,12 @@ NameResolutionContext::insert (Identifier name, NodeId id, 
Namespace ns)
     }
 }
 
+tl::expected<NodeId, DuplicateNameError>
+NameResolutionContext::insert_variant (Identifier name, NodeId id)
+{
+  return types.insert_variant (name, id);
+}
+
 tl::expected<NodeId, DuplicateNameError>
 NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
                                          Namespace ns)
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index a381411514d2..ea81bdeed54f 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -172,6 +172,9 @@ public:
   tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id,
                                                   Namespace ns);
 
+  tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
+                                                          NodeId id);
+
   tl::expected<NodeId, DuplicateNameError>
   insert_shadowable (Identifier name, NodeId id, Namespace ns);
 
diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc
index b0380bb0b78f..1d53a7418588 100644
--- a/gcc/rust/resolve/rust-rib.cc
+++ b/gcc/rust/resolve/rust-rib.cc
@@ -22,7 +22,8 @@
 namespace Rust {
 namespace Resolver2_0 {
 
-Rib::Definition::Definition (NodeId id, Mode mode)
+Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
+  : enum_variant (enum_variant)
 {
   switch (mode)
     {
@@ -51,6 +52,12 @@ Rib::Definition::is_ambiguous () const
     return ids_globbed.size () > 1;
 }
 
+bool
+Rib::Definition::is_variant () const
+{
+  return enum_variant;
+}
+
 std::string
 Rib::Definition::to_string () const
 {
@@ -75,19 +82,19 @@ Rib::Definition::to_string () const
 Rib::Definition
 Rib::Definition::Shadowable (NodeId id)
 {
-  return Definition (id, Mode::SHADOWABLE);
+  return Definition (id, Mode::SHADOWABLE, false);
 }
 
 Rib::Definition
-Rib::Definition::NonShadowable (NodeId id)
+Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
 {
-  return Definition (id, Mode::NON_SHADOWABLE);
+  return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
 }
 
 Rib::Definition
 Rib::Definition::Globbed (NodeId id)
 {
-  return Definition (id, Mode::GLOBBED);
+  return Definition (id, Mode::GLOBBED, false);
 }
 
 DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index 767547f985f7..ccc4c277b125 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -111,7 +111,7 @@ public:
   class Definition
   {
   public:
-    static Definition NonShadowable (NodeId id);
+    static Definition NonShadowable (NodeId id, bool enum_variant = false);
     static Definition Shadowable (NodeId id);
     static Definition Globbed (NodeId id);
 
@@ -124,11 +124,21 @@ public:
     std::vector<NodeId> ids_non_shadowable;
     std::vector<NodeId> ids_globbed;
 
+    // Enum variant should be skipped when dealing with inner definition.
+    // struct E2;
+    //
+    // enum MyEnum<T> /* <-- Should be kept */{
+    //     E2 /* <-- Should be skipped */ (E2);
+    // }
+    bool enum_variant;
+
     Definition () = default;
 
     Definition &operator= (const Definition &) = default;
     Definition (Definition const &) = default;
 
+    bool is_variant () const;
+
     bool is_ambiguous () const;
 
     NodeId get_node_id () const
@@ -155,7 +165,7 @@ public:
       GLOBBED
     };
 
-    Definition (NodeId id, Mode mode);
+    Definition (NodeId id, Mode mode, bool enum_variant);
   };
 
   enum class Kind
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index 572d5956c0a8..8863be768a1a 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -32,21 +32,18 @@ TopLevel::TopLevel (NameResolutionContext &resolver)
 
 template <typename T>
 void
-TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
-                              Namespace ns)
+TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
+                                           const T &node)
 {
-  insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
+  insert_enum_variant_or_error_out (identifier, node.get_locus (),
+                                   node.get_node_id ());
 }
 
 void
-TopLevel::insert_or_error_out (const Identifier &identifier,
-                              const location_t &locus, const NodeId &node_id,
-                              Namespace ns)
+TopLevel::check_multiple_insertion_error (
+  tl::expected<NodeId, DuplicateNameError> result, const Identifier 
&identifier,
+  const location_t &locus, const NodeId node_id)
 {
-  // keep track of each node's location to provide useful errors
-  node_locations.emplace (node_id, locus);
-
-  auto result = ctx.insert (identifier, node_id, ns);
   if (result)
     dirty = true;
   else if (result.error ().existing != node_id)
@@ -58,6 +55,37 @@ TopLevel::insert_or_error_out (const Identifier &identifier,
                     identifier.as_string ().c_str ());
     }
 }
+void
+TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
+                                           const location_t &locus,
+                                           const NodeId node_id)
+{
+  // keep track of each node's location to provide useful errors
+  node_locations.emplace (node_id, locus);
+
+  auto result = ctx.insert_variant (identifier, node_id);
+  check_multiple_insertion_error (result, identifier, locus, node_id);
+}
+
+template <typename T>
+void
+TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
+                              Namespace ns)
+{
+  insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
+}
+
+void
+TopLevel::insert_or_error_out (const Identifier &identifier,
+                              const location_t &locus, const NodeId &node_id,
+                              Namespace ns)
+{
+  // keep track of each node's location to provide useful errors
+  node_locations.emplace (node_id, locus);
+
+  auto result = ctx.insert (identifier, node_id, ns);
+  check_multiple_insertion_error (result, identifier, locus, node_id);
+}
 
 void
 TopLevel::go (AST::Crate &crate)
@@ -336,19 +364,19 @@ TopLevel::visit (AST::TupleStruct &tuple_struct)
 void
 TopLevel::visit (AST::EnumItem &variant)
 {
-  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+  insert_enum_variant_or_error_out (variant.get_identifier (), variant);
 }
 
 void
 TopLevel::visit (AST::EnumItemTuple &variant)
 {
-  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+  insert_enum_variant_or_error_out (variant.get_identifier (), variant);
 }
 
 void
 TopLevel::visit (AST::EnumItemStruct &variant)
 {
-  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+  insert_enum_variant_or_error_out (variant.get_identifier (), variant);
 }
 
 void
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index fabcb5bf7073..559c0d8757f2 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -114,9 +114,14 @@ public:
     return std::move (imports_to_resolve);
   }
 
+  void check_multiple_insertion_error (
+    tl::expected<NodeId, DuplicateNameError> result,
+    const Identifier &identifier, const location_t &locus,
+    const NodeId node_id);
+
   /**
-   * Insert a new definition or error out if a definition with the same name 
was
-   * already present in the same namespace in the same scope.
+   * Insert a new definition or error out if a definition with the same name
+   * was already present in the same namespace in the same scope.
    *
    * @param identifier The identifier of the definition to add.
    * @param node A reference to the node, so we can get its `NodeId` and
@@ -130,6 +135,14 @@ public:
                            const location_t &locus, const NodeId &id,
                            Namespace ns);
 
+  template <typename T>
+  void insert_enum_variant_or_error_out (const Identifier &identifier,
+                                        const T &node);
+
+  void insert_enum_variant_or_error_out (const Identifier &identifier,
+                                        const location_t &locus,
+                                        const NodeId node_id);
+
 private:
   // If a new export has been defined whilst visiting the visitor is considered
   // dirty

Reply via email to