From: Pierre-Emmanuel Patry <[email protected]>

We used in several places a vector of segment (unspecified segment kind)
but left the opening scope information. This commit introduces a new
class to group both segments and opening scope information in one place.

gcc/rust/ChangeLog:

        * ast/rust-ast.h: Add a new function to convert to util path.
        * ast/rust-path.h: Likewise.
        * resolve/rust-early-name-resolver-2.0.cc (Early::resolve_glob_import):
        Create a UtilPath and use it.
        * resolve/rust-early-name-resolver-2.0.h: Likewise.
        * resolve/rust-forever-stack.h: Change ResolutionPath class to add an
        opening_scope_resolution flag to mark extern prelude paths. Add a
        getter for that flag.
        * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use a UtilPath.
        * resolve/rust-name-resolution-context.h: Change set_path functions
        to accept a UtilPath instead of a simple vector or segment.
        * util/rust-util-path.h: New file.

Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
---
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/61950bcefd1e0aa20ed6dd5a29aca1593c960f79

The commit has NOT been mentioned in any issue.

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

 gcc/rust/ast/rust-ast.h                       |  7 ++
 gcc/rust/ast/rust-path.h                      | 12 ++++
 .../resolve/rust-early-name-resolver-2.0.cc   |  9 ++-
 .../resolve/rust-early-name-resolver-2.0.h    | 11 +++-
 gcc/rust/resolve/rust-forever-stack.h         | 14 +++-
 .../resolve/rust-late-name-resolver-2.0.cc    |  5 +-
 .../resolve/rust-name-resolution-context.h    | 64 +++++++++----------
 gcc/rust/util/rust-util-path.h                | 41 ++++++++++++
 8 files changed, 120 insertions(+), 43 deletions(-)
 create mode 100644 gcc/rust/util/rust-util-path.h

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 50778bcaf..d2d76edb0 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -28,6 +28,7 @@
 #include "rust-keyword-values.h"
 #include "rust-cloneable.h"
 #include "rust-ast-identifier.h"
+#include "rust-util-path.h"
 
 namespace Rust {
 // TODO: remove typedefs and make actual types for these
@@ -411,6 +412,12 @@ public:
   {
     return segments.back ();
   }
+
+  UtilPath<SimplePathSegment> as_util_path () const
+  {
+    return UtilPath<SimplePathSegment> (get_segments (),
+                                       has_opening_scope_resolution ());
+  }
 };
 
 // path-to-string inverse comparison operator
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index ecb156e90..37f5c19c9 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -811,6 +811,12 @@ public:
     return Expr::Kind::PathInExpression;
   }
 
+  UtilPath<PathExprSegment> as_util_path () const
+  {
+    return UtilPath<PathExprSegment> (get_segments (),
+                                     has_opening_scope_resolution);
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object
    * rather than base */
@@ -1369,6 +1375,12 @@ public:
   size_t get_num_segments () const { return segments.size (); }
 
   Type::Kind get_type_kind () const override { return Type::Kind::TypePath; }
+
+  UtilPath<std::unique_ptr<TypePathSegment>> as_util_path () const
+  {
+    return UtilPath<std::unique_ptr<TypePathSegment>> (
+      get_segments (), has_opening_scope_resolution_op ());
+  }
 };
 
 struct QualifiedPathType
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 1422a300d..6a7100127 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -111,9 +111,12 @@ Early::import_resolution_mode (const AST::SimplePath &path)
 bool
 Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
 {
-  auto resolved = ctx.resolve_path (glob.to_resolve.get_segments (),
-                                   import_resolution_mode (glob.to_resolve),
-                                   Namespace::Types);
+  auto path = UtilPath<AST::SimplePathSegment> (
+    glob.to_resolve.get_segments (),
+    glob.to_resolve.has_opening_scope_resolution ());
+  auto resolved
+    = ctx.resolve_path (path, import_resolution_mode (glob.to_resolve),
+                       Namespace::Types);
   if (!resolved.has_value ())
     return false;
 
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index c8cfe3891..610c6df39 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -221,6 +221,7 @@ private:
   resolve_path_in_all_ns (const P &path)
   {
     auto &segments = path.get_segments ();
+    bool opening_scope_resolution = path.has_opening_scope_resolution ();
     auto mode = import_resolution_mode (path);
 
     std::vector<NameResolutionContext::NamespacedDefinition> resolved;
@@ -234,11 +235,15 @@ private:
          resolved.emplace_back (new_def);
        };
 
-    ctx.resolve_path (segments, mode, value_errors, Namespace::Values)
+    auto util_path = UtilPath<
+      typename std::remove_reference_t<decltype (segments)>::value_type> (
+      segments, opening_scope_resolution);
+
+    ctx.resolve_path (util_path, mode, value_errors, Namespace::Values)
       .map (resolved_fn);
-    ctx.resolve_path (segments, mode, type_errors, Namespace::Types)
+    ctx.resolve_path (util_path, mode, type_errors, Namespace::Types)
       .map (resolved_fn);
-    ctx.resolve_path (segments, mode, macro_errors, Namespace::Macros)
+    ctx.resolve_path (util_path, mode, macro_errors, Namespace::Macros)
       .map (resolved_fn);
 
     if (!value_errors.empty () && !type_errors.empty ()
diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index 22cb68850..0f9874eb8 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -406,8 +406,9 @@ class ResolutionPath
 {
 public:
   template <typename T>
-  ResolutionPath (const std::vector<T> &segments_in, NodeId node_id)
-    : node_id (node_id)
+  ResolutionPath (const std::vector<T> &segments_in,
+                 bool opening_scope_resolution, NodeId node_id)
+    : opening_scope_resolution (opening_scope_resolution), node_id (node_id)
   {
     segments.clear ();
     segments.reserve (segments_in.size ());
@@ -431,7 +432,8 @@ public:
       }
   }
 
-  ResolutionPath () : node_id (UNKNOWN_NODEID) {}
+  ResolutionPath () : opening_scope_resolution (false), node_id 
(UNKNOWN_NODEID)
+  {}
 
   struct Segment
   {
@@ -452,6 +454,11 @@ public:
 
   const std::vector<Segment> &get_segments () const { return segments; }
 
+  bool has_opening_scope_resolution () const
+  {
+    return opening_scope_resolution;
+  }
+
   NodeId get_node_id () const { return node_id; }
 
   std::string as_string () const
@@ -474,6 +481,7 @@ public:
 private:
   tl::optional<std::pair<LangItem::Kind, NodeId>> lang_prefix;
   std::vector<Segment> segments;
+  bool opening_scope_resolution;
   NodeId node_id;
 };
 
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 dfcf6b283..6bf67f145 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -628,7 +628,10 @@ Late::visit (AST::Visibility &vis)
        }
     }
 
