From: Arthur Cohen <[email protected]>

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.
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/3c35188069614f2b01e2c8443ece0024595c4ca4

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4149

 .../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 49ac9c821..9e0e6a258 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -411,6 +411,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 9263e19d6..2d1ce3117 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -560,23 +560,63 @@ public:
          if (resolved_nodes.find (Usage (seg_id)) == resolved_nodes.end ())
            map_usage (Usage (seg_id), Definition (id));
        };
+
+    tl::optional<Rib::Definition> 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 <typename S, typename... Args>
@@ -676,6 +716,9 @@ public:
                         std::forward<Args> (args)...);
   }
 
+  /* If declared with #[prelude_import], the current standard library module */
+  tl::optional<NodeId> prelude;
+
 private:
   /* 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-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index b3dafc480..ed93911fb 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<AST::SimplePath> &paths,
     paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ()));
 }
 
+static bool
+has_prelude_import (const std::vector<AST::Attribute> &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 cc280ec67..b5b0c8b19 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 @@ public:
     } kind;
 
     static ImportKind Glob (AST::SimplePath &&to_resolve, Rib &values_rib,
-                           Rib &types_rib, Rib &macros_rib)
+                           Rib &types_rib, Rib &macros_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 @@ public:
                              AST::UseTreeRebind &&rebind, Rib &values_rib,
                              Rib &types_rib, Rib &macros_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 @@ public:
     Rib &types_rib;
     Rib &macros_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 &macros_rib,
+               Rib &types_rib, Rib &macros_rib, bool is_prelude = false,
                tl::optional<AST::UseTreeRebind> &&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)
     {}
   };
 

base-commit: 055467b59016b87e1652eb5d3190389bd2f72af5
-- 
2.52.0

Reply via email to