From: Owen Avery <powerboat9.ga...@gmail.com>

gcc/rust/ChangeLog:

        * util/rust-unwrap-segment.cc: New file.
        * util/rust-unwrap-segment.h: New file.
        * Make-lang.in: Add rust-unwrap-segment.o to the object list.
        * resolve/rust-forever-stack.hxx: Include rust-unwrap-segment.h.
        (ForeverStack::find_starting_point): Use unwrap_type_segment.
        (ForeverStack::resolve_segments): Likewise.
        (ForeverStack::resolve_path): Likewise.
        * resolve/rust-late-name-resolver-2.0.cc
        (Late::visit): Resolve type paths using
        NameResolutionContext::resolve_path.
        * resolve/rust-name-resolution-context.h
        (NameResolutionContext::resolve_path): Use
        unwrap_segment_node_id.

gcc/testsuite/ChangeLog:

        * rust/compile/nr2/exclude: Remove entries.

Signed-off-by: Owen Avery <powerboat9.ga...@gmail.com>
---
 gcc/rust/Make-lang.in                         |   1 +
 gcc/rust/resolve/rust-forever-stack.hxx       |  20 ++--
 .../resolve/rust-late-name-resolver-2.0.cc    |  31 ++----
 .../resolve/rust-name-resolution-context.h    |   6 +-
 gcc/rust/util/rust-unwrap-segment.cc          |  41 +++++++
 gcc/rust/util/rust-unwrap-segment.h           | 102 ++++++++++++++++++
 gcc/testsuite/rust/compile/nr2/exclude        |   5 -
 7 files changed, 170 insertions(+), 36 deletions(-)
 create mode 100644 gcc/rust/util/rust-unwrap-segment.cc
 create mode 100644 gcc/rust/util/rust-unwrap-segment.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 24054531d9e..dc03a72ec78 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -231,6 +231,7 @@ GRS_OBJS = \
     rust/rust-dir-owner.o \
     rust/rust-unicode.o \
     rust/rust-punycode.o \
+    rust/rust-unwrap-segment.o \
        rust/rust-expand-format-args.o \
        rust/rust-lang-item.o \
        rust/rust-collect-lang-items.o \
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index f5f0b15c00b..b51da51948f 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -21,6 +21,7 @@
 #include "rust-diagnostics.h"
 #include "rust-forever-stack.h"
 #include "rust-rib.h"
