diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 24bbf3c292a..70cd64a2e94 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 57bd0bba650..a628c61aa08 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::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::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::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::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::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::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::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 8ed30532583..59cac8d02b7 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` 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 bd03ff92445..19b943623b5 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -222,9 +222,9 @@ class NameResolutionContext { std::function 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 +// . + +#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 +// . + +#include + +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 (); } +}; + +/* + * 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 +NodeId +unwrap_segment_node_id (const std::unique_ptr &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