aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorOwen Avery <powerboat9.gamer@gmail.com>2025-01-22 20:12:46 -0500
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-24 13:07:03 +0100
commitbbf31f8f5a6da20090ae2a5126854e0cf96b9253 (patch)
tree89e05ffad2b9f47b7f64bfc1762c4d25b8baa66b /gcc/rust
parentd9a21c1875110711159cc435124493849343532a (diff)
downloadgcc-bbf31f8f5a6da20090ae2a5126854e0cf96b9253.zip
gcc-bbf31f8f5a6da20090ae2a5126854e0cf96b9253.tar.gz
gcc-bbf31f8f5a6da20090ae2a5126854e0cf96b9253.tar.bz2
gccrs: nr2.0: Resolve instances of TypePath more accurately
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.gamer@gmail.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx20
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc31
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h6
-rw-r--r--gcc/rust/util/rust-unwrap-segment.cc41
-rw-r--r--gcc/rust/util/rust-unwrap-segment.h102
6 files changed, 170 insertions, 31 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 2405453..dc03a72 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 f5f0b15..b51da51 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 0b591730..c134ca0 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 b4d6859..a381411 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 0000000..38ff273
--- /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 0000000..4a3838a
--- /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