-  auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
+  auto util_path
+    = UtilPath<AST::SimplePathSegment> (path.get_segments (),
+                                       path.has_opening_scope_resolution ());
+  auto res = ctx.resolve_path (util_path, mode, Namespace::Types);
 
   if (!res.has_value ())
     {
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index f9a277ce1..62b31d9b1 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -26,6 +26,7 @@
 #include "rust-stacked-contexts.h"
 #include "rust-item.h"
 #include "rust-name-resolution.h"
+#include "rust-util-path.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -686,12 +687,12 @@ public:
     ResolutionBuilder (NameResolutionContext &ctx) : ctx (&ctx) {}
 
     template <typename S>
-    void set_path (const std::vector<S> &path_segments, NodeId node_id,
-                  bool has_opening_scope)
+    void set_path (const UtilPath<S> &util_path, NodeId node_id)
     {
-      path = ResolutionPath (path_segments, node_id);
+      path = ResolutionPath (util_path.get_segments (),
+                            util_path.has_opening_scope (), node_id);
       mode = ResolutionMode::Normal;
-      if (has_opening_scope)
+      if (util_path.has_opening_scope ())
        {
          if (get_rust_edition () == Edition::E2015)
            mode = ResolutionMode::FromRoot;
@@ -702,30 +703,28 @@ public:
     }
 
     template <typename S>
-    void set_path (const std::vector<S> &path_segments, NodeId node_id,
+    void set_path (const UtilPath<S> &util_path, NodeId node_id,
                   ResolutionMode mode)
     {
-      path = ResolutionPath (path_segments, node_id);
+      path = ResolutionPath (util_path.get_segments (),
+                            util_path.has_opening_scope (), node_id);
       this->mode = mode;
       has_path_set = true;
     }
 
     void set_path (const AST::SimplePath &path)
     {
-      set_path (path.get_segments (), path.get_node_id (),
-               path.has_opening_scope_resolution ());
+      set_path (path.as_util_path (), path.get_node_id ());
     }
 
     void set_path (const AST::PathInExpression &path)
     {
-      set_path (path.get_segments (), path.get_node_id (),
-               path.opening_scope_resolution ());
+      set_path (path.as_util_path (), path.get_node_id ());
     }
 
     void set_path (const AST::TypePath &path)
     {
-      set_path (path.get_segments (), path.get_node_id (),
-               path.has_opening_scope_resolution_op ());
+      set_path (path.as_util_path (), path.get_node_id ());
     }
 
     void set_mode (ResolutionMode mode) { this->mode = mode; }
@@ -786,12 +785,12 @@ public:
 
   template <typename S, typename... Args>
   tl::optional<NamespacedDefinition>
-  resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
+  resolve_path (const UtilPath<S> &path, ResolutionMode mode,
                tl::optional<std::vector<Error> &> collect_errors,
                Namespace ns_first, Args... ns_args)
   {
     ResolutionBuilder builder (*this);
-    builder.set_path (path_segments, UNKNOWN_NODEID, mode);
+    builder.set_path (path, UNKNOWN_NODEID, mode);
     builder.add_namespaces (ns_first, ns_args...);
     builder.set_collect_errors (collect_errors);
 
@@ -800,14 +799,13 @@ public:
 
   template <typename S, typename... Args>
   tl::optional<NamespacedDefinition>
-  resolve_path (const std::vector<S> &path_segments,
-               bool has_opening_scope_resolution,
+  resolve_path (const UtilPath<S> &path,
                tl::optional<std::vector<Error> &> collect_errors,
                Namespace ns_first, Args... ns_args)
   {
     ResolutionBuilder builder (*this);
-    builder.set_path (path_segments, UNKNOWN_NODEID,
-                     has_opening_scope_resolution);
+    builder.set_path (path.get_segments (), path.has_opening_scope (),
+                     UNKNOWN_NODEID);
     builder.add_namespaces (ns_first, ns_args...);
     builder.set_collect_errors (collect_errors);
 
@@ -816,13 +814,10 @@ public:
 
   template <typename S, typename... Args>
   tl::optional<NamespacedDefinition>
-  resolve_path (const std::vector<S> &path_segments,
-               bool has_opening_scope_resolution, Namespace ns_first,
-               Args... ns_args)
+  resolve_path (const UtilPath<S> &path, Namespace ns_first, Args... ns_args)
   {
     ResolutionBuilder builder (*this);
-    builder.set_path (path_segments, UNKNOWN_NODEID,
-                     has_opening_scope_resolution);
+    builder.set_path (path, UNKNOWN_NODEID);
     builder.add_namespaces (ns_first, ns_args...);
 
     return builder.resolve ();
@@ -830,11 +825,11 @@ public:
 
   template <typename S, typename... Args>
   tl::optional<NamespacedDefinition>
-  resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
+  resolve_path (const UtilPath<S> &path, ResolutionMode mode,
                Namespace ns_first, Args... ns_args)
   {
     ResolutionBuilder builder (*this);
-    builder.set_path (path_segments, UNKNOWN_NODEID, mode);
+    builder.set_path (path, UNKNOWN_NODEID, mode);
     builder.add_namespaces (ns_first, ns_args...);
 
     return builder.resolve ();
@@ -844,26 +839,29 @@ public:
   tl::optional<NamespacedDefinition> resolve_path (const AST::SimplePath &path,
                                                   Args &&...args)
   {
-    return resolve_path (path.get_segments (),
-                        path.has_opening_scope_resolution (),
-                        std::forward<Args> (args)...);
+    auto util_path
+      = UtilPath<AST::SimplePathSegment> (path.get_segments (),
+                                         path.has_opening_scope_resolution ());
+    return resolve_path (util_path, std::forward<Args> (args)...);
   }
 
   template <typename... Args>
   tl::optional<NamespacedDefinition>
   resolve_path (const AST::PathInExpression &path, Args &&...args)
   {
-    return resolve_path (path.get_segments (), path.opening_scope_resolution 
(),
-                        std::forward<Args> (args)...);
+    auto util_path
+      = UtilPath<AST::PathExprSegment> (path.get_segments (),
+                                       path.opening_scope_resolution ());
+    return resolve_path (util_path, std::forward<Args> (args)...);
   }
 
   template <typename... Args>
   tl::optional<NamespacedDefinition> resolve_path (const AST::TypePath &path,
                                                   Args &&...args)
   {
-    return resolve_path (path.get_segments (),
-                        path.has_opening_scope_resolution_op (),
-                        std::forward<Args> (args)...);
+    auto util_path = UtilPath<std::unique_ptr<AST::TypePathSegment>> (
+      path.get_segments (), path.has_opening_scope_resolution_op ());
+    return resolve_path (util_path, std::forward<Args> (args)...);
   }
 
   /*
diff --git a/gcc/rust/util/rust-util-path.h b/gcc/rust/util/rust-util-path.h
new file mode 100644
index 000000000..f612afd9f
--- /dev/null
+++ b/gcc/rust/util/rust-util-path.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2026 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-system.h"
+
+#ifndef RUST_UTIL_PATH_H
+#define RUST_UTIL_PATH_H
+
+// Simple path container class to keep segments and opening scope flag together
+// whilst keeping the segment type generic.
+//
+// Only meant as a tuple for path elements with a name and a proper type.
+template <typename Segment> struct UtilPath
+{
+  UtilPath (const std::vector<Segment> &segments, bool opening_scope)
+    : segments (segments), opening_scope (opening_scope)
+  {}
+
+  const std::vector<Segment> &segments;
+  bool opening_scope;
+
+  bool has_opening_scope () const { return opening_scope; }
+  const std::vector<Segment> &get_segments () const { return segments; }
+};
+
+#endif

base-commit: 4bad9e6144dd3fe867919aeb75a63e790f985087
-- 
2.56.0

Reply via email to