diff options
author | Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> | 2024-03-21 19:25:52 +0100 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-08-01 16:52:28 +0200 |
commit | c083906944bc458c8ae4bc27956772c11db77785 (patch) | |
tree | d63b9866902ddfc37ebea8fc9843576752cca80c /gcc/rust/resolve | |
parent | e126c71b36b03276957f36745bf6f8303833b751 (diff) | |
download | gcc-c083906944bc458c8ae4bc27956772c11db77785.zip gcc-c083906944bc458c8ae4bc27956772c11db77785.tar.gz gcc-c083906944bc458c8ae4bc27956772c11db77785.tar.bz2 |
gccrs: Fix use rebind name resolution.
Name resolution for rebind were missing.
gcc/rust/ChangeLog:
* resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::handle_use_glob):
Change function prototype to use a reference instead.
(TopLevel::handle_use_dec): Likewise.
(TopLevel::handle_rebind): Add name resolution on rebind use
declarations.
(flatten_rebind): Change prototype to accept a pair of path/alias.
(flatten_list): Adapt call to flatten_rebind.
(flatten): Adapt call to flatten_rebind.
(flatten_glob): Remove unused part.
(TopLevel::visit): Add rebind resolution.
* resolve/rust-toplevel-name-resolver-2.0.h: Adapt function prototypes.
Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 194 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h | 5 |
2 files changed, 151 insertions, 48 deletions
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index e6da8db..4593c67 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-toplevel-name-resolver-2.0.h" +#include "input.h" #include "optional.h" #include "rust-ast-full.h" #include "rust-hir-map.h" @@ -434,7 +435,7 @@ TopLevel::visit (AST::ConstantItem &const_item) } bool -TopLevel::handle_use_glob (AST::SimplePath glob) +TopLevel::handle_use_glob (AST::SimplePath &glob) { auto resolved = ctx.types.resolve_path (glob.get_segments ()); if (!resolved.has_value ()) @@ -453,7 +454,7 @@ TopLevel::handle_use_glob (AST::SimplePath glob) } bool -TopLevel::handle_use_dec (AST::SimplePath path) +TopLevel::handle_use_dec (AST::SimplePath &path) { auto locus = path.get_final_segment ().get_locus (); auto declared_name = path.get_final_segment ().as_string (); @@ -508,6 +509,97 @@ TopLevel::handle_use_dec (AST::SimplePath path) }); }; + resolve_and_insert (Namespace::Values, path); + resolve_and_insert (Namespace::Types, path); + resolve_and_insert (Namespace::Macros, path); + + return found; +} + +bool +TopLevel::handle_rebind (std::pair<AST::SimplePath, AST::UseTreeRebind> &rebind) +{ + auto &path = rebind.first; + + location_t locus = UNKNOWN_LOCATION; + std::string declared_name; + + switch (rebind.second.get_new_bind_type ()) + { + case AST::UseTreeRebind::NewBindType::IDENTIFIER: + declared_name = rebind.second.get_identifier ().as_string (); + locus = rebind.second.get_identifier ().get_locus (); + break; + case AST::UseTreeRebind::NewBindType::NONE: + declared_name = path.get_final_segment ().as_string (); + locus = path.get_final_segment ().get_locus (); + break; + case AST::UseTreeRebind::NewBindType::WILDCARD: + rust_unreachable (); + break; + } + + // in what namespace do we perform path resolution? All + // of them? see which one matches? Error out on + // ambiguities? so, apparently, for each one that + // matches, add it to the proper namespace + // :( + auto found = false; + + auto resolve_and_insert = [this, &found, &declared_name, + locus] (Namespace ns, + const AST::SimplePath &path) { + tl::optional<Rib::Definition> resolved = tl::nullopt; + tl::optional<Rib::Definition> resolved_bind = tl::nullopt; + + std::vector<AST::SimplePathSegment> declaration_v + = {AST::SimplePathSegment (declared_name, locus)}; + // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so + // that we can improve it with hints or location or w/ever. and maybe + // only emit it the first time. + switch (ns) + { + case Namespace::Values: + resolved = ctx.values.resolve_path (path.get_segments ()); + resolved_bind = ctx.values.resolve_path (declaration_v); + break; + case Namespace::Types: + resolved = ctx.types.resolve_path (path.get_segments ()); + resolved_bind = ctx.types.resolve_path (declaration_v); + break; + case Namespace::Macros: + resolved = ctx.macros.resolve_path (path.get_segments ()); + resolved_bind = ctx.macros.resolve_path (declaration_v); + break; + case Namespace::Labels: + // TODO: Is that okay? + rust_unreachable (); + } + + resolved.map ([this, &found, &declared_name, locus, ns, path, + &resolved_bind] (Rib::Definition def) { + found = true; + + insert_or_error_out (declared_name, locus, def.get_node_id (), ns); + if (resolved_bind.has_value ()) + { + auto bind_def = resolved_bind.value (); + // what do we do with the id? + auto result = node_forwarding.find (bind_def.get_node_id ()); + if (result != node_forwarding.cend () + && result->second != path.get_node_id ()) + rust_error_at (path.get_locus (), "%qs defined multiple times", + declared_name.c_str ()); + } + else + { + // No previous thing has inserted this into our scope + node_forwarding.insert ({def.get_node_id (), path.get_node_id ()}); + } + return def.get_node_id (); + }); + }; + // do this for all namespaces (even Labels?) resolve_and_insert (Namespace::Values, path); @@ -520,31 +612,38 @@ TopLevel::handle_use_dec (AST::SimplePath path) } static void -flatten_rebind (const AST::UseTreeRebind &glob, - std::vector<AST::SimplePath> &paths); +flatten_rebind ( + const AST::UseTreeRebind &glob, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths); + static void -flatten_list (const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths, - std::vector<AST::SimplePath> &glob_paths, - NameResolutionContext &ctx); +flatten_list ( + const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths, + std::vector<AST::SimplePath> &glob_paths, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths, + NameResolutionContext &ctx); static void flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &glob_paths, NameResolutionContext &ctx); static void -flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths, - std::vector<AST::SimplePath> &glob_paths, NameResolutionContext &ctx) +flatten ( + const AST::UseTree *tree, std::vector<AST::SimplePath> &paths, + std::vector<AST::SimplePath> &glob_paths, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths, + NameResolutionContext &ctx) { switch (tree->get_kind ()) { case AST::UseTree::Rebind: { auto rebind = static_cast<const AST::UseTreeRebind *> (tree); - flatten_rebind (*rebind, paths); + flatten_rebind (*rebind, rebind_paths); break; } case AST::UseTree::List: { auto list = static_cast<const AST::UseTreeList *> (tree); - flatten_list (*list, paths, glob_paths, ctx); + flatten_list (*list, paths, glob_paths, rebind_paths, ctx); break; } case AST::UseTree::Glob: { @@ -557,27 +656,11 @@ flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths, } static void -flatten_rebind (const AST::UseTreeRebind &rebind, - std::vector<AST::SimplePath> &paths) +flatten_rebind ( + const AST::UseTreeRebind &rebind, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths) { - auto path = rebind.get_path (); - - // FIXME: Do we want to emplace the rebind here as well? - if (rebind.has_identifier ()) - { - auto rebind_path = path; - auto new_seg = rebind.get_identifier (); - - // Add the identifier as a new path - rebind_path.get_segments ().back () - = AST::SimplePathSegment (new_seg.as_string (), UNDEF_LOCATION); - - paths.emplace_back (rebind_path); - } - else - { - paths.emplace_back (path); - } + rebind_paths.emplace_back (rebind.get_path (), rebind); } /** Prefix a list of subpath @@ -599,9 +682,27 @@ prefix_subpaths (AST::SimplePath prefix, std::vector<AST::SimplePath> subs, } static void -flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths, - std::vector<AST::SimplePath> &glob_paths, - NameResolutionContext &ctx) +prefix_rebinds ( + AST::SimplePath prefix, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> subs, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &results) +{ + for (auto &sub : subs) + { + auto new_path = prefix; + std::copy (sub.first.get_segments ().begin (), + sub.first.get_segments ().end (), + std::back_inserter (new_path.get_segments ())); + results.emplace_back (std::make_pair (new_path, sub.second)); + } +} + +static void +flatten_list ( + const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths, + std::vector<AST::SimplePath> &glob_paths, + std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths, + NameResolutionContext &ctx) { auto prefix = AST::SimplePath::create_empty (); if (list.has_path ()) @@ -611,10 +712,13 @@ flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths, { auto sub_paths = std::vector<AST::SimplePath> (); auto sub_globs = std::vector<AST::SimplePath> (); - flatten (tree.get (), sub_paths, sub_globs, ctx); + auto sub_rebinds + = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> (); + flatten (tree.get (), sub_paths, sub_globs, sub_rebinds, ctx); prefix_subpaths (prefix, sub_paths, paths); prefix_subpaths (prefix, sub_globs, glob_paths); + prefix_rebinds (prefix, sub_rebinds, rebind_paths); } } @@ -624,16 +728,6 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths, { if (glob.has_path ()) paths.emplace_back (glob.get_path ()); - - // (PE): Get path rib - auto rib = ctx.values.resolve_path (glob.get_path ().get_segments ()) - .and_then ([&] (Rib::Definition def) { - return ctx.values.to_rib (def.get_node_id ()); - }); - if (rib.has_value ()) - { - auto value = rib.value ().get_values (); - } } void @@ -641,13 +735,15 @@ TopLevel::visit (AST::UseDeclaration &use) { auto paths = std::vector<AST::SimplePath> (); auto glob_path = std::vector<AST::SimplePath> (); + auto rebind_path + = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> (); // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup? // How do we handle module imports in general? Should they get added to all // namespaces? const auto &tree = use.get_tree (); - flatten (tree.get (), paths, glob_path, this->ctx); + flatten (tree.get (), paths, glob_path, rebind_path, this->ctx); for (auto &path : paths) if (!handle_use_dec (path)) @@ -658,6 +754,12 @@ TopLevel::visit (AST::UseDeclaration &use) if (!handle_use_glob (glob)) rust_error_at (glob.get_final_segment ().get_locus (), ErrorCode::E0433, "unresolved import %qs", glob.as_string ().c_str ()); + + for (auto &rebind : rebind_path) + if (!handle_rebind (rebind)) + rust_error_at (rebind.first.get_final_segment ().get_locus (), + ErrorCode::E0433, "unresolved import %qs", + rebind.first.as_string ().c_str ()); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index e226c79..fb16866 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -108,8 +108,9 @@ private: // Call this on all the paths of a UseDec - so each flattened path in a // UseTreeList for example // FIXME: Should that return `found`? - bool handle_use_dec (AST::SimplePath path); - bool handle_use_glob (AST::SimplePath glob); + bool handle_use_dec (AST::SimplePath &path); + bool handle_use_glob (AST::SimplePath &glob); + bool handle_rebind (std::pair<AST::SimplePath, AST::UseTreeRebind> &pair); void visit (AST::UseDeclaration &use) override; }; |