Skip to content

Commit

Permalink
nr2.0: Resolve instances of TypePath more accurately
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
powerboat9 authored and P-E-P committed Feb 4, 2025
1 parent e7306a9 commit ca227ed
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 36 deletions.
1 change: 1 addition & 0 deletions gcc/rust/Make-lang.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
20 changes: 12 additions & 8 deletions gcc/rust/resolve/rust-forever-stack.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 ();

Expand All @@ -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;
}
Expand All @@ -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;
}

Expand All @@ -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 ());

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
31 changes: 11 additions & 20 deletions gcc/rust/resolve/rust-late-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
6 changes: 3 additions & 3 deletions gcc/rust/resolve/rust-name-resolution-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ class NameResolutionContext
{
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)
{
Expand Down
41 changes: 41 additions & 0 deletions gcc/rust/util/rust-unwrap-segment.cc
Original file line number Diff line number Diff line change
@@ -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
102 changes: 102 additions & 0 deletions gcc/rust/util/rust-unwrap-segment.h
Original file line number Diff line number Diff line change
@@ -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
5 changes: 0 additions & 5 deletions gcc/testsuite/rust/compile/nr2/exclude
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit ca227ed

Please sign in to comment.