aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2024-04-04 17:07:54 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-19 15:32:12 +0100
commit333a4cbff7ef62208647c234af12caa35271b59c (patch)
treedf096abd47cc2b4612162f15ecd16e8eec2fa925 /gcc/rust
parent2f743673232dc87b85e802ea5256a36bb1988172 (diff)
downloadgcc-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.in1
-rw-r--r--gcc/rust/ast/rust-item.h2
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.cc31
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.cc206
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.h96
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc112
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h25
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 &macro)
+{
+ 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 &macro) 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 &macro)
-{
- 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 &macro) 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;