From f60bddd7ce6cefdfaa096880d0e5b33cddf202d6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 10 Sep 2025 09:07:55 +0200 Subject: [PATCH 1/3] nr: Add prelude field to NRCtx, and fill it upon encountering a prelude. gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_glob_import): Save prelude if we find one. * resolve/rust-name-resolution-context.h: Add field. * resolve/rust-toplevel-name-resolver-2.0.cc (has_prelude_import): New function. (TopLevel::visit): Create a prelude glob import if necessary. * resolve/rust-toplevel-name-resolver-2.0.h: Allow glob imports to be prelude imports. --- .../resolve/rust-early-name-resolver-2.0.cc | 8 +++ .../resolve/rust-name-resolution-context.h | 59 ++++++++++++++++--- .../rust-toplevel-name-resolver-2.0.cc | 13 +++- .../resolve/rust-toplevel-name-resolver-2.0.h | 18 ++++-- 4 files changed, 83 insertions(+), 15 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 0dff83153311..fb63b0edbac2 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -410,6 +410,14 @@ Early::finalize_glob_import (NameResolutionContext &ctx, rust_assert (container); + if (mapping.import_kind.is_prelude) + { + rust_assert (container.value ()->get_item_kind () + == AST::Item::Kind::Module); + + ctx.prelude = container.value ()->get_node_id (); + } + GlobbingVisitor (ctx).go (container.value ()); } diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 558b3cab6647..25922bc3c93b 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -560,23 +560,63 @@ class NameResolutionContext if (resolved_nodes.find (Usage (seg_id)) == resolved_nodes.end ()) map_usage (Usage (seg_id), Definition (id)); }; + + tl::optional resolved = tl::nullopt; + switch (ns) { case Namespace::Values: - return values.resolve_path (segments, mode, insert_segment_resolution, - collect_errors); + resolved + = values.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); + break; case Namespace::Types: - return types.resolve_path (segments, mode, insert_segment_resolution, - collect_errors); + resolved + = types.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); + break; case Namespace::Macros: - return macros.resolve_path (segments, mode, insert_segment_resolution, - collect_errors); + resolved + = macros.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); + break; case Namespace::Labels: - return labels.resolve_path (segments, mode, insert_segment_resolution, - collect_errors); + resolved + = labels.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); + break; default: rust_unreachable (); } + + // If it fails, switch to std prelude resolution if it exists + if (prelude && !resolved) + { + // TODO: Factor this with the above + switch (ns) + { + case Namespace::Values: + return values.resolve_path (segments, mode, + insert_segment_resolution, + collect_errors, *prelude); + case Namespace::Types: + return types.resolve_path (segments, mode, + insert_segment_resolution, + collect_errors, *prelude); + case Namespace::Macros: + return macros.resolve_path (segments, mode, + insert_segment_resolution, + collect_errors, *prelude); + case Namespace::Labels: + return labels.resolve_path (segments, mode, + insert_segment_resolution, + collect_errors, *prelude); + default: + rust_unreachable (); + } + } + + return resolved; } template @@ -676,6 +716,9 @@ class NameResolutionContext std::forward (args)...); } + /* If declared with #[prelude_import], the current standard library module */ + tl::optional prelude; + private: /* Map of "usage" nodes which have been resolved to a "definition" node */ std::map resolved_nodes; 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 0930f966e202..dcd1592a8373 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -496,6 +496,16 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths, paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ())); } +static bool +has_prelude_import (const std::vector &attributes) +{ + for (const auto &attr : attributes) + if (attr.get_path ().as_string () == "prelude_import") + return true; + + return false; +} + void TopLevel::visit (AST::UseDeclaration &use) { @@ -523,7 +533,8 @@ TopLevel::visit (AST::UseDeclaration &use) for (auto &&glob : glob_path) imports.emplace_back ( - ImportKind::Glob (std::move (glob), values_rib, types_rib, macros_rib)); + ImportKind::Glob (std::move (glob), values_rib, types_rib, macros_rib, + has_prelude_import (use.get_outer_attrs ()))); for (auto &&rebind : rebind_path) imports.emplace_back ( 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 8d3da92961ad..fca1b368b16c 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -67,10 +67,10 @@ class TopLevel : public DefaultResolver } kind; static ImportKind Glob (AST::SimplePath &&to_resolve, Rib &values_rib, - Rib &types_rib, Rib ¯os_rib) + Rib &types_rib, Rib ¯os_rib, bool is_prelude) { return ImportKind (Kind::Glob, std::move (to_resolve), values_rib, - types_rib, macros_rib); + types_rib, macros_rib, is_prelude); } static ImportKind Simple (AST::SimplePath &&to_resolve, Rib &values_rib, @@ -84,8 +84,10 @@ class TopLevel : public DefaultResolver AST::UseTreeRebind &&rebind, Rib &values_rib, Rib &types_rib, Rib ¯os_rib) { - return ImportKind (Kind::Rebind, std::move (to_resolve), values_rib, - types_rib, macros_rib, std::move (rebind)); + return ImportKind ( + Kind::Rebind, std::move (to_resolve), values_rib, types_rib, macros_rib, + false /* is_prelude: rebind imports can never be preludes */, + std::move (rebind)); } // The path for `Early` to resolve. @@ -98,13 +100,17 @@ class TopLevel : public DefaultResolver Rib &types_rib; Rib ¯os_rib; + // Can only be true if we are dealing with a glob import with the + // #[prelude_import] attribute + bool is_prelude = false; + private: ImportKind (Kind kind, AST::SimplePath &&to_resolve, Rib &values_rib, - Rib &types_rib, Rib ¯os_rib, + Rib &types_rib, Rib ¯os_rib, bool is_prelude = false, tl::optional &&rebind = tl::nullopt) : kind (kind), to_resolve (std::move (to_resolve)), rebind (std::move (rebind)), values_rib (values_rib), - types_rib (types_rib), macros_rib (macros_rib) + types_rib (types_rib), macros_rib (macros_rib), is_prelude (is_prelude) {} }; From aa7435e57b9d5d57d6ba6a9432d8375b01532878 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 10 Sep 2025 09:39:18 +0200 Subject: [PATCH 2/3] forever-stack: Add extra path resolution from a known NodeId. gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: Add new resolve_path function. * resolve/rust-forever-stack.hxx: Implement it. --- gcc/rust/resolve/rust-forever-stack.h | 18 ++++++++++++- gcc/rust/resolve/rust-forever-stack.hxx | 35 ++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 75dd87395bef..927e54705a17 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -682,6 +682,11 @@ template class ForeverStack const std::vector &segments, ResolutionMode mode, std::function insert_segment_resolution, std::vector &collect_errors); + template + tl::optional resolve_path ( + const std::vector &segments, ResolutionMode mode, + std::function insert_segment_resolution, + std::vector &collect_errors, NodeId starting_point_id); // FIXME: Documentation tl::optional to_rib (NodeId rib_id); @@ -743,9 +748,19 @@ template class ForeverStack tl::optional parent; // `None` only if the node is a root }; - // private overload which allows specifying a starting point + /** + * Private overloads which allow specifying a starting point + */ + tl::optional get (Node &start, const Identifier &name); + template + tl::optional resolve_path ( + const std::vector &segments, ResolutionMode mode, + std::function insert_segment_resolution, + std::vector &collect_errors, + std::reference_wrapper starting_point); + /* Should we keep going upon seeing a Rib? */ enum class KeepGoing { @@ -777,6 +792,7 @@ template class ForeverStack * resolution */ Node lang_prelude; + /* * The extern prelude, used for resolving external crates */ diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 848f5e61522b..c0b3041e9655 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -647,6 +647,25 @@ ForeverStack::resolve_final_segment (Node &final_node, std::string &seg_name, return final_node.rib.get (seg_name); } +template +template +tl::optional +ForeverStack::resolve_path ( + const std::vector &segments, ResolutionMode mode, + std::function insert_segment_resolution, + std::vector &collect_errors, NodeId starting_point_id) +{ + auto starting_point = dfs_node (root, starting_point_id); + + // We may have a prelude, but haven't visited it yet and thus it's not in our + // nodes + if (!starting_point) + return tl::nullopt; + + return resolve_path (segments, mode, insert_segment_resolution, + collect_errors, *starting_point); +} + template template tl::optional @@ -654,10 +673,24 @@ ForeverStack::resolve_path ( const std::vector &segments, ResolutionMode mode, std::function insert_segment_resolution, std::vector &collect_errors) +{ + std::reference_wrapper starting_point = cursor (); + + return resolve_path (segments, mode, insert_segment_resolution, + collect_errors, starting_point); +} + +template +template +tl::optional +ForeverStack::resolve_path ( + const std::vector &segments, ResolutionMode mode, + std::function insert_segment_resolution, + std::vector &collect_errors, + std::reference_wrapper starting_point) { rust_assert (!segments.empty ()); - std::reference_wrapper starting_point = cursor (); switch (mode) { case ResolutionMode::Normal: From 8811544fadfdbdbc268427dac903ddb0e333354a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 12 Sep 2025 16:11:15 +0200 Subject: [PATCH 3/3] nr: Do prelude resolution for Identifiers gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: New function. * resolve/rust-forever-stack.hxx: Implement it. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Call it if the prelude exists and we have an unresolved Identifier Call it if the prelude exists and we have an unresolved Identifier. --- gcc/rust/resolve/rust-forever-stack.h | 2 ++ gcc/rust/resolve/rust-forever-stack.hxx | 11 +++++++++++ gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 12 +++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 927e54705a17..4e6e433e407f 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -668,6 +668,8 @@ template class ForeverStack tl::optional get (const Identifier &name); tl::optional get_lang_prelude (const Identifier &name); tl::optional get_lang_prelude (const std::string &name); + tl::optional get_from_prelude (NodeId prelude, + const Identifier &name); /** * Resolve a path to its definition in the current `ForeverStack` diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index c0b3041e9655..ffdfb871155e 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -343,6 +343,17 @@ ForeverStack::get_lang_prelude (const std::string &name) return lang_prelude.rib.get (name); } +template +tl::optional +ForeverStack::get_from_prelude (NodeId prelude, const Identifier &name) +{ + auto starting_point = dfs_node (root, prelude); + if (!starting_point) + return tl::nullopt; + + return get (*starting_point, name); +} + template <> tl::optional inline ForeverStack::get ( const Identifier &name) 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 96b38f48e4e4..f87f2515e14c 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -348,7 +348,17 @@ Late::visit (AST::IdentifierExpr &expr) { resolved = type; } - else + else if (!resolved && ctx.prelude) + { + resolved + = ctx.values.get_from_prelude (*ctx.prelude, expr.get_ident ()); + + if (!resolved) + resolved + = ctx.types.get_from_prelude (*ctx.prelude, expr.get_ident ()); + } + + if (!resolved) { rust_error_at (expr.get_locus (), ErrorCode::E0425, "cannot find value %qs in this scope",