diff options
author | Owen Avery <powerboat9.gamer@gmail.com> | 2025-01-04 14:59:54 -0500 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2025-02-03 11:44:49 +0000 |
commit | 668c3bf7b7b45f8cea7a09515b6420cece877881 (patch) | |
tree | 2d7394f4c305d28719615b6d84293337b388fbb9 /gcc/rust | |
parent | a4a3183322dc195b3f235618d28ddca3e320a5fa (diff) | |
download | gcc-668c3bf7b7b45f8cea7a09515b6420cece877881.zip gcc-668c3bf7b7b45f8cea7a09515b6420cece877881.tar.gz gcc-668c3bf7b7b45f8cea7a09515b6420cece877881.tar.bz2 |
Fix bug in type resolution of paths
gcc/rust/ChangeLog:
* resolve/rust-early-name-resolver-2.0.cc
(Early::resolve_glob_import): Use
NameResolutionContext::resolve_path instead of
ForeverStack::resolve_path.
(Early::visit): Likewise.
(Early::visit_attributes): Likewise.
* resolve/rust-early-name-resolver-2.0.h
(Early::resolve_path_in_all_ns): Likewise.
* resolve/rust-late-name-resolver-2.0.cc
(Late::visit): Likewise, insert segment resolutions not
handled by NameResolutionContext::resolve_path, and avoid throwing
an error when path resolution could be finished by the typechecker.
* resolve/rust-name-resolution-context.h
(NameResolutionContext::resolve_path): Add.
* typecheck/rust-hir-type-check-path.cc
(TypeCheckExpr::resolve_root_path): Use segment node ids instead
of the path node id to look up segment resolutions when using
the 2.0 resolver, as is done with the 1.0 resolver.
* typecheck/rust-hir-type-check-type.cc
(TypeCheckType::resolve_root_path): Likewise.
* resolve/rust-forever-stack.h
(ForeverStack::resolve_path): Add callback parameter for
inserting segment resolutions.
(ForeverStack::find_starting_point): Likewise.
(ForeverStack::resolve_segments): Likewise.
* resolve/rust-forever-stack.hxx
(ForeverStack::find_starting_point): Likewise.
(ForeverStack::resolve_segments): Likewise.
(ForeverStack::resolve_path): Likewise and avoid resolving
inside TraitOrImpl ribs.
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/resolve/rust-early-name-resolver-2.0.cc | 13 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-early-name-resolver-2.0.h | 9 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-forever-stack.h | 18 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-forever-stack.hxx | 48 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 36 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-name-resolution-context.h | 40 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-path.cc | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.cc | 2 |
8 files changed, 128 insertions, 43 deletions
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index ae02a17..cdd8d16 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -74,7 +74,8 @@ Early::go (AST::Crate &crate) bool Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob) { - auto resolved = ctx.types.resolve_path (glob.to_resolve.get_segments ()); + auto resolved + = ctx.resolve_path (glob.to_resolve.get_segments (), Namespace::Types); if (!resolved.has_value ()) return false; @@ -259,7 +260,7 @@ Early::visit (AST::MacroInvocation &invoc) // we won't have changed `definition` from `nullopt` if there are more // than one segments in our path if (!definition.has_value ()) - definition = ctx.macros.resolve_path (path.get_segments ()); + definition = ctx.resolve_path (path.get_segments (), Namespace::Macros); // if the definition still does not have a value, then it's an error if (!definition.has_value ()) @@ -300,8 +301,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto traits = attr.get_traits_to_derive (); for (auto &trait : traits) { - auto definition - = ctx.macros.resolve_path (trait.get ().get_segments ()); + auto definition = ctx.resolve_path (trait.get ().get_segments (), + Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -324,8 +325,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) ->lookup_builtin (name) .is_error ()) // Do not resolve builtins { - auto definition - = ctx.macros.resolve_path (attr.get_path ().get_segments ()); + auto definition = ctx.resolve_path (attr.get_path ().get_segments (), + Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index dd199cc..de14d3c 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -227,9 +227,12 @@ private: }; }; - ctx.values.resolve_path (segments).map (pair_with_ns (Namespace::Values)); - ctx.types.resolve_path (segments).map (pair_with_ns (Namespace::Types)); - ctx.macros.resolve_path (segments).map (pair_with_ns (Namespace::Macros)); + ctx.resolve_path (segments, Namespace::Values) + .map (pair_with_ns (Namespace::Values)); + ctx.resolve_path (segments, Namespace::Types) + .map (pair_with_ns (Namespace::Types)); + ctx.resolve_path (segments, Namespace::Macros) + .map (pair_with_ns (Namespace::Macros)); return resolved; } diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 278c1a8..7bfe651 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -661,7 +661,9 @@ public: * current map, an empty one otherwise. */ template <typename S> - tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments); + tl::optional<Rib::Definition> resolve_path ( + const std::vector<S> &segments, + std::function<void (const S &, NodeId)> insert_segment_resolution); // FIXME: Documentation tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const; @@ -764,14 +766,16 @@ private: Node &find_closest_module (Node &starting_point); template <typename S> - tl::optional<SegIterator<S>> - find_starting_point (const std::vector<S> &segments, - std::reference_wrapper<Node> &starting_point); + tl::optional<SegIterator<S>> find_starting_point ( + const std::vector<S> &segments, + std::reference_wrapper<Node> &starting_point, + std::function<void (const S &, NodeId)> insert_segment_resolution); template <typename S> - tl::optional<Node &> resolve_segments (Node &starting_point, - const std::vector<S> &segments, - SegIterator<S> iterator); + tl::optional<Node &> resolve_segments ( + Node &starting_point, const std::vector<S> &segments, + SegIterator<S> iterator, + std::function<void (const S &, NodeId)> insert_segment_resolution); /* Helper functions for forward resolution (to_canonical_path, to_rib...) */ struct DfsResult diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index be05f52..57bd0bb 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -375,7 +375,8 @@ template <Namespace N> template <typename S> tl::optional<typename std::vector<S>::const_iterator> ForeverStack<N>::find_starting_point ( - const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point) + const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point, + std::function<void (const S &, NodeId)> insert_segment_resolution) { auto iterator = segments.begin (); @@ -401,12 +402,19 @@ ForeverStack<N>::find_starting_point ( if (seg.is_crate_path_seg ()) { starting_point = root; + // TODO: is this how we should be getting the crate node id? + auto &mappings = Analysis::Mappings::get (); + NodeId current_crate + = *mappings.crate_num_to_nodeid (mappings.get_current_crate ()); + + insert_segment_resolution (seg, current_crate); iterator++; break; } if (seg.is_lower_self_seg ()) { - // do nothing and exit + // insert segment resolution and exit + insert_segment_resolution (seg, starting_point.get ().id); iterator++; break; } @@ -421,6 +429,8 @@ ForeverStack<N>::find_starting_point ( starting_point = find_closest_module (starting_point.get ().parent.value ()); + + insert_segment_resolution (seg, starting_point.get ().id); continue; } @@ -438,7 +448,8 @@ template <typename S> tl::optional<typename ForeverStack<N>::Node &> ForeverStack<N>::resolve_segments ( Node &starting_point, const std::vector<S> &segments, - typename std::vector<S>::const_iterator iterator) + typename std::vector<S>::const_iterator iterator, + std::function<void (const S &, NodeId)> insert_segment_resolution) { auto *current_node = &starting_point; for (; !is_last (iterator, segments); iterator++) @@ -479,6 +490,7 @@ ForeverStack<N>::resolve_segments ( } current_node = &child.value (); + insert_segment_resolution (seg, current_node->id); } return *current_node; @@ -487,23 +499,39 @@ ForeverStack<N>::resolve_segments ( template <Namespace N> template <typename S> tl::optional<Rib::Definition> -ForeverStack<N>::resolve_path (const std::vector<S> &segments) +ForeverStack<N>::resolve_path ( + const std::vector<S> &segments, + std::function<void (const S &, NodeId)> insert_segment_resolution) { // TODO: What to do if segments.empty() ? // if there's only one segment, we just use `get` if (segments.size () == 1) - return get (segments.back ().as_string ()); + { + auto res = get (segments.back ().as_string ()); + if (res && !res->is_ambiguous ()) + insert_segment_resolution (segments.back (), res->get_node_id ()); + return res; + } std::reference_wrapper<Node> starting_point = cursor (); - return find_starting_point (segments, starting_point) - .and_then ([this, &segments, &starting_point] ( + return find_starting_point (segments, starting_point, + insert_segment_resolution) + .and_then ([this, &segments, &starting_point, &insert_segment_resolution] ( typename std::vector<S>::const_iterator iterator) { - return resolve_segments (starting_point.get (), segments, iterator); + return resolve_segments (starting_point.get (), segments, iterator, + insert_segment_resolution); }) - .and_then ([&segments] (Node final_node) { - return final_node.rib.get (segments.back ().as_string ()); + .and_then ([&segments, &insert_segment_resolution] ( + Node final_node) -> tl::optional<Rib::Definition> { + // 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 ()); + 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 a0c3a05..8ed3053 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -263,16 +263,15 @@ Late::visit (AST::PathInExpression &expr) return; } - auto resolved - = ctx.values.resolve_path (expr.get_segments ()).or_else ([&] () { - return ctx.types.resolve_path (expr.get_segments ()); - }); + auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values, + Namespace::Types); if (!resolved) { - rust_error_at (expr.get_locus (), - "could not resolve path expression: %qs", - expr.as_simple_path ().as_string ().c_str ()); + if (!ctx.lookup (expr.get_segments ().front ().get_node_id ())) + rust_error_at (expr.get_locus (), + "could not resolve path expression: %qs", + expr.as_simple_path ().as_string ().c_str ()); return; } @@ -307,11 +306,17 @@ Late::visit (AST::TypePath &type) auto values = ctx.types.peek ().get_values (); 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_node_id ()), + Definition (resolved->get_node_id ())); + ctx.map_usage (Usage (type.get_segments ().back ()->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", + str.c_str ()); + } DefaultResolver::visit (type); } @@ -339,7 +344,8 @@ Late::visit (AST::StructStruct &s) void Late::visit (AST::StructExprStruct &s) { - auto resolved = ctx.types.resolve_path (s.get_struct_name ().get_segments ()); + auto resolved + = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); @@ -348,7 +354,8 @@ Late::visit (AST::StructExprStruct &s) void Late::visit (AST::StructExprStructBase &s) { - auto resolved = ctx.types.resolve_path (s.get_struct_name ().get_segments ()); + auto resolved + = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); @@ -358,7 +365,8 @@ Late::visit (AST::StructExprStructBase &s) void Late::visit (AST::StructExprStructFields &s) { - auto resolved = ctx.types.resolve_path (s.get_struct_name ().get_segments ()); + auto resolved + = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 44d7da7..bd03ff9 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -216,6 +216,46 @@ public: tl::optional<NodeId> lookup (NodeId usage) const; + template <typename S> + tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments, + Namespace ns) + { + 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)); + }; + switch (ns) + { + case Namespace::Values: + return values.resolve_path (segments, insert_segment_resolution); + case Namespace::Types: + return types.resolve_path (segments, insert_segment_resolution); + case Namespace::Macros: + return macros.resolve_path (segments, insert_segment_resolution); + case Namespace::Labels: + return labels.resolve_path (segments, insert_segment_resolution); + default: + rust_unreachable (); + } + } + + template <typename S, typename... Args> + tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments, + Args... ns_args) + { + std::initializer_list<Namespace> namespaces = {ns_args...}; + + for (auto ns : namespaces) + { + if (auto ret = resolve_path (segments, ns)) + return ret; + } + + return tl::nullopt; + } + private: /* Map of "usage" nodes which have been resolved to a "definition" node */ std::map<Usage, Definition> resolved_nodes; diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index a489490..a4f294b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -274,8 +274,9 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); // assign the ref_node_id if we've found something - nr_ctx.lookup (expr.get_mappings ().get_nodeid ()) - .map ([&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); + nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) { + ref_node_id = resolved; + }); } else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) resolver->lookup_resolved_type (ast_node_id, &ref_node_id); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 55c5934..6dc62d6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -403,7 +403,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, .resolver (); // assign the ref_node_id if we've found something - nr_ctx.lookup (path.get_mappings ().get_nodeid ()) + nr_ctx.lookup (ast_node_id) .map ( [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); } |