+#include "rust-unwrap-segment.h"
 #include "optional.h"
 
 namespace Rust {
@@ -389,7 +390,8 @@ ForeverStack<N>::find_starting_point (
 
   for (; !is_last (iterator, segments); iterator++)
     {
-      auto &seg = *iterator;
+      auto &outer_seg = *iterator;
+      auto &seg = unwrap_type_segment (outer_seg);
       auto is_self_or_crate
        = seg.is_crate_path_seg () || seg.is_lower_self_seg ();
 
@@ -407,14 +409,14 @@ ForeverStack<N>::find_starting_point (
          NodeId current_crate
            = *mappings.crate_num_to_nodeid (mappings.get_current_crate ());
 
-         insert_segment_resolution (seg, current_crate);
+         insert_segment_resolution (outer_seg, current_crate);
          iterator++;
          break;
        }
       if (seg.is_lower_self_seg ())
        {
          // insert segment resolution and exit
-         insert_segment_resolution (seg, starting_point.get ().id);
+         insert_segment_resolution (outer_seg, starting_point.get ().id);
          iterator++;
          break;
        }
@@ -430,7 +432,7 @@ ForeverStack<N>::find_starting_point (
          starting_point
            = find_closest_module (starting_point.get ().parent.value ());
 
-         insert_segment_resolution (seg, starting_point.get ().id);
+         insert_segment_resolution (outer_seg, starting_point.get ().id);
          continue;
        }
 
@@ -454,7 +456,8 @@ ForeverStack<N>::resolve_segments (
   auto *current_node = &starting_point;
   for (; !is_last (iterator, segments); iterator++)
     {
-      auto &seg = *iterator;
+      auto &outer_seg = *iterator;
+      auto &seg = unwrap_type_segment (outer_seg);
       auto str = seg.as_string ();
       rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ());
 
@@ -490,7 +493,7 @@ ForeverStack<N>::resolve_segments (
        }
 
       current_node = &child.value ();
-      insert_segment_resolution (seg, current_node->id);
+      insert_segment_resolution (outer_seg, current_node->id);
     }
 
   return *current_node;
@@ -508,7 +511,7 @@ ForeverStack<N>::resolve_path (
   // if there's only one segment, we just use `get`
   if (segments.size () == 1)
     {
-      auto res = get (segments.back ().as_string ());
+      auto res = get (unwrap_type_segment (segments.back ()).as_string ());
       if (res && !res->is_ambiguous ())
        insert_segment_resolution (segments.back (), res->get_node_id ());
       return res;
@@ -528,7 +531,8 @@ ForeverStack<N>::resolve_path (
       // leave resolution within impl blocks to type checker
       if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
        return tl::nullopt;
-      auto res = final_node.rib.get (segments.back ().as_string ());
+      auto res = final_node.rib.get (
+       unwrap_type_segment (segments.back ()).as_string ());
       if (res && !res->is_ambiguous ())
        insert_segment_resolution (segments.back (), res->get_node_id ());
       return res;
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 0b591730824..c134ca03336 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -294,29 +294,20 @@ Late::visit (AST::TypePath &type)
   // maybe we can overload `resolve_path<Namespace::Types>` to only do
   // typepath-like path resolution? that sounds good
 
-  if (type.get_segments ().size () != 1)
-    {
-      rust_sorry_at (
-       type.get_locus (),
-       "name resolution 2.0 cannot resolve multi-segment type paths");
-      return;
-    }
+  // take care of only simple cases
+  // TODO: remove this?
+  rust_assert (!type.has_opening_scope_resolution_op ());
 
-  auto str = type.get_segments ().back ()->get_ident_segment ().as_string ();
-  auto values = ctx.types.peek ().get_values ();
+  // this *should* mostly work
+  // TODO: make sure typepath-like path resolution (?) is working
+  auto resolved = ctx.resolve_path (type.get_segments (), Namespace::Types);
 
-  if (auto resolved = ctx.types.get (str))
-    {
-      ctx.map_usage (Usage (type.get_node_id ()),
-                    Definition (resolved->get_node_id ()));
-      ctx.map_usage (Usage (type.get_segments ().back ()->get_node_id ()),
-                    Definition (resolved->get_node_id ()));
-    }
+  if (resolved.has_value ())
+    ctx.map_usage (Usage (type.get_node_id ()),
+                  Definition (resolved->get_node_id ()));
   else
-    {
-      rust_error_at (type.get_locus (), "could not resolve type path %qs",
-                    str.c_str ());
-    }
+    rust_error_at (type.get_locus (), "could not resolve type path %qs",
+                  type.as_string ().c_str ());
 
   DefaultResolver::visit (type);
 }
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index b4d68593631..a381411514d 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -222,9 +222,9 @@ public:
   {
     std::function<void (const S &, NodeId)> insert_segment_resolution
       = [this] (const S &seg, NodeId id) {
-         if (resolved_nodes.find (Usage (seg.get_node_id ()))
-             == resolved_nodes.end ())
-           map_usage (Usage (seg.get_node_id ()), Definition (id));
+         auto seg_id = unwrap_segment_node_id (seg);
+         if (resolved_nodes.find (Usage (seg_id)) == resolved_nodes.end ())
+           map_usage (Usage (seg_id), Definition (id));
        };
     switch (ns)
       {
diff --git a/gcc/rust/util/rust-unwrap-segment.cc 
b/gcc/rust/util/rust-unwrap-segment.cc
new file mode 100644
index 00000000000..38ff273fc06
--- /dev/null
+++ b/gcc/rust/util/rust-unwrap-segment.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2025 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 "ast/rust-path.h"
+
+namespace Rust {
+
+NodeId
+unwrap_segment_node_id (const AST::TypePathSegment &seg)
+{
+  return seg.get_node_id ();
+}
+
+NodeId
+unwrap_segment_node_id (const AST::SimplePathSegment &seg)
+{
+  return seg.get_node_id ();
+}
+
+NodeId
+unwrap_segment_node_id (const AST::PathExprSegment &seg)
+{
+  return seg.get_node_id ();
+}
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-unwrap-segment.h 
b/gcc/rust/util/rust-unwrap-segment.h
new file mode 100644
index 00000000000..4a3838a407a
--- /dev/null
+++ b/gcc/rust/util/rust-unwrap-segment.h
@@ -0,0 +1,102 @@
+// Copyright (C) 2025 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 <ast/rust-ast-full-decls.h>
+
+namespace Rust {
+
+/*
+ * Used to convert different path segment object references
+ * into SimplePathSegment/PathIdentSegment references
+ *
+ * unwrap_type_segment:
+ *   expands to a call to unwrap_type_segment_inner::unwrap,
+ *   used for type inference
+ */
+#define unwrap_type_segment(x)                                                 
\
+  (unwrap_type_segment_inner<typename std::remove_const<                       
\
+     typename std::remove_reference<decltype (x)>::type>::type>::unwrap (x))
+
+template <class T> class unwrap_type_segment_inner;
+
+/* base case */
+template <> class unwrap_type_segment_inner<AST::SimplePathSegment>
+{
+public:
+  /* The return type of unwrap */
+  using ret = AST::SimplePathSegment;
+
+  /* non-const qualified unwrap */
+  static AST::SimplePathSegment &unwrap (AST::SimplePathSegment &x)
+  {
+    return x;
+  }
+
+  /* const qualified unwrap */
+  static const AST::SimplePathSegment &unwrap (const AST::SimplePathSegment &x)
+  {
+    return x;
+  }
+};
+
+/* case which dereferences unique_ptr */
+template <class T> class unwrap_type_segment_inner<std::unique_ptr<T>>
+{
+public:
+  using ret = typename unwrap_type_segment_inner<T>::ret;
+
+  static ret &unwrap (std::unique_ptr<T> &x)
+  {
+    return unwrap_type_segment (*x);
+  }
+  static const ret &unwrap (const std::unique_ptr<T> &x)
+  {
+    return unwrap_type_segment (*x);
+  }
+};
+
+/* case which handles objects with a get_ident_segment member function */
+template <class T> class unwrap_type_segment_inner
+{
+public:
+  using ret = AST::PathIdentSegment;
+
+  static ret &unwrap (T &x) { return x.get_ident_segment (); }
+  static const ret &unwrap (const T &x) { return x.get_ident_segment (); }
+};
+
+/*
+ * Used to get the node id of a path segment object
+ */
+NodeId
+unwrap_segment_node_id (const AST::TypePathSegment &seg);
+
+NodeId
+unwrap_segment_node_id (const AST::SimplePathSegment &seg);
+
+NodeId
+unwrap_segment_node_id (const AST::PathExprSegment &seg);
+
+template <class T>
+NodeId
+unwrap_segment_node_id (const std::unique_ptr<T> &ptr)
+{
+  return unwrap_segment_node_id (*ptr);
+}
+
+} // namespace Rust
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index 1b34e9fe20e..2d9cb76b27d 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -13,7 +13,6 @@ expected_type_args2.rs
 feature_rust_attri0.rs
 format_args_basic_expansion.rs
 generic-default1.rs
-generics1.rs
 generics3.rs
 generics4.rs
 generics5.rs
@@ -37,7 +36,6 @@ issue-2330.rs
 issue-2479.rs
 issue-2723-1.rs
 issue-2723-2.rs
-issue-2772-2.rs
 issue-2775.rs
 issue-2782.rs
 issue-2812.rs
@@ -59,8 +57,6 @@ nested_macro_use1.rs
 nested_macro_use2.rs
 nested_macro_use3.rs
 not_find_value_in_scope.rs
-parse_complex_generic_application.rs
-path_as_generic_arg.rs
 pattern-struct.rs
 privacy4.rs
 privacy5.rs
@@ -80,7 +76,6 @@ struct-expr-parse.rs
 traits3.rs
 traits6.rs
 traits7.rs
-type-bindings1.rs
 undeclared_label.rs
 use_1.rs
 v0-mangle1.rs
-- 
2.45.2

Reply via email to