diff options
Diffstat (limited to 'gcc/rust/resolve/rust-early-name-resolver-2.0.cc')
-rw-r--r-- | gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 132 |
1 files changed, 116 insertions, 16 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 342f102..492a665 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -22,11 +22,13 @@ #include "rust-toplevel-name-resolver-2.0.h" #include "rust-attributes.h" #include "rust-finalize-imports-2.0.h" +#include "rust-attribute-values.h" namespace Rust { namespace Resolver2_0 { -Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx), dirty (false) +Early::Early (NameResolutionContext &ctx) + : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false) {} void @@ -51,16 +53,10 @@ void Early::go (AST::Crate &crate) { // First we go through TopLevel resolution to get all our declared items - auto toplevel = TopLevel (ctx); toplevel.go (crate); // We start with resolving the list of imports that `TopLevel` has built for // us - for (auto &&import : toplevel.get_imports_to_resolve ()) - build_import_mapping (std::move (import)); - - // Once this is done, we finalize their resolution - FinalizeImports (std::move (import_mappings), toplevel, ctx).go (crate); dirty = toplevel.is_dirty (); // We now proceed with resolving macros, which can be nested in almost any @@ -74,7 +70,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; @@ -226,11 +223,24 @@ Early::visit (AST::BlockExpr &block) void Early::visit (AST::Module &module) { - textual_scope.push (); + bool is_macro_use = false; + + for (const auto &attr : module.get_outer_attrs ()) + { + if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE) + { + is_macro_use = true; + break; + } + } + + if (!is_macro_use) + textual_scope.push (); DefaultResolver::visit (module); - textual_scope.pop (); + if (!is_macro_use) + textual_scope.pop (); } void @@ -259,13 +269,14 @@ 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 ()) { collect_error (Error (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation")); + "could not resolve macro invocation %qs", + path.as_string ().c_str ())); return; } @@ -300,8 +311,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 +335,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 @@ -359,5 +370,94 @@ Early::visit (AST::StructStruct &s) DefaultResolver::visit (s); } +void +Early::finalize_simple_import (const Early::ImportPair &mapping) +{ + // FIXME: We probably need to store namespace information + + auto locus = mapping.import_kind.to_resolve.get_locus (); + auto data = mapping.data; + auto identifier + = mapping.import_kind.to_resolve.get_final_segment ().get_segment_name (); + + for (auto &&definition : data.definitions ()) + toplevel + .insert_or_error_out ( + identifier, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */); +} + +void +Early::finalize_glob_import (NameResolutionContext &ctx, + const Early::ImportPair &mapping) +{ + auto module = Analysis::Mappings::get ().lookup_ast_module ( + mapping.data.module ().get_node_id ()); + rust_assert (module); + + GlobbingVisitor glob_visitor (ctx); + glob_visitor.go (module.value ()); +} + +void +Early::finalize_rebind_import (const Early::ImportPair &mapping) +{ + // We can fetch the value here as `resolve_rebind` will only be called on + // imports of the right kind + auto &path = mapping.import_kind.to_resolve; + auto &rebind = mapping.import_kind.rebind.value (); + auto data = mapping.data; + + 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; + } + + for (auto &&definition : data.definitions ()) + toplevel.insert_or_error_out ( + declared_name, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */); +} + +void +Early::visit (AST::UseDeclaration &decl) +{ + auto &imports = toplevel.get_imports_to_resolve (); + auto current_import = imports.find (decl.get_node_id ()); + if (current_import != imports.end ()) + { + build_import_mapping (*current_import); + } + + // Once this is done, we finalize their resolution + for (const auto &mapping : import_mappings.get (decl.get_node_id ())) + switch (mapping.import_kind.kind) + { + case TopLevel::ImportKind::Kind::Glob: + finalize_glob_import (ctx, mapping); + break; + case TopLevel::ImportKind::Kind::Simple: + finalize_simple_import (mapping); + break; + case TopLevel::ImportKind::Kind::Rebind: + finalize_rebind_import (mapping); + break; + } + + DefaultResolver::visit (decl); +} + } // namespace Resolver2_0 } // namespace Rust |