https://gcc.gnu.org/g:8dac20e0e0e1a25ab8f363266c6dc94a51c2cd5f
commit r17-1876-g8dac20e0e0e1a25ab8f363266c6dc94a51c2cd5f Author: Arthur Cohen <[email protected]> Date: Fri Apr 24 18:14:07 2026 +0200 gccrs: nr: Separate APIs properly for flattening. Namespaces, flattening and resolved_nodes are all properly separated now and in the files where they should be. gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::try_insert_once): Use new Usage -> Definition map for macros. * resolve/rust-finalized-name-resolution-context.cc (FinalizedNameResolutionContext::map_usage): Dispatch to proper resolution map. * resolve/rust-forever-stack.h (enum class LookupFinalizeError): Move here. * resolve/rust-forever-stack.hxx: Make resolution take a resolve_segment lambda with an extra namespace parameter. * resolve/rust-name-resolution-context.hxx: Likewise. * resolve/rust-name-resolution-context.cc (find_leaf_definition_inner): Move here... (NameResolutionContext::find_leaf_definition): Likewise. (NameResolutionContext::flatten): Likewise. * resolve/rust-name-resolution-context.h: ...from here. Diff: --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 2 +- .../rust-finalized-name-resolution-context.cc | 27 +++++++-- gcc/rust/resolve/rust-forever-stack.h | 39 ++++++++++-- gcc/rust/resolve/rust-forever-stack.hxx | 69 ++++++++++++++++++++-- gcc/rust/resolve/rust-name-resolution-context.cc | 69 ++-------------------- gcc/rust/resolve/rust-name-resolution-context.h | 60 ++++++++----------- gcc/rust/resolve/rust-name-resolution-context.hxx | 41 ++++++++----- 7 files changed, 177 insertions(+), 130 deletions(-) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index de68bf52e4db..148385300e9f 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -41,7 +41,7 @@ Early::Early (NameResolutionContext &ctx) void Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved) { - auto leaf_macro = ctx.find_leaf_definition (resolved); + auto leaf_macro = ctx.macros.find_leaf_definition (resolved); // Sometimes the import itself isn't resolved yet this turn of the fixed-point if (!leaf_macro) diff --git a/gcc/rust/resolve/rust-finalized-name-resolution-context.cc b/gcc/rust/resolve/rust-finalized-name-resolution-context.cc index a8902e283282..71d1269f3131 100644 --- a/gcc/rust/resolve/rust-finalized-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-finalized-name-resolution-context.cc @@ -17,6 +17,9 @@ // <http://www.gnu.org/licenses/>. #include "rust-finalized-name-resolution-context.h" +#include "expected.h" +#include "optional.h" +#include "rust-forever-stack.h" namespace Rust { namespace Resolver2_0 { @@ -45,10 +48,26 @@ void FinalizedNameResolutionContext::map_usage (Usage usage, Definition definition, Namespace ns) { - auto leaf_definition - = ctx.find_leaf_definition (definition.id).value_or (definition); - - ctx.map_usage (usage, leaf_definition, ns); + tl::expected<Definition, LookupFinalizeError> leaf_result + = tl::make_unexpected (LookupFinalizeError::NoDefinition); + + switch (ns) + { + case Namespace::Values: + leaf_result = ctx.values.find_leaf_definition (definition.id); + break; + case Namespace::Types: + leaf_result = ctx.types.find_leaf_definition (definition.id); + break; + case Namespace::Labels: + leaf_result = ctx.labels.find_leaf_definition (definition.id); + break; + case Namespace::Macros: + leaf_result = ctx.macros.find_leaf_definition (definition.id); + break; + } + + ctx.map_usage (usage, leaf_result.value_or (definition), ns); } tl::optional<NodeId> diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 3a2877244837..a2a031ddd998 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -620,6 +620,20 @@ private: NodeId node_id; }; +/** + * Error enum for finding leaf definitions in the resolved_nodes map + */ +enum class LookupFinalizeError +{ + // Impossible - we did not find any definition corresponding to a Usage. + // This is an internal compiler error + NoDefinition, + // There was a loop in the map, such as an import resolving to another + // import which eventually resolved to the original import. Report the + // error and stop the pipeline + Loop, +}; + template <Namespace N> class ForeverStack { public: @@ -862,11 +876,12 @@ public: Node &find_closest_module (Node &starting_point); - tl::optional<SegIterator> find_starting_point ( - const std::vector<ResolutionPath::Segment> &segments, - std::reference_wrapper<Node> &starting_point, - std::function<void (Usage, Definition)> insert_segment_resolution, - std::vector<Error> &collect_errors); + tl::optional<SegIterator> + find_starting_point (const std::vector<ResolutionPath::Segment> &segments, + std::reference_wrapper<Node> &starting_point, + std::function<void (Usage, Definition, Namespace)> + insert_segment_resolution, + std::vector<Error> &collect_errors); /* Helper functions for forward resolution (to_canonical_path, to_rib...) */ struct DfsResult @@ -909,7 +924,9 @@ public: void map_usage (Usage usage, Definition definition) { - auto inserted = resolved_nodes.emplace (usage, definition); + resolved_nodes.emplace (usage, definition); + + // auto inserted = resolved_nodes.emplace (usage, definition); // is that valid? // FIXME: Yikes @@ -926,6 +943,16 @@ public: return it->second.id; } + tl::expected<Definition, LookupFinalizeError> + find_leaf_definition (const NodeId &key) const; + + /** + * Look at NameResolutionContext::flatten - This is the inner working function + * which works on one specific namespace, while NameResolutionContext::flatten + * calls flatten for every namespace + */ + void flatten (); + /* Map of "usage" nodes which have been resolved to a "definition" node */ std::map<Usage, Definition> resolved_nodes; }; diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 9f1a2cdb563d..9a21dc1ee1b1 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -462,7 +462,7 @@ tl::optional<typename std::vector<ResolutionPath::Segment>::const_iterator> ForeverStack<N>::find_starting_point ( const std::vector<ResolutionPath::Segment> &segments, std::reference_wrapper<Node> &starting_point, - std::function<void (Usage, Definition)> insert_segment_resolution, + std::function<void (Usage, Definition, Namespace)> insert_segment_resolution, std::vector<Error> &collect_errors) { auto iterator = segments.begin (); @@ -485,7 +485,7 @@ ForeverStack<N>::find_starting_point ( { starting_point = root; insert_segment_resolution (Usage (seg.node_id), - Definition (starting_point.get ().id)); + Definition (starting_point.get ().id), N); iterator++; break; } @@ -494,7 +494,7 @@ ForeverStack<N>::find_starting_point ( // insert segment resolution and exit starting_point = find_closest_module (starting_point); insert_segment_resolution (Usage (seg.node_id), - Definition (starting_point.get ().id)); + Definition (starting_point.get ().id), N); iterator++; break; } @@ -513,7 +513,7 @@ ForeverStack<N>::find_starting_point ( = find_closest_module (starting_point.get ().parent.value ()); insert_segment_resolution (Usage (seg.node_id), - Definition (starting_point.get ().id)); + Definition (starting_point.get ().id), N); continue; } @@ -733,6 +733,67 @@ ForeverStack<N>::is_module_descendant (NodeId parent, NodeId child) const return dfs_node (dfs_node (root, parent).value (), child).has_value (); } +static tl::expected<Definition, LookupFinalizeError> +find_leaf_definition_inner (const Usage &key, + const std::map<Usage, Definition> &resolved_nodes, + std::set<Usage> &keys_seen) +{ + auto original_definition = resolved_nodes.find (key); + auto possible_import = Usage (original_definition->second.id); + + if (original_definition == resolved_nodes.end ()) + return tl::make_unexpected (LookupFinalizeError::NoDefinition); + + if (!keys_seen.insert (key).second) + return tl::make_unexpected (LookupFinalizeError::Loop); + + if (resolved_nodes.find (possible_import) == resolved_nodes.end ()) + return original_definition->second; + + // We're dealing with an import - a reference to another + // definition. Go through the chain and update the original key's + // corresponding definition. + return find_leaf_definition_inner (possible_import, resolved_nodes, + keys_seen); +} + +template <Namespace N> +tl::expected<Definition, LookupFinalizeError> +ForeverStack<N>::find_leaf_definition (const NodeId &key) const +{ + std::set<Usage> keys_seen; + + return find_leaf_definition_inner (Usage (key), resolved_nodes, keys_seen); +} + +template <Namespace N> +void +ForeverStack<N>::flatten () +{ + for (auto &k_v : resolved_nodes) + { + // Loop detection + auto keys_seen = std::set<Usage> (); + + auto result + = find_leaf_definition_inner (k_v.first, resolved_nodes, keys_seen); + + if (!result) + { + // Trigger an ICE if we haven't found a definition because that's + // really weird + rust_assert (result.error () != LookupFinalizeError::NoDefinition); + + // FIXME: This needs to be improved and tested, but later + rust_error_at (UNDEF_LOCATION, "import loop"); + continue; + } + + // Replace the Definition for this Usage in the map. This may be a no-op. + k_v.second = result.value (); + } +} + // FIXME: Can we add selftests? } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index c84c34258a60..479d0cb46670 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -372,74 +372,13 @@ NameResolutionContext::scoped (Rib::Kind rib_kind, Namespace ns, } } -static tl::expected<Definition, NameResolutionContext::LookupFinalizeError> -find_leaf_definition_inner (const Usage &key, - const std::map<Usage, Definition> &resolved_nodes, - std::set<Usage> &keys_seen) -{ - auto original_definition = resolved_nodes.find (key); - auto possible_import = Usage (original_definition->second.id); - - if (original_definition == resolved_nodes.end ()) - return tl::make_unexpected ( - NameResolutionContext::LookupFinalizeError::NoDefinition); - - if (!keys_seen.insert (key).second) - return tl::make_unexpected ( - NameResolutionContext::LookupFinalizeError::Loop); - - if (resolved_nodes.find (possible_import) == resolved_nodes.end ()) - return original_definition->second; - - // We're dealing with an import - a reference to another - // definition. Go through the chain and update the original key's - // corresponding definition. - return find_leaf_definition_inner (possible_import, resolved_nodes, - keys_seen); -} - -tl::expected<Definition, NameResolutionContext::LookupFinalizeError> -NameResolutionContext::find_leaf_definition (const NodeId &key) const -{ - std::set<Usage> keys_seen; - - return find_leaf_definition_inner (Usage (key), resolved_nodes, keys_seen); -} - void NameResolutionContext::flatten () { - rust_debug ("[ARTHUR] FINALIZING EARLY NR!!!!"); - - for (auto &kv : resolved_nodes) - rust_debug ("[ARTHUR] [resolved_nodes]: %d -> %d", kv.first.id, - kv.second.id); - - for (auto &k_v : resolved_nodes) - { - // Loop detection - auto keys_seen = std::set<Usage> (); - - auto result - = find_leaf_definition_inner (k_v.first, resolved_nodes, keys_seen); - - if (!result) - { - // Trigger an ICE if we haven't found a definition because that's - // really weird - rust_assert (result.error () != LookupFinalizeError::NoDefinition); - - rust_error_at (UNDEF_LOCATION, "import loop"); - continue; - } - - // Replace the Definition for this Usage in the map. This may be a no-op. - k_v.second = result.value (); - } - - for (auto &kv : resolved_nodes) - rust_debug ("[ARTHUR] [resolved_nodes]: %d -> %d", kv.first.id, - kv.second.id); + values.flatten (); + types.flatten (); + macros.flatten (); + labels.flatten (); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index fa383df37a07..f44fc2c5df54 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -585,10 +585,9 @@ public: resolve_path (const ResolutionPath &path, ResolutionMode mode, std::vector<Error> &collect_errors, Namespace ns) { - std::function<void (Usage, Definition)> insert_segment_resolution - = [this, ns] (Usage seg_id, Definition id) { - if (resolved_nodes.find (seg_id) == resolved_nodes.end ()) - map_usage (seg_id, id, ns); + std::function<void (Usage, Definition, Namespace)> insert_segment_resolution + = [this] (Usage seg_id, Definition id, Namespace ns) { + map_usage (seg_id, id, ns); }; tl::optional<NamespacedDefinition> resolved = tl::nullopt; @@ -843,20 +842,6 @@ public: std::forward<Args> (args)...); } - enum class LookupFinalizeError - { - // Impossible - we did not find any definition corresponding to a Usage. - // This is an internal compiler error - NoDefinition, - // There was a loop in the map, such as an import resolving to another - // import which eventually resolved to the original import. Report the - // error and stop the pipeline - Loop, - }; - - tl::expected<Definition, LookupFinalizeError> - find_leaf_definition (const NodeId &key) const; - /** * We've now collected every definition and import, and errored out when * necessary if multiple definitions are colliding. Do a final flattening of @@ -890,31 +875,38 @@ private: * current map, an empty one otherwise. */ template <Namespace N> - tl::optional<Rib::Definition> resolve_path ( - ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode, - std::function<void (Usage, Definition)> insert_segment_resolution, - std::vector<Error> &collect_errors); + tl::optional<Rib::Definition> + resolve_path (ForeverStack<N> &stack, const ResolutionPath &path, + ResolutionMode mode, + std::function<void (Usage, Definition, Namespace)> + insert_segment_resolution, + std::vector<Error> &collect_errors); template <Namespace N> - tl::optional<Rib::Definition> resolve_path ( - ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode, - std::function<void (Usage, Definition)> insert_segment_resolution, - std::vector<Error> &collect_errors, NodeId starting_point_id); + tl::optional<Rib::Definition> + resolve_path (ForeverStack<N> &stack, const ResolutionPath &path, + ResolutionMode mode, + std::function<void (Usage, Definition, Namespace)> + insert_segment_resolution, + std::vector<Error> &collect_errors, NodeId starting_point_id); template <Namespace N> tl::optional<Rib::Definition> resolve_path ( ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode, - std::function<void (Usage, Definition)> insert_segment_resolution, + std::function<void (Usage, Definition, Namespace)> + insert_segment_resolution, std::vector<Error> &collect_errors, std::reference_wrapper<typename ForeverStack<N>::Node> starting_point); template <Namespace N> - tl::optional<typename ForeverStack<N>::Node &> resolve_segments ( - ForeverStack<N> &stack, typename ForeverStack<N>::Node &starting_point, - const std::vector<ResolutionPath::Segment> &segments, - typename ForeverStack<N>::SegIterator iterator, - std::function<void (Usage, Definition)> insert_segment_resolution, - std::vector<Error> &collect_errors); + tl::optional<typename ForeverStack<N>::Node &> + resolve_segments (ForeverStack<N> &stack, + typename ForeverStack<N>::Node &starting_point, + const std::vector<ResolutionPath::Segment> &segments, + typename ForeverStack<N>::SegIterator iterator, + std::function<void (Usage, Definition, Namespace)> + insert_segment_resolution, + std::vector<Error> &collect_errors); template <Namespace N> tl::optional<Rib::Definition> @@ -923,7 +915,7 @@ private: std::string &seg_name, bool is_lower_self); /* Map of "usage" nodes which have been resolved to a "definition" node */ - std::map<Usage, Definition> resolved_nodes; + // std::map<Usage, Definition> resolved_nodes; }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-name-resolution-context.hxx b/gcc/rust/resolve/rust-name-resolution-context.hxx index 1492125e5c58..c16bae87443e 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.hxx +++ b/gcc/rust/resolve/rust-name-resolution-context.hxx @@ -32,7 +32,7 @@ template <Namespace N> tl::optional<Rib::Definition> NameResolutionContext::resolve_path ( ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode, - std::function<void (Usage, Definition)> insert_segment_resolution, + std::function<void (Usage, Definition, Namespace)> insert_segment_resolution, std::vector<Error> &collect_errors) { std::reference_wrapper<typename ForeverStack<N>::Node> starting_point @@ -47,7 +47,7 @@ template <Namespace N> tl::optional<Rib::Definition> NameResolutionContext::resolve_path ( ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode, - std::function<void (Usage, Definition)> insert_segment_resolution, + std::function<void (Usage, Definition, Namespace)> insert_segment_resolution, std::vector<Error> &collect_errors, NodeId starting_point_id) { @@ -67,7 +67,7 @@ template <Namespace N> tl::optional<Rib::Definition> NameResolutionContext::resolve_path ( ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode, - std::function<void (Usage, Definition)> insert_segment_resolution, + std::function<void (Usage, Definition, Namespace)> insert_segment_resolution, std::vector<Error> &collect_errors, std::reference_wrapper<typename ForeverStack<N>::Node> starting_point) { @@ -80,8 +80,8 @@ NameResolutionContext::resolve_path ( NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node (lang_item->first); - insert_segment_resolution (Usage (lang_item->second), - Definition (seg_id)); + insert_segment_resolution (Usage (lang_item->second), Definition (seg_id), + N); if (path.get_segments ().empty ()) return Rib::Definition::NonShadowable (seg_id); @@ -130,14 +130,15 @@ NameResolutionContext::resolve_path ( if (seg.is_crate_path_seg ()) { insert_segment_resolution (Usage (seg.node_id), - Definition (stack.root.id)); + Definition (stack.root.id), N); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (stack.root.id); } else if (seg.is_lower_self_seg ()) { NodeId id = stack.find_closest_module (starting_point.get ()).id; - insert_segment_resolution (Usage (seg.node_id), Definition (id)); + insert_segment_resolution (Usage (seg.node_id), Definition (id), + N); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (id); } @@ -154,7 +155,8 @@ NameResolutionContext::resolve_path ( NodeId id = stack.find_closest_module (closest_module.parent.value ()).id; - insert_segment_resolution (Usage (seg.node_id), Definition (id)); + insert_segment_resolution (Usage (seg.node_id), Definition (id), + N); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (id); } @@ -173,17 +175,19 @@ NameResolutionContext::resolve_path ( }, false)) { + // FIXME: Is the NS to insert_segment_resolution valid? insert_segment_resolution (Usage (seg.node_id), - Definition (kv.second.id)); + Definition (kv.second.id), N); return Rib::Definition::NonShadowable (kv.second.id); } } } } + // FIXME: Is the NS to insert_segment_resolution valid? if (res && !res->is_ambiguous ()) insert_segment_resolution (Usage (seg.node_id), - Definition (res->get_node_id ())); + Definition (res->get_node_id ()), N); return res; } @@ -253,7 +257,7 @@ NameResolutionContext::resolve_path ( false)) { insert_segment_resolution (Usage (seg.node_id), - Definition (kv.second.id)); + Definition (kv.second.id), N); return Rib::Definition::NonShadowable (kv.second.id); } } @@ -261,7 +265,7 @@ NameResolutionContext::resolve_path ( if (res && !res->is_ambiguous ()) insert_segment_resolution (Usage (seg.node_id), - Definition (res->get_node_id ())); + Definition (res->get_node_id ()), N); return res; } @@ -272,7 +276,7 @@ NameResolutionContext::resolve_segments ( ForeverStack<N> &stack, typename ForeverStack<N>::Node &starting_point, const std::vector<ResolutionPath::Segment> &segments, typename ForeverStack<N>::SegIterator iterator, - std::function<void (Usage, Definition)> insert_segment_resolution, + std::function<void (Usage, Definition, Namespace)> insert_segment_resolution, std::vector<Error> &collect_errors) { auto *current_node = &starting_point; @@ -350,7 +354,7 @@ NameResolutionContext::resolve_segments ( .has_value ()) { auto leaf_module - = find_leaf_definition (rib_lookup->get_node_id ()) + = stack.find_leaf_definition (rib_lookup->get_node_id ()) .value () .id; @@ -359,9 +363,14 @@ NameResolutionContext::resolve_segments ( } else { + // FIXME: Resolve segments always resolves in the Types NS + // correct? If so, we should remove the template parameter for + // this function - and use NS::Types directly here instead of + // N insert_segment_resolution (Usage (seg.node_id), Definition ( - rib_lookup->get_node_id ())); + rib_lookup->get_node_id ()), + N); return tl::nullopt; } @@ -388,7 +397,7 @@ NameResolutionContext::resolve_segments ( // the while loop above would have returned or kept looping current_node = &child->get (); insert_segment_resolution (Usage (seg.node_id), - Definition (current_node->id)); + Definition (current_node->id), N); } return *current_node;
