diff options
Diffstat (limited to 'gcc/rust/resolve')
20 files changed, 400 insertions, 138 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 71c4c48..3c7b425 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -116,7 +116,7 @@ ResolverBase::visit (AST::MetaItemLitExpr &) {} void -ResolverBase::visit (AST::MetaItemPathLit &) +ResolverBase::visit (AST::MetaItemPathExpr &) {} void @@ -284,6 +284,10 @@ ResolverBase::visit (AST::ReturnExpr &) {} void +ResolverBase::visit (AST::TryExpr &) +{} + +void ResolverBase::visit (AST::UnsafeBlockExpr &) {} @@ -580,6 +584,14 @@ ResolverBase::visit (AST::GroupedPattern &) {} void +ResolverBase::visit (AST::SlicePatternItemsNoRest &) +{} + +void +ResolverBase::visit (AST::SlicePatternItemsHasRest &) +{} + +void ResolverBase::visit (AST::SlicePattern &) {} @@ -671,5 +683,9 @@ void ResolverBase::visit (AST::FormatArgs &fmt) {} +void +ResolverBase::visit (AST::OffsetOf &offset_of) +{} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index e17bdcb..89c5c35 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -21,6 +21,7 @@ #include "rust-ast-visitor.h" #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-expr.h" #include "rust-name-resolver.h" #include "rust-diagnostics.h" @@ -57,7 +58,7 @@ public: void visit (AST::AttrInputLiteral &); void visit (AST::AttrInputMacro &); void visit (AST::MetaItemLitExpr &); - void visit (AST::MetaItemPathLit &); + void visit (AST::MetaItemPathExpr &); void visit (AST::BorrowExpr &); void visit (AST::DereferenceExpr &); void visit (AST::ErrorPropagationExpr &); @@ -99,6 +100,7 @@ public: void visit (AST::RangeToInclExpr &); void visit (AST::BoxExpr &); void visit (AST::ReturnExpr &); + void visit (AST::TryExpr &); void visit (AST::UnsafeBlockExpr &); void visit (AST::LoopExpr &); void visit (AST::WhileLoopExpr &); @@ -184,6 +186,8 @@ public: void visit (AST::TuplePatternItemsRanged &); void visit (AST::TuplePattern &); void visit (AST::GroupedPattern &); + void visit (AST::SlicePatternItemsNoRest &); + void visit (AST::SlicePatternItemsHasRest &); void visit (AST::SlicePattern &); void visit (AST::AltPattern &); @@ -210,6 +214,7 @@ public: void visit (AST::SelfParam ¶m); void visit (AST::FormatArgs &fmt); + void visit (AST::OffsetOf &offset_of); protected: ResolverBase () diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 0937d65..1d5ebed 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -453,7 +453,8 @@ ResolveItem::visit (AST::ConstantItem &constant) resolve_visibility (constant.get_visibility ()); ResolveType::go (constant.get_type ()); - ResolveExpr::go (constant.get_expr (), path, cpath); + if (constant.has_expr ()) + ResolveExpr::go (constant.get_expr (), path, cpath); } void diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index 2b5e2bf..3b80f9f 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -62,6 +62,11 @@ PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type, void PatternDeclaration::visit (AST::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + pattern.get_subpattern ().accept_vis (*this); + } + Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm; add_new_binding (pattern.get_ident (), pattern.get_node_id (), BindingTypeInfo (mut, pattern.get_is_ref (), @@ -383,9 +388,30 @@ PatternDeclaration::visit (AST::RangePattern &pattern) void PatternDeclaration::visit (AST::SlicePattern &pattern) { - for (auto &p : pattern.get_items ()) + auto &items = pattern.get_items (); + switch (items.get_pattern_type ()) { - p->accept_vis (*this); + case AST::SlicePatternItems::SlicePatternItemType::NO_REST: + { + auto &ref + = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); + + for (auto &p : ref.get_patterns ()) + p->accept_vis (*this); + } + break; + + case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: + { + auto &ref + = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); + + for (auto &p : ref.get_lower_patterns ()) + p->accept_vis (*this); + for (auto &p : ref.get_upper_patterns ()) + p->accept_vis (*this); + } + break; } } diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index d413a7c..d714511 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -67,7 +67,8 @@ public: }); ResolveType::go (constant.get_type ()); - ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); + if (constant.has_expr ()) + ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); } void visit (AST::LetStmt &stmt) override diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 01906cf..f1c0e5c 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -111,17 +111,42 @@ DefaultResolver::visit (AST::IfLetExpr &expr) } void +DefaultResolver::visit (AST::IfLetExprConseqElse &expr) +{ + DefaultResolver::visit (static_cast<AST::IfLetExpr &> (expr)); + visit (expr.get_else_block ()); +} + +void DefaultResolver::visit (AST::Trait &trait) { - auto inner_fn_1 - = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; + visit_outer_attrs (trait); + visit (trait.get_visibility ()); + visit_inner_attrs (trait); + + auto inner_fn_1 = [this, &trait] () { + for (auto &item : trait.get_trait_items ()) + visit (item); + }; auto inner_fn_2 = [this, &trait, &inner_fn_1] () { + visit (trait.get_implicit_self ()); + for (auto &generic : trait.get_generic_params ()) + visit (generic); + if (trait.has_where_clause ()) + visit (trait.get_where_clause ()); + for (auto &bound : trait.get_type_param_bounds ()) + visit (bound); + + ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &trait, &inner_fn_2] () { ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (), - std::move (inner_fn_1)); + std::move (inner_fn_2)); }; - ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_2, + ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3, trait.get_identifier () /* FIXME: Is that valid?*/); } @@ -343,19 +368,15 @@ DefaultResolver::visit (AST::MatchExpr &expr) void DefaultResolver::visit (AST::ConstantItem &item) { - if (item.has_expr ()) - { - auto expr_vis_1 - = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; - auto expr_vis_2 = [this, &item, &expr_vis_1] () { - ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), - std::move (expr_vis_1)); - }; + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; - // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); - } + // FIXME: Why do we need a Rib here? + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void @@ -380,5 +401,46 @@ DefaultResolver::visit (AST::TypeParam ¶m) ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis); } +void +DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate, + AST::Crate &crate, CrateNum num) +{ + visit (crate); +} + +void +DefaultResolver::visit (AST::ExternCrate &crate) +{ + auto &mappings = Analysis::Mappings::get (); + auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); + + if (!num_opt) + { + rust_error_at (crate.get_locus (), "unknown crate %qs", + crate.get_referenced_crate ().c_str ()); + return; + } + + CrateNum num = *num_opt; + + AST::Crate &referenced_crate = mappings.get_ast_crate (num); + + auto sub_visitor_1 + = [&, this] () { visit_extern_crate (crate, referenced_crate, num); }; + + auto sub_visitor_2 = [&] () { + ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (), + crate.get_referenced_crate (), + std::move (sub_visitor_1)); + }; + + if (crate.has_as_clause ()) + ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), + sub_visitor_2, crate.get_as_clause ()); + else + ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), + sub_visitor_2, crate.get_referenced_crate ()); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 99fd8e7..cf0df68 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -49,6 +49,7 @@ public: void visit (AST::ForLoopExpr &expr) override; virtual void visit_if_let_patterns (AST::IfLetExpr &expr); void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::Trait &) override; // used to handle Self insertion in TopLevel virtual void maybe_insert_big_self (AST::Impl &) {} @@ -58,6 +59,9 @@ public: void visit (AST::TypeParam &) override; + virtual void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum); + void visit (AST::ExternCrate &) override; + // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &) override; void visit (AST::TupleStruct &) 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 c10379a..4fd1dd2 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -17,8 +17,11 @@ // <http://www.gnu.org/licenses/>. #include "rust-early-name-resolver-2.0.h" -#include "rust-ast-full.h" +#include "optional.h" +#include "options.h" #include "rust-diagnostics.h" +#include "rust-hir-map.h" +#include "rust-item.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-attributes.h" #include "rust-finalize-imports-2.0.h" @@ -75,8 +78,9 @@ Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob) if (!resolved.has_value ()) return false; - auto result - = Analysis::Mappings::get ().lookup_ast_module (resolved->get_node_id ()); + auto result = Analysis::Mappings::get ().lookup_glob_container ( + resolved->get_node_id ()); + if (!result) return false; @@ -252,6 +256,11 @@ Early::visit (AST::MacroInvocation &invoc) { auto &path = invoc.get_invoc_data ().get_path (); + // We special case the `offset_of!()` macro if the flag is here, otherwise + // we accept whatever `offset_of!()` definition we resolved to. + auto resolve_offset_of + = flag_assume_builtin_offset_of && (path.as_string () == "offset_of"); + if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) pending_invoc->accept_vis (*this); @@ -275,12 +284,14 @@ Early::visit (AST::MacroInvocation &invoc) if (!definition.has_value ()) definition = ctx.resolve_path (path, Namespace::Macros); - // if the definition still does not have a value, then it's an error + // if the definition still does not have a value, then it's an error - unless + // we should automatically resolve offset_of!() calls if (!definition.has_value ()) { - collect_error (Error (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation %qs", - path.as_string ().c_str ())); + if (!resolve_offset_of) + collect_error (Error (invoc.get_locus (), ErrorCode::E0433, + "could not resolve macro invocation %qs", + path.as_string ().c_str ())); return; } @@ -394,12 +405,12 @@ 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); + auto container = Analysis::Mappings::get ().lookup_glob_container ( + mapping.data.container ().get_node_id ()); + + rust_assert (container); - GlobbingVisitor glob_visitor (ctx); - glob_visitor.go (module.value ()); + GlobbingVisitor (ctx).go (container.value ()); } void 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 e78bec0..960de0e 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -83,15 +83,15 @@ public: return ImportData (Kind::Rebind, std::move (definitions)); } - static ImportData Glob (Rib::Definition module) + static ImportData Glob (Rib::Definition container) { - return ImportData (Kind::Glob, module); + return ImportData (Kind::Glob, container); } - Rib::Definition module () const + Rib::Definition container () const { rust_assert (kind == Kind::Glob); - return glob_module; + return glob_container; } std::vector<std::pair<Rib::Definition, Namespace>> definitions () const @@ -107,8 +107,8 @@ public: : kind (kind), resolved_definitions (std::move (definitions)) {} - ImportData (Kind kind, Rib::Definition module) - : kind (kind), glob_module (module) + ImportData (Kind kind, Rib::Definition container) + : kind (kind), glob_container (container) {} // TODO: Should this be a union? @@ -117,7 +117,7 @@ public: std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions; // For Glob - Rib::Definition glob_module; + Rib::Definition glob_container; }; struct ImportPair diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc index fc9a26c..7b365ef 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ b/gcc/rust/resolve/rust-early-name-resolver.cc @@ -205,7 +205,7 @@ EarlyNameResolver::visit (AST::MetaItemLitExpr &) {} void -EarlyNameResolver::visit (AST::MetaItemPathLit &) +EarlyNameResolver::visit (AST::MetaItemPathExpr &) {} void diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h index 26fc84d..d3c5225 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ b/gcc/rust/resolve/rust-early-name-resolver.h @@ -142,7 +142,7 @@ private: virtual void visit (AST::AttrInputLiteral &attr_input); virtual void visit (AST::AttrInputMacro &attr_input); virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); + virtual void visit (AST::MetaItemPathExpr &meta_item); virtual void visit (AST::StructExprStruct &expr); virtual void visit (AST::StructExprFieldIdentifier &field); virtual void visit (AST::StructExprStructBase &expr); diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc index b0e8651..317acb0 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc @@ -21,19 +21,44 @@ #include "rust-hir-map.h" #include "rust-name-resolution-context.h" #include "rust-rib.h" +#include "rust-system.h" #include "rust-toplevel-name-resolver-2.0.h" namespace Rust { namespace Resolver2_0 { void -GlobbingVisitor::go (AST::Module *module) +GlobbingVisitor::go (AST::Item *container) { - for (auto &i : module->get_items ()) + switch (container->get_item_kind ()) + { + case AST::Item::Kind::Module: + visit_module_container (static_cast<AST::Module &> (*container)); + break; + case AST::Item::Kind::Enum: + visit_enum_container (static_cast<AST::Enum &> (*container)); + break; + default: + rust_unreachable (); + } +} + +void +GlobbingVisitor::visit_module_container (AST::Module &module) +{ + for (auto &i : module.get_items ()) visit (i); } void +GlobbingVisitor::visit_enum_container (AST::Enum &item) +{ + for (auto &variant : item.get_variants ()) + ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (), + Namespace::Types); +} + +void GlobbingVisitor::visit (AST::Module &module) { if (module.get_visibility ().is_public ()) diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h index d587a5e..4ae1d6d 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.h +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h @@ -18,6 +18,7 @@ #include "rust-ast.h" #include "rust-expr.h" +#include "rust-item.h" #include "rust-name-resolution-context.h" #include "rust-toplevel-name-resolver-2.0.h" #include "rust-early-name-resolver-2.0.h" @@ -32,7 +33,11 @@ class GlobbingVisitor : public AST::DefaultASTVisitor public: GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {} - void go (AST::Module *module); + void go (AST::Item *container); + + void visit_module_container (AST::Module &module); + void visit_enum_container (AST::Enum &item); + void visit (AST::Module &module) override; void visit (AST::MacroRulesDefinition ¯o) override; void visit (AST::Function &function) override; diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 8721386..1ed87b3 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -297,6 +297,10 @@ ForeverStack<N>::get (Node &start, const Identifier &name) // TODO: Can we improve the API? have `reverse_iter` return an optional? reverse_iter (start, [&resolved_definition, &name] (Node ¤t) { + // we can't reference associated types/functions like this + if (current.rib.kind == Rib::Kind::TraitOrImpl) + return KeepGoing::Yes; + auto candidate = current.rib.get (name.as_string ()); return candidate.map_or ( @@ -549,6 +553,14 @@ ForeverStack<N>::resolve_segments ( bool searched_prelude = false; while (true) { + if (is_start (iterator, segments) + && current_node->rib.kind == Rib::Kind::TraitOrImpl) + { + // we can't reference associated types/functions like this + current_node = ¤t_node->parent.value (); + continue; + } + // may set the value of child for (auto &kv : current_node->children) { @@ -675,7 +687,7 @@ ForeverStack<N>::resolve_path ( if (!res) res = get_lang_prelude (seg.as_string ()); - if (!res && N == Namespace::Types) + if (N == Namespace::Types && !res) { if (seg.is_crate_path_seg ()) { @@ -707,6 +719,26 @@ ForeverStack<N>::resolve_path ( // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (id); } + else + { + // HACK: check for a module after we check the language prelude + for (auto &kv : + find_closest_module (starting_point.get ()).children) + { + auto &link = kv.first; + + if (link.path.map_or ( + [&seg] (Identifier path) { + auto &path_str = path.as_string (); + return path_str == seg.as_string (); + }, + false)) + { + insert_segment_resolution (outer_seg, kv.second.id); + return Rib::Definition::NonShadowable (kv.second.id); + } + } + } } if (res && !res->is_ambiguous ()) @@ -739,6 +771,26 @@ ForeverStack<N>::resolve_path ( if (!res) res = get_lang_prelude (seg_name); + if (N == Namespace::Types && !res) + { + // HACK: check for a module after we check the language prelude + for (auto &kv : final_node.children) + { + auto &link = kv.first; + + if (link.path.map_or ( + [&seg_name] (Identifier path) { + auto &path_str = path.as_string (); + return path_str == seg_name; + }, + false)) + { + insert_segment_resolution (segments.back (), kv.second.id); + return Rib::Definition::NonShadowable (kv.second.id); + } + } + } + if (res && !res->is_ambiguous ()) insert_segment_resolution (segments.back (), res->get_node_id ()); 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 62829e0..e39ca15 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -19,6 +19,7 @@ #include "optional.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" +#include "rust-expr.h" #include "rust-hir-map.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" @@ -141,7 +142,10 @@ Late::visit (AST::ForLoopExpr &expr) ctx.bindings.exit (); visit (expr.get_iterator_expr ()); - visit (expr.get_loop_label ()); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + visit (expr.get_loop_block ()); } @@ -208,10 +212,32 @@ Late::visit (AST::LetStmt &let) // let.get_node_id (), [] () {}); } +void +Late::visit (AST::WhileLetLoopExpr &while_let) +{ + DefaultASTVisitor::visit_outer_attrs (while_let); + + if (while_let.has_loop_label ()) + visit (while_let.get_loop_label ()); + + // visit expression before pattern + // this makes variable shadowing work properly + visit (while_let.get_scrutinee_expr ()); + + ctx.bindings.enter (BindingSource::WhileLet); + + for (auto &pattern : while_let.get_patterns ()) + visit (pattern); + + ctx.bindings.exit (); + + visit (while_let.get_loop_block ()); +} + static void visit_identifier_as_pattern (NameResolutionContext &ctx, const Identifier &ident, location_t locus, - NodeId node_id) + NodeId node_id, bool is_ref, bool is_mut) { // do we insert in labels or in values // but values does not allow shadowing... since functions cannot shadow @@ -232,7 +258,7 @@ visit_identifier_as_pattern (NameResolutionContext &ctx, return; } - ctx.bindings.peek ().insert_ident (ident); + ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut); if (ctx.bindings.peek ().is_or_bound (ident)) { @@ -251,9 +277,13 @@ visit_identifier_as_pattern (NameResolutionContext &ctx, void Late::visit (AST::IdentifierPattern &identifier) { + DefaultResolver::visit (identifier); + visit_identifier_as_pattern (ctx, identifier.get_ident (), identifier.get_locus (), - identifier.get_node_id ()); + identifier.get_node_id (), + identifier.get_is_ref (), + identifier.get_is_mut ()); } void @@ -284,7 +314,8 @@ void Late::visit (AST::StructPatternFieldIdent &field) { visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (), - field.get_node_id ()); + field.get_node_id (), field.is_ref (), + field.is_mut ()); } void @@ -612,13 +643,6 @@ Late::visit (AST::Trait &trait) } void -Late::visit (AST::StructStruct &s) -{ - auto s_vis = [this, &s] () { AST::DefaultASTVisitor::visit (s); }; - ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis); -} - -void Late::visit (AST::StructExprStruct &s) { visit_outer_attrs (s); diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index f2907c9..95540e3 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -42,6 +42,7 @@ public: // some more label declarations void visit (AST::LetStmt &) override; + void visit (AST::WhileLetLoopExpr &) override; // TODO: Do we need this? // void visit (AST::Method &) override; void visit (AST::IdentifierPattern &) override; @@ -66,7 +67,6 @@ public: void visit (AST::StructExprStruct &) override; void visit (AST::StructExprStructBase &) override; void visit (AST::StructExprStructFields &) override; - void visit (AST::StructStruct &) override; void visit (AST::GenericArgs &) override; void visit (AST::GenericArg &); void visit_closure_params (AST::ClosureExpr &) override; diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 34615ed..1b84f1d 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind) { for (auto &bind : bindings) { - if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind) + if (bind.idents.find (ident.as_string ()) != bind.idents.cend () + && bind.kind == kind) { return true; } @@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident) } void -BindingLayer::insert_ident (Identifier ident) +BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref, + bool is_mut) { - bindings.back ().set.insert (ident); + bindings.back ().idents.emplace ( + std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut))); } void BindingLayer::merge () { - auto last_binding = bindings.back (); + auto last_binding = std::move (bindings.back ()); bindings.pop_back (); - for (auto &value : last_binding.set) + + if (bindings.back ().has_expected_bindings) { - bindings.back ().set.insert (value); + for (auto &value : bindings.back ().idents) + { + auto ident = value.first; + if (last_binding.idents.find (ident) == last_binding.idents.end ()) + { + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0408, + "variable %qs is not bound in all patterns", + ident.c_str ()); + } + } } + + for (auto &value : last_binding.idents) + { + auto res = bindings.back ().idents.emplace (value); + if (res.second) + { + if (bindings.back ().has_expected_bindings) + { + auto &ident = value.first; + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0408, + "variable %qs is not bound in all patterns", + ident.c_str ()); + } + } + else + { + auto this_mode = value.second.second; + auto other_mode = res.first->second.second; + if (this_mode != other_mode) + { + auto &ident = value.first; + location_t locus = value.second.first; + rust_error_at (locus, ErrorCode::E0409, + "variable %qs is bound inconsistently across " + "pattern alternatives", + ident.c_str ()); + } + } + } + + if (bindings.back ().kind == Binding::Kind::Or) + bindings.back ().has_expected_bindings = true; } BindingSource diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index bb8519a..558b3ca 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -158,6 +158,22 @@ public: NodeId id; }; +struct IdentifierMode +{ + bool is_ref; + bool is_mut; + + IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut) + {} + + bool operator== (const IdentifierMode &other) + { + return other.is_ref == is_ref && other.is_mut == is_mut; + } + + bool operator!= (const IdentifierMode &other) { return !(*this == other); } +}; + struct Binding { enum class Kind @@ -166,9 +182,12 @@ struct Binding Or, } kind; - std::unordered_set<Identifier> set; + // used to check the correctness of or-bindings + bool has_expected_bindings; + + std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents; - Binding (Binding::Kind kind) : kind (kind) {} + Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {} }; /** @@ -179,6 +198,7 @@ enum class BindingSource Match, Let, IfLet, + WhileLet, For, /* Closure param or function param */ Param @@ -208,7 +228,8 @@ public: */ bool is_or_bound (Identifier ident); - void insert_ident (Identifier ident); + void insert_ident (std::string ident, location_t locus, bool is_ref, + bool is_mut); void merge (); 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 3e5ed53..0930f96 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -101,34 +101,11 @@ TopLevel::go (AST::Crate &crate) void TopLevel::visit (AST::Module &module) { - insert_or_error_out (module.get_name (), module, Namespace::Types); - - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive - // TODO: make sure this is right - // TODO: avoid loading items if cfg attributes are present? - // might not be needed if this runs after early resolution? - // This was copied from the old early resolver method - // 'accumulate_escaped_macros' - if (module.get_kind () == AST::Module::UNLOADED) - { - module.load_items (); - - // If the module was previously unloaded, then we don't want to visit it - // this time around as the CfgStrip hasn't run on its inner items yet. - // Skip it for now, mark the visitor as dirty and try again - - dirty = true; - - return; - } - DefaultResolver::visit (module); - if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ()) + if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ()) == tl::nullopt) - Analysis::Mappings::get ().insert_ast_module (&module); + Analysis::Mappings::get ().insert_glob_container (&module); } void @@ -173,19 +150,10 @@ insert_macros (std::vector<PROC_MACRO> ¯os, NameResolutionContext &ctx) } void -TopLevel::visit (AST::ExternCrate &crate) +TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate, + CrateNum num) { auto &mappings = Analysis::Mappings::get (); - auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); - - if (!num_opt) - { - rust_error_at (crate.get_locus (), "unknown crate %qs", - crate.get_referenced_crate ().c_str ()); - return; - } - - CrateNum num = *num_opt; auto attribute_macros = mappings.lookup_attribute_proc_macros (num); @@ -193,40 +161,27 @@ TopLevel::visit (AST::ExternCrate &crate) auto derive_macros = mappings.lookup_derive_proc_macros (num); - auto sub_visitor_1 = [&] () { - // TODO: Find a way to keep this part clean without the double dispatch. - if (derive_macros.has_value ()) - { - insert_macros (derive_macros.value (), ctx); - for (auto ¯o : derive_macros.value ()) - mappings.insert_derive_proc_macro_def (macro); - } - if (attribute_macros.has_value ()) - { - insert_macros (attribute_macros.value (), ctx); - for (auto ¯o : attribute_macros.value ()) - mappings.insert_attribute_proc_macro_def (macro); - } - if (bang_macros.has_value ()) - { - insert_macros (bang_macros.value (), ctx); - for (auto ¯o : bang_macros.value ()) - mappings.insert_bang_proc_macro_def (macro); - } - }; - - auto sub_visitor_2 = [&] () { - ctx.canonical_ctx.scope_crate (crate.get_node_id (), - crate.get_referenced_crate (), - std::move (sub_visitor_1)); - }; + // TODO: Find a way to keep this part clean without the double dispatch. + if (derive_macros.has_value ()) + { + insert_macros (derive_macros.value (), ctx); + for (auto ¯o : derive_macros.value ()) + mappings.insert_derive_proc_macro_def (macro); + } + if (attribute_macros.has_value ()) + { + insert_macros (attribute_macros.value (), ctx); + for (auto ¯o : attribute_macros.value ()) + mappings.insert_attribute_proc_macro_def (macro); + } + if (bang_macros.has_value ()) + { + insert_macros (bang_macros.value (), ctx); + for (auto ¯o : bang_macros.value ()) + mappings.insert_bang_proc_macro_def (macro); + } - if (crate.has_as_clause ()) - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, - crate.get_as_clause ()); - else - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, - crate.get_referenced_crate ()); + visit (crate); } static bool @@ -384,6 +339,13 @@ TopLevel::visit (AST::Enum &enum_item) Namespace::Types); DefaultResolver::visit (enum_item); + + // Since enums can be containers for imports, we need to insert them like we + // do for modules + if (Analysis::Mappings::get ().lookup_glob_container ( + enum_item.get_node_id ()) + == tl::nullopt) + Analysis::Mappings::get ().insert_glob_container (&enum_item); } void 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 0dfd654..8d3da92 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -176,7 +176,7 @@ private: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::TypeAlias &type_item) override; - void visit (AST::ExternCrate &crate) override; + void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override; void visit (AST::TypeParam &type_param) override; void visit (AST::ConstGenericParam &const_param) override; |