diff options
author | Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> | 2025-03-04 16:41:48 +0100 |
---|---|---|
committer | P-E-P <32375388+P-E-P@users.noreply.github.com> | 2025-03-11 14:06:30 +0000 |
commit | c67466b2b28dac51da6d3a4694b31a2e53df80cd (patch) | |
tree | 0f3375d44a16a8a187f1b387bb1d1a11a633e654 /gcc | |
parent | 126680c6116cd7413b3163e41f1db968ce26666a (diff) | |
download | gcc-c67466b2b28dac51da6d3a4694b31a2e53df80cd.zip gcc-c67466b2b28dac51da6d3a4694b31a2e53df80cd.tar.gz gcc-c67466b2b28dac51da6d3a4694b31a2e53df80cd.tar.bz2 |
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.patry@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/resolve/rust-forever-stack.h | 3 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-forever-stack.hxx | 18 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-name-resolution-context.cc | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-name-resolution-context.h | 3 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-rib.cc | 17 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-rib.h | 14 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 54 | ||||
-rw-r--r-- | 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 74944fb..4c61582 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 43061ff..fcd50af 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 1a70cd0..38994fe 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -46,6 +46,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 19b9436..d21b868 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 34abbff..e3d1d31 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 da1838a..8748969 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 310b3c5..2c0cc66 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 ff86cf4..f385bc1 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 |