From aae4adba62bff1d2c25cb4a2f7e4cf3470517745 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 22 Jan 2025 20:12:46 -0500 Subject: [PATCH] nr2.0: Resolve instances of TypePath more accurately gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx: Include rust-unwrap-segment.h. (ForeverStack::find_starting_point): Use unwrap_segment. (ForeverStack::resolve_segments): Likewise. (ForeverStack::resolve_path): Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use ForeverStack::resolve_path to resolve type paths. * util/rust-unwrap-segment.h: New file. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery --- gcc/rust/resolve/rust-forever-stack.hxx | 10 ++- .../resolve/rust-late-name-resolver-2.0.cc | 19 ++--- gcc/rust/util/rust-unwrap-segment.h | 81 +++++++++++++++++++ gcc/testsuite/rust/compile/nr2/exclude | 4 - 4 files changed, 95 insertions(+), 19 deletions(-) create mode 100644 gcc/rust/util/rust-unwrap-segment.h diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 6181c05fc6c5..048b125642de 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 { @@ -388,7 +389,7 @@ ForeverStack::find_starting_point ( for (; !is_last (iterator, segments); iterator++) { - auto &seg = *iterator; + auto &seg = unwrap_type_segment (*iterator); auto is_self_or_crate = seg.is_crate_path_seg () || seg.is_lower_self_seg (); @@ -443,7 +444,7 @@ ForeverStack::resolve_segments ( auto *current_node = &starting_point; for (; !is_last (iterator, segments); iterator++) { - auto &seg = *iterator; + auto &seg = unwrap_type_segment (*iterator); auto str = seg.as_string (); rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ()); @@ -493,7 +494,7 @@ ForeverStack::resolve_path (const std::vector &segments) // if there's only one segment, we just use `get` if (segments.size () == 1) - return get (segments.back ().as_string ()); + return get (unwrap_type_segment (segments.back ()).as_string ()); std::reference_wrapper starting_point = cursor (); @@ -503,7 +504,8 @@ ForeverStack::resolve_path (const std::vector &segments) return resolve_segments (starting_point.get (), segments, iterator); }) .and_then ([&segments] (Node final_node) { - return final_node.rib.get (segments.back ().as_string ()); + return final_node.rib.get ( + unwrap_type_segment (segments.back ()).as_string ()); }); } 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 7c6948565202..41c361c899ae 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -287,23 +287,20 @@ Late::visit (AST::TypePath &type) // maybe we can overload `resolve_path` 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.types.resolve_path (type.get_segments ()); - if (auto resolved = ctx.types.get (str)) + 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 ()); + type.as_string ().c_str ()); DefaultResolver::visit (type); } diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h new file mode 100644 index 000000000000..a18a821cc969 --- /dev/null +++ b/gcc/rust/util/rust-unwrap-segment.h @@ -0,0 +1,81 @@ +// 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 +// . + +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::type>::type>::unwrap (x)) + +template class unwrap_type_segment_inner; + +/* base case */ +template <> class unwrap_type_segment_inner +{ +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 unwrap_type_segment_inner> +{ +public: + using ret = typename unwrap_type_segment_inner::ret; + + static ret &unwrap (std::unique_ptr &x) + { + return unwrap_type_segment (*x); + } + static const ret &unwrap (const std::unique_ptr &x) + { + return unwrap_type_segment (*x); + } +}; + +/* case which handles objects with a get_ident_segment member function */ +template 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 (); } +}; + +} // namespace Rust diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 5cc7cf7d64c5..1ef560d00e1b 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -6,7 +6,6 @@ cfg3.rs cfg4.rs cfg5.rs closure_no_type_anno.rs -complex-path1.rs const-issue1440.rs const_generics_3.rs const_generics_4.rs @@ -18,7 +17,6 @@ expected_type_args2.rs feature_rust_attri0.rs format_args_basic_expansion.rs generic-default1.rs -generics1.rs generics10.rs generics11.rs generics3.rs @@ -47,7 +45,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 @@ -111,7 +108,6 @@ struct-expr-parse.rs traits3.rs traits6.rs traits7.rs -type-bindings1.rs unconstrained_type_param.rs undeclared_label.rs use_1.rs