From: Pierre-Emmanuel Patry Date: Tue, 4 Mar 2025 15:41:48 +0000 (+0100) Subject: gccrs: Keep definition provenance to skip enum variants X-Git-Tag: basepoints/gcc-16~713 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8b178586c7ec1be0391c98c1f2361e41e002c459;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 64e8a0f0f2c..22efc973197 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -591,6 +591,9 @@ public: */ tl::expected insert (Identifier name, NodeId id); + tl::expected 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 9e66c802d5f..628b8c5b6fe 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -173,6 +173,14 @@ ForeverStack::insert (Identifier name, NodeId node) Rib::Definition::Shadowable (node)); } +template <> +inline tl::expected +ForeverStack::insert_variant (Identifier name, NodeId node) +{ + return insert_inner (peek (), name.as_string (), + Rib::Definition::NonShadowable (node, true)); +} + template Rib & ForeverStack::peek () @@ -275,10 +283,12 @@ ForeverStack::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 1b375213878..517a4836aaf 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 +NameResolutionContext::insert_variant (Identifier name, NodeId id) +{ + return types.insert_variant (name, id); +} + tl::expected 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 a381411514d..ea81bdeed54 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 insert (Identifier name, NodeId id, Namespace ns); + tl::expected insert_variant (Identifier name, + NodeId id); + tl::expected 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 b0380bb0b78..1d53a741858 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 767547f985f..ccc4c277b12 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 ids_non_shadowable; std::vector ids_globbed; + // Enum variant should be skipped when dealing with inner definition. + // struct E2; + // + // enum MyEnum /* <-- 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 572d5956c0a..8863be768a1 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 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 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 +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 fabcb5bf707..559c0d8757f 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 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 + 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