diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-04-04 17:07:54 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-03-19 15:32:12 +0100 |
commit | 333a4cbff7ef62208647c234af12caa35271b59c (patch) | |
tree | df096abd47cc2b4612162f15ecd16e8eec2fa925 /gcc/rust | |
parent | 2f743673232dc87b85e802ea5256a36bb1988172 (diff) | |
download | gcc-333a4cbff7ef62208647c234af12caa35271b59c.zip gcc-333a4cbff7ef62208647c234af12caa35271b59c.tar.gz gcc-333a4cbff7ef62208647c234af12caa35271b59c.tar.bz2 |
gccrs: imports: Add FinalizeImports class
gcc/rust/ChangeLog:
* Make-lang.in: Add new object file.
* ast/rust-item.h: Constify method.
* resolve/rust-early-name-resolver-2.0.cc (Early::go): Call into
the imports finalizer.
(Early::resolve_glob_import): Remove old resolution.
(Early::resolve_rebind_import): Likewise.
* resolve/rust-toplevel-name-resolver-2.0.cc (GlobbingVisitor::go):
New function.
(GlobbingVisitor::visit): Likewise.
(TopLevel::visit): Do not call into handle_use_* functions anymore.
* resolve/rust-toplevel-name-resolver-2.0.h (class GlobbingVisitor):
New.
* resolve/rust-finalize-imports-2.0.cc: New file.
* resolve/rust-finalize-imports-2.0.h: New file.
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 31 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-finalize-imports-2.0.cc | 206 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-finalize-imports-2.0.h | 96 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 112 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h | 25 |
7 files changed, 309 insertions, 164 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 950cd3a..c1a3c1f 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -131,6 +131,7 @@ GRS_OBJS = \ rust/rust-default-resolver.o \ rust/rust-toplevel-name-resolver-2.0.o \ rust/rust-early-name-resolver-2.0.o \ + rust/rust-finalize-imports-2.0.o \ rust/rust-late-name-resolver-2.0.o \ rust/rust-immutable-name-resolution-context.o \ rust/rust-early-name-resolver.o \ diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index bd9113f..2ae7c44 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1213,7 +1213,7 @@ public: std::string as_string () const override; - NewBindType get_new_bind_type () { return bind_type; } + NewBindType get_new_bind_type () const { return bind_type; } void accept_vis (ASTVisitor &vis) override; 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 884c05a..41d0a07 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -21,6 +21,7 @@ #include "rust-diagnostics.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-attributes.h" +#include "rust-finalize-imports-2.0.h" namespace Rust { namespace Resolver2_0 { @@ -57,6 +58,9 @@ Early::go (AST::Crate &crate) for (auto &&import : toplevel.get_imports_to_resolve ()) build_import_mapping (std::move (import)); + // Once this is done, we finalize their resolution + FinalizeImports::go (import_mappings, toplevel, ctx); + // We now proceed with resolving macros, which can be nested in almost any // items textual_scope.push (); @@ -81,10 +85,6 @@ Early::resolve_glob_import (TopLevel::ImportKind &&glob) // up the module proper in `FinalizeImports` import_mappings.insert ({std::move (glob), resolved->get_node_id ()}); - // FIXME: This needs to be done in `FinalizeImports` - // GlobbingVisitor gvisitor (ctx); - // gvisitor.go (result.value ()); - return true; } @@ -169,29 +169,6 @@ Early::resolve_rebind_import (TopLevel::ImportKind &&rebind_import) { auto &path = rebind_import.to_resolve; - // We can fetch the value here as `resolve_rebind` will only be called on - // imports of the right kind - auto &rebind = rebind_import.rebind.value (); - - location_t locus = UNKNOWN_LOCATION; - std::string declared_name; - - // FIXME: This needs to be done in `FinalizeImports` - switch (rebind.get_new_bind_type ()) - { - case AST::UseTreeRebind::NewBindType::IDENTIFIER: - declared_name = rebind.get_identifier ().as_string (); - locus = rebind.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; - } - return ctx.values.resolve_path (path.get_segments ()) .or_else ([&] () { return ctx.types.resolve_path (path.get_segments ()); }) .or_else ([&] () { return ctx.macros.resolve_path (path.get_segments ()); }) diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc new file mode 100644 index 0000000..1725e71 --- /dev/null +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc @@ -0,0 +1,206 @@ +// Copyright (C) 2020-2024 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 "rust-finalize-imports-2.0.h" +#include "rust-hir-map.h" +#include "rust-name-resolution-context.h" +#include "rust-rib.h" +#include "rust-toplevel-name-resolver-2.0.h" + +namespace Rust { +namespace Resolver2_0 { + +void +GlobbingVisitor::go (AST::Module *module) +{ + for (auto &i : module->get_items ()) + visit (i); +} + +void +GlobbingVisitor::visit (AST::Module &module) +{ + if (module.get_visibility ().is_public ()) + ctx.insert_shadowable (module.get_name (), module.get_node_id (), + Namespace::Types); +} + +void +GlobbingVisitor::visit (AST::MacroRulesDefinition ¯o) +{ + if (macro.get_visibility ().is_public ()) + ctx.insert_shadowable (macro.get_rule_name (), macro.get_node_id (), + Namespace::Macros); +} + +void +GlobbingVisitor::visit (AST::Function &function) +{ + if (function.get_visibility ().is_public ()) + ctx.insert_shadowable (function.get_function_name (), + function.get_node_id (), Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::StaticItem &static_item) +{ + if (static_item.get_visibility ().is_public ()) + ctx.insert_shadowable (static_item.get_identifier (), + static_item.get_node_id (), Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::StructStruct &struct_item) +{ + if (struct_item.get_visibility ().is_public ()) + { + ctx.insert_shadowable (struct_item.get_identifier (), + struct_item.get_node_id (), Namespace::Types); + if (struct_item.is_unit_struct ()) + ctx.insert_shadowable (struct_item.get_identifier (), + struct_item.get_node_id (), Namespace::Values); + } +} + +void +GlobbingVisitor::visit (AST::TupleStruct &tuple_struct) +{ + if (tuple_struct.get_visibility ().is_public ()) + { + ctx.insert_shadowable (tuple_struct.get_identifier (), + tuple_struct.get_node_id (), Namespace::Types); + + ctx.insert_shadowable (tuple_struct.get_identifier (), + tuple_struct.get_node_id (), Namespace::Values); + } +} + +void +GlobbingVisitor::visit (AST::Enum &enum_item) +{ + if (enum_item.get_visibility ().is_public ()) + ctx.insert_shadowable (enum_item.get_identifier (), + enum_item.get_node_id (), Namespace::Types); +} + +void +GlobbingVisitor::visit (AST::Union &union_item) +{ + if (union_item.get_visibility ().is_public ()) + ctx.insert_shadowable (union_item.get_identifier (), + union_item.get_node_id (), Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::ConstantItem &const_item) +{ + if (const_item.get_visibility ().is_public ()) + ctx.insert_shadowable (const_item.get_identifier (), + const_item.get_node_id (), Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::ExternCrate &crate) +{} + +void +GlobbingVisitor::visit (AST::UseDeclaration &use) +{ + // Handle cycles ? +} + +void +finalize_simple_import (TopLevel &toplevel, + const std::pair<TopLevel::ImportKind, NodeId> &mapping) +{ + // FIXME: We probably need to store namespace information + + auto locus = mapping.first.to_resolve.get_locus (); + auto def = mapping.second; + auto identifier + = mapping.first.to_resolve.get_final_segment ().get_segment_name (); + + // FIXME: Fix the namespace in which we insert the new definition + toplevel.insert_or_error_out (identifier, locus, def, Namespace::Values); +} + +void +finalize_glob_import (NameResolutionContext &ctx, + const std::pair<TopLevel::ImportKind, NodeId> &mapping) +{ + auto module = Analysis::Mappings::get ().lookup_ast_module (mapping.second); + rust_assert (module); + + GlobbingVisitor glob_visitor (ctx); + glob_visitor.go (module.value ()); +} + +void +finalize_rebind_import (TopLevel &toplevel, + const std::pair<TopLevel::ImportKind, NodeId> &mapping) +{ + // We can fetch the value here as `resolve_rebind` will only be called on + // imports of the right kind + auto &path = mapping.first.to_resolve; + auto &rebind = mapping.first.rebind.value (); + auto def = mapping.second; + + location_t locus = UNKNOWN_LOCATION; + std::string declared_name; + + // FIXME: This needs to be done in `FinalizeImports` + switch (rebind.get_new_bind_type ()) + { + case AST::UseTreeRebind::NewBindType::IDENTIFIER: + declared_name = rebind.get_identifier ().as_string (); + locus = rebind.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; + } + + // FIXME: Fix the namespace in which we insert the new definition + toplevel.insert_or_error_out (declared_name, locus, def, Namespace::Values); +} + +void +FinalizeImports::go (std::map<TopLevel::ImportKind, NodeId> import_mappings, + TopLevel &toplevel, NameResolutionContext &ctx) +{ + for (const auto &mapping : import_mappings) + switch (mapping.first.kind) + { + case TopLevel::ImportKind::Kind::Glob: + finalize_glob_import (ctx, mapping); + break; + case TopLevel::ImportKind::Kind::Simple: + finalize_simple_import (toplevel, mapping); + break; + case TopLevel::ImportKind::Kind::Rebind: + finalize_rebind_import (toplevel, mapping); + break; + } +} + +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h new file mode 100644 index 0000000..e566a48 --- /dev/null +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h @@ -0,0 +1,96 @@ +// Copyright (C) 2020-2024 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 "rust-name-resolution-context.h" +#include "rust-toplevel-name-resolver-2.0.h" + +namespace Rust { +namespace Resolver2_0 { + +class GlobbingVisitor : public AST::DefaultASTVisitor +{ + using AST::DefaultASTVisitor::visit; + +public: + GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {} + + void go (AST::Module *module); + void visit (AST::Module &module) override; + void visit (AST::MacroRulesDefinition ¯o) override; + void visit (AST::Function &function) override; + void visit (AST::StaticItem &static_item) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TupleStruct &tuple_struct) override; + void visit (AST::Enum &enum_item) override; + void visit (AST::Union &union_item) override; + void visit (AST::ConstantItem &const_item) override; + void visit (AST::ExternCrate &crate) override; + void visit (AST::UseDeclaration &use) override; + +private: + NameResolutionContext &ctx; +}; + +// TODO: Fix documentation +// How do we do that? +// +// We want to resolve in the EarlyNameResolver, but we want to declare in the +// TopLevel Should the TopLevel declare stubs? How does rustc do it? How to do +// that for globbing? Should we do globbing afterwards once we've declared all +// the Uses*? +// +// Basically, for each use declare it in a separate map - in the +// EarlyNameResolver resolve and fix the ForeverStack? Emptying the maps each +// time? +// +// e.g. TopLevel builds a std::vector<NodeId, SimplePath> use_trees_to_resolve; +// Early goes through and resolves the SimplePath, then replaces the NodeId with +// the resolved one? Do we even need to do that? +// +// rustc just creates an empty definition for the use tree. +// +// What about globbing? std::vector<GlobbulesPath> globules; +// Early goes through and visits the module's path and calls the +// GlobbingVisitor? +// +// the file `imports.rs` goes through and *finalizes* imports. So we can +// probably add a FinalizeImport pass after the TopLevel and the Early. +// - TopLevel takes care of declaring these use trees +// - Early takes care of resolving them to definition points +// - Finalize takes care of mapping the use's definition point to the actual +// definition point +// - We need to work more on that last bit to know exactly what is being +// inserted, but probably it's going to mutate the ForeverStack - is that okay? +// - Oh actually maybe no! +// - TopLevel creates a map of UseTrees with paths to resolve. This should +// probably be an ImportKind enum or whatever +// - Early resolves them, creates a map of SimplePath with the associated +// definition: Map<ImportKind, ImportData> +// - Finalizes visits all UseTrees and inserts the Definitions found for +// each ImportKind - easy! +// - yay! + +class FinalizeImports +{ +public: + static void go (std::map<TopLevel::ImportKind, NodeId> import_mappings, + TopLevel &toplevel, NameResolutionContext &ctx); +}; + +} // namespace Resolver2_0 +} // namespace Rust 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 8a1d8be..b6695f6 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -26,105 +26,6 @@ namespace Rust { namespace Resolver2_0 { -void -GlobbingVisitor::go (AST::Module *module) -{ - for (auto &i : module->get_items ()) - visit (i); -} - -void -GlobbingVisitor::visit (AST::Module &module) -{ - if (module.get_visibility ().is_public ()) - ctx.insert_shadowable (module.get_name (), module.get_node_id (), - Namespace::Types); -} - -void -GlobbingVisitor::visit (AST::MacroRulesDefinition ¯o) -{ - if (macro.get_visibility ().is_public ()) - ctx.insert_shadowable (macro.get_rule_name (), macro.get_node_id (), - Namespace::Macros); -} - -void -GlobbingVisitor::visit (AST::Function &function) -{ - if (function.get_visibility ().is_public ()) - ctx.insert_shadowable (function.get_function_name (), - function.get_node_id (), Namespace::Values); -} - -void -GlobbingVisitor::visit (AST::StaticItem &static_item) -{ - if (static_item.get_visibility ().is_public ()) - ctx.insert_shadowable (static_item.get_identifier (), - static_item.get_node_id (), Namespace::Values); -} - -void -GlobbingVisitor::visit (AST::StructStruct &struct_item) -{ - if (struct_item.get_visibility ().is_public ()) - { - ctx.insert_shadowable (struct_item.get_identifier (), - struct_item.get_node_id (), Namespace::Types); - if (struct_item.is_unit_struct ()) - ctx.insert_shadowable (struct_item.get_identifier (), - struct_item.get_node_id (), Namespace::Values); - } -} - -void -GlobbingVisitor::visit (AST::TupleStruct &tuple_struct) -{ - if (tuple_struct.get_visibility ().is_public ()) - { - ctx.insert_shadowable (tuple_struct.get_identifier (), - tuple_struct.get_node_id (), Namespace::Types); - - ctx.insert_shadowable (tuple_struct.get_identifier (), - tuple_struct.get_node_id (), Namespace::Values); - } -} - -void -GlobbingVisitor::visit (AST::Enum &enum_item) -{ - if (enum_item.get_visibility ().is_public ()) - ctx.insert_shadowable (enum_item.get_identifier (), - enum_item.get_node_id (), Namespace::Types); -} - -void -GlobbingVisitor::visit (AST::Union &union_item) -{ - if (union_item.get_visibility ().is_public ()) - ctx.insert_shadowable (union_item.get_identifier (), - union_item.get_node_id (), Namespace::Values); -} - -void -GlobbingVisitor::visit (AST::ConstantItem &const_item) -{ - if (const_item.get_visibility ().is_public ()) - ctx.insert_shadowable (const_item.get_identifier (), - const_item.get_node_id (), Namespace::Values); -} - -void -GlobbingVisitor::visit (AST::ExternCrate &crate) -{} - -void -GlobbingVisitor::visit (AST::UseDeclaration &use) -{ - // Handle cycles ? -} - TopLevel::TopLevel (NameResolutionContext &resolver) : DefaultResolver (resolver) {} @@ -564,25 +465,12 @@ TopLevel::visit (AST::UseDeclaration &use) for (auto &&path : paths) imports_to_resolve.emplace_back (ImportKind::Simple (std::move (path))); - // if (!handle_use_dec (path)) - // rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433, - // "unresolved import %qs", path.as_string ().c_str ()); - for (auto &&glob : glob_path) imports_to_resolve.emplace_back (ImportKind::Glob (std::move (glob))); - // 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) imports_to_resolve.emplace_back ( ImportKind::Rebind (std::move (rebind.first), std::move (rebind.second))); - - // 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 77dd522..7b505cb 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -29,29 +29,6 @@ namespace Rust { namespace Resolver2_0 { -class GlobbingVisitor : public AST::DefaultASTVisitor -{ - using AST::DefaultASTVisitor::visit; - -public: - GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {} - - void go (AST::Module *module); - void visit (AST::Module &module) override; - void visit (AST::MacroRulesDefinition ¯o) override; - void visit (AST::Function &function) override; - void visit (AST::StaticItem &static_item) override; - void visit (AST::StructStruct &struct_item) override; - void visit (AST::TupleStruct &tuple_struct) override; - void visit (AST::Enum &enum_item) override; - void visit (AST::Union &union_item) override; - void visit (AST::ConstantItem &const_item) override; - void visit (AST::ExternCrate &crate) override; - void visit (AST::UseDeclaration &use) override; - -private: - NameResolutionContext &ctx; -}; /** * The `TopLevel` visitor takes care of collecting all the definitions in a * crate, and inserting them into the proper namespaces. These definitions can @@ -123,7 +100,6 @@ public: return std::move (imports_to_resolve); } -private: /** * Insert a new definition or error out if a definition with the same name was * already present in the same namespace in the same scope. @@ -140,6 +116,7 @@ private: const location_t &locus, const NodeId &id, Namespace ns); +private: // FIXME: Do we move these to our mappings? std::unordered_map<NodeId, location_t> node_locations; |