diff options
Diffstat (limited to 'gcc/rust/resolve')
23 files changed, 617 insertions, 143 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 6c35a22..b781ce33 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -328,6 +328,10 @@ ResolverBase::visit (AST::InlineAsm &) {} void +ResolverBase::visit (AST::LlvmInlineAsm &) +{} + +void ResolverBase::visit (AST::TypeParam &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 0d497f8..5bb9e4f 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -27,6 +27,11 @@ namespace Rust { namespace Resolver { +inline void +redefined_error (const rich_location &loc) +{ + rust_error_at (loc, "redefined multiple times"); +} class ResolverBase : public AST::ASTVisitor { @@ -105,6 +110,7 @@ public: void visit (AST::AwaitExpr &); void visit (AST::AsyncBlockExpr &); void visit (AST::InlineAsm &); + void visit (AST::LlvmInlineAsm &); void visit (AST::TypeParam &); diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index dc7f76d..6242235 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -368,6 +368,17 @@ ResolveExpr::visit (AST::InlineAsm &expr) { translate_operand (expr, prefix, canonical_prefix); } + +void +ResolveExpr::visit (AST::LlvmInlineAsm &expr) +{ + for (auto &output : expr.get_outputs ()) + ResolveExpr::go (*output.expr, prefix, canonical_prefix); + + for (auto &input : expr.get_inputs ()) + ResolveExpr::go (*input.expr, prefix, canonical_prefix); +} + void ResolveExpr::visit (AST::UnsafeBlockExpr &expr) { @@ -471,7 +482,7 @@ ResolveExpr::visit (AST::BreakExpr &expr) { if (expr.has_label ()) { - auto label = expr.get_label ().get_lifetime (); + auto label = expr.get_label_unchecked ().get_lifetime (); if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) { rust_error_at (label.get_locus (), @@ -486,8 +497,8 @@ ResolveExpr::visit (AST::BreakExpr &expr) &resolved_node)) { rust_error_at (label.get_locus (), ErrorCode::E0426, - "use of undeclared label %qs in %<break%>", - label.get_lifetime_name ().c_str ()); + "use of undeclared label %qs", + label.as_string ().c_str ()); return; } resolver->insert_resolved_label (label.get_node_id (), resolved_node); @@ -594,7 +605,7 @@ ResolveExpr::visit (AST::ContinueExpr &expr) { if (expr.has_label ()) { - auto label = expr.get_label (); + auto label = expr.get_label_unchecked (); if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) { rust_error_at (label.get_locus (), @@ -608,9 +619,9 @@ ResolveExpr::visit (AST::ContinueExpr &expr) label.get_lifetime_name ()), &resolved_node)) { - rust_error_at (expr.get_label ().get_locus (), ErrorCode::E0426, - "use of undeclared label %qs in %<continue%>", - label.get_lifetime_name ().c_str ()); + rust_error_at (expr.get_label_unchecked ().get_locus (), + ErrorCode::E0426, "use of undeclared label %qs", + label.as_string ().c_str ()); return; } resolver->insert_resolved_label (label.get_node_id (), resolved_node); diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 562a3bd..b296d66 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -57,6 +57,7 @@ public: void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; void visit (AST::InlineAsm &expr) override; + void visit (AST::LlvmInlineAsm &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; void visit (AST::ArrayElemsValues &elems) override; void visit (AST::ArrayExpr &expr) override; diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index 971bf8f..2081697 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -51,7 +51,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, type.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); } @@ -67,7 +67,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, constant.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); } @@ -84,7 +84,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, function.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); } @@ -124,7 +124,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, function.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (function.get_node_id (), cpath); @@ -144,7 +144,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, constant.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (constant.get_node_id (), cpath); @@ -162,7 +162,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, type.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (type.get_node_id (), cpath); @@ -202,7 +202,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, function.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -221,7 +221,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -239,8 +239,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, type.get_locus ()); r.add_range (locus); - - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index d584961..30f6d43 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -356,6 +356,8 @@ ResolveItem::visit (AST::EnumItemDiscriminant &item) auto cpath = canonical_prefix.append (decl); mappings.insert_canonical_path (item.get_node_id (), cpath); + + ResolveExpr::go (item.get_expr (), path, cpath); } void diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index 530926d..fb6715d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -68,8 +68,7 @@ ResolvePath::resolve_path (AST::PathInExpression &expr) if (in_middle_of_path && segment.is_lower_self_seg ()) { rust_error_at (segment.get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the " - "beginning of a path", + "%qs in paths can only be used in start position", segment.as_string ().c_str ()); return UNKNOWN_NODEID; } @@ -372,8 +371,9 @@ ResolvePath::resolve_path (AST::SimplePath &expr) { if (!is_first_segment) { - rust_error_at (segment.get_locus (), - "%<super%> can only be used in start position"); + rust_error_at ( + segment.get_locus (), ErrorCode::E0433, + "%<super%> in paths can only be used in start position"); return UNKNOWN_NODEID; } if (module_scope_id == crate_scope_id) diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc index fefb522..bfba302 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.cc @@ -70,7 +70,7 @@ ResolveStmt::visit (AST::StaticItem &var) [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, var.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); ResolveType::go (var.get_type ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 6c99d6a..d413a7c 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -63,7 +63,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, constant.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); ResolveType::go (constant.get_type ()); @@ -98,7 +98,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, struct_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId scope_node_id = struct_decl.get_node_id (); @@ -129,7 +129,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, enum_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId scope_node_id = enum_decl.get_node_id (); @@ -159,7 +159,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); // Done, no fields. @@ -179,7 +179,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); for (auto &field : item.get_tuple_fields ()) @@ -205,7 +205,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); for (auto &field : item.get_struct_fields ()) @@ -231,7 +231,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); // Done, no fields. @@ -252,7 +252,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, struct_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId scope_node_id = struct_decl.get_node_id (); @@ -288,7 +288,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, union_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId scope_node_id = union_decl.get_node_id (); @@ -324,7 +324,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, function.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId scope_node_id = function.get_node_id (); diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 379ccab..f52fb8a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -58,7 +58,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, module.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -88,7 +88,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, alias.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -110,7 +110,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, struct_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -132,7 +132,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, enum_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); resolver->push_new_module_scope (enum_decl.get_node_id ()); @@ -158,7 +158,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (item.get_node_id (), cpath); @@ -180,7 +180,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (item.get_node_id (), cpath); @@ -202,7 +202,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (item.get_node_id (), cpath); @@ -224,7 +224,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, item.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); mappings.insert_canonical_path (item.get_node_id (), cpath); @@ -246,7 +246,7 @@ public: = [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, struct_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }; resolver->get_type_scope ().insert (path, struct_decl.get_node_id (), @@ -277,7 +277,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, union_decl.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -297,7 +297,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, var.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -318,7 +318,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, constant.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -340,7 +340,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, function.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); NodeId current_module = resolver->peek_current_module_scope (); @@ -388,7 +388,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, impl_block.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); for (auto &impl_item : impl_block.get_impl_items ()) @@ -408,7 +408,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, trait.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); for (auto &item : trait.get_trait_items ()) @@ -480,7 +480,7 @@ public: [&] (const CanonicalPath &, NodeId, location_t locus) -> void { rich_location r (line_table, extern_crate.get_locus ()); r.add_range (locus); - rust_error_at (r, "defined multiple times"); + redefined_error (r); }); } diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 5ab0c44..8fd69c3 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -176,8 +176,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) if (in_middle_of_path && segment->is_lower_self_seg ()) { rust_error_at (segment->get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the " - "beginning of a path", + "%qs in paths can only be used in start position", segment->as_string ().c_str ()); return false; } @@ -357,7 +356,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) { rust_error_at (segment->get_locus (), ErrorCode::E0412, "could not resolve type path %qs", - segment->as_string ().c_str ()); + segment->get_ident_segment ().as_string ().c_str ()); return false; } } diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 8379d0e..f1481fc 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -141,8 +141,8 @@ public: if (first_pass) ResolveType::go (param.get_type ()); else if (param.has_default_value ()) - ResolveExpr::go (param.get_default_value ().get_expression (), prefix, - canonical_prefix); + ResolveExpr::go (param.get_default_value_unchecked ().get_expression (), + prefix, canonical_prefix); } void visit (AST::TypeParam ¶m) override diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 7528e79..480034c 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -179,5 +179,13 @@ DefaultResolver::visit (AST::StaticItem &item) ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); } +void +DefaultResolver::visit (AST::TypeParam ¶m) +{ + auto expr_vis = [this, ¶m] () { AST::DefaultASTVisitor::visit (param); }; + + ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 587d7d4..2a987ef 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -50,6 +50,8 @@ public: void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; + void visit (AST::TypeParam &) 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 afaca1f..3390f09 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -70,8 +70,7 @@ Early::go (AST::Crate &crate) bool Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob) { - auto resolved - = ctx.resolve_path (glob.to_resolve.get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types); if (!resolved.has_value ()) return false; @@ -141,6 +140,10 @@ Early::build_import_mapping ( // be moved into the newly created import mappings auto path = import.to_resolve; + // used to skip the "unresolved import" error + // if we output other errors during resolution + size_t old_error_count = macro_resolve_errors.size (); + switch (import.kind) { case TopLevel::ImportKind::Kind::Glob: @@ -154,7 +157,7 @@ Early::build_import_mapping ( break; } - if (!found) + if (!found && old_error_count == macro_resolve_errors.size ()) collect_error (Error (path.get_final_segment ().get_locus (), ErrorCode::E0433, "unresolved import %qs", path.as_string ().c_str ())); @@ -325,10 +328,9 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto pm_def = mappings.lookup_derive_proc_macro_def ( definition->get_node_id ()); - rust_assert (pm_def.has_value ()); - - mappings.insert_derive_proc_macro_invocation (trait, - pm_def.value ()); + if (pm_def.has_value ()) + mappings.insert_derive_proc_macro_invocation (trait, + pm_def.value ()); } } else if (Analysis::BuiltinAttributeMappings::get () 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 c4226fe..e78bec0 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -218,7 +218,6 @@ private: std::vector<std::pair<Rib::Definition, Namespace>> resolve_path_in_all_ns (const P &path) { - const auto &segments = path.get_segments (); std::vector<std::pair<Rib::Definition, Namespace>> resolved; // Pair a definition with the namespace it was found in @@ -229,13 +228,22 @@ private: }; }; - ctx.resolve_path (segments, Namespace::Values) + std::vector<Error> value_errors; + std::vector<Error> type_errors; + std::vector<Error> macro_errors; + + ctx.resolve_path (path, value_errors, Namespace::Values) .map (pair_with_ns (Namespace::Values)); - ctx.resolve_path (segments, Namespace::Types) + ctx.resolve_path (path, type_errors, Namespace::Types) .map (pair_with_ns (Namespace::Types)); - ctx.resolve_path (segments, Namespace::Macros) + ctx.resolve_path (path, macro_errors, Namespace::Macros) .map (pair_with_ns (Namespace::Macros)); + if (!value_errors.empty () && !type_errors.empty () + && !macro_errors.empty ()) + for (auto &ent : value_errors) + collect_error (std::move (ent)); + return resolved; } diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index f390e38..81468e5 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -549,6 +549,7 @@ public: ForeverStack () : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)), lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)), + extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)), cursor_reference (root) { rust_assert (root.is_root ()); @@ -671,8 +672,9 @@ public: */ template <typename S> tl::optional<Rib::Definition> resolve_path ( - const std::vector<S> &segments, - std::function<void (const S &, NodeId)> insert_segment_resolution); + const std::vector<S> &segments, bool has_opening_scope_resolution, + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors); // FIXME: Documentation tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const; @@ -768,6 +770,10 @@ private: * resolution */ Node lang_prelude; + /* + * The extern prelude, used for resolving external crates + */ + Node extern_prelude; std::reference_wrapper<Node> cursor_reference; @@ -787,13 +793,15 @@ private: tl::optional<SegIterator<S>> find_starting_point ( const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point, - std::function<void (const S &, NodeId)> insert_segment_resolution); + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors); template <typename S> tl::optional<Node &> resolve_segments ( Node &starting_point, const std::vector<S> &segments, SegIterator<S> iterator, - std::function<void (const S &, NodeId)> insert_segment_resolution); + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors); tl::optional<Rib::Definition> resolve_final_segment (Node &final_node, std::string &seg_name, @@ -823,6 +831,21 @@ private: tl::optional<Node &> dfs_node (Node &starting_point, NodeId to_find); tl::optional<const Node &> dfs_node (const Node &starting_point, NodeId to_find) const; + +public: + bool forward_declared (NodeId definition, NodeId usage) + { + if (peek ().kind != Rib::Kind::ForwardTypeParamBan) + return false; + + const auto &definition_rib = dfs_rib (cursor (), definition); + + if (!definition_rib) + return false; + + return (definition_rib + && definition_rib.value ().kind == Rib::Kind::ForwardTypeParamBan); + } }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 885f282..069111e 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -20,6 +20,7 @@ #include "rust-ast.h" #include "rust-diagnostics.h" #include "rust-forever-stack.h" +#include "rust-edition.h" #include "rust-rib.h" #include "rust-unwrap-segment.h" #include "optional.h" @@ -397,12 +398,13 @@ ForeverStack<N>::find_closest_module (Node &starting_point) * segments */ template <typename S> static inline bool -check_leading_kw_at_start (const S &segment, bool condition) +check_leading_kw_at_start (std::vector<Error> &collect_errors, const S &segment, + bool condition) { if (condition) - rust_error_at ( + collect_errors.emplace_back ( segment.get_locus (), ErrorCode::E0433, - "leading path segment %qs can only be used at the beginning of a path", + "%qs in paths can only be used in start position", segment.as_string ().c_str ()); return condition; @@ -418,7 +420,8 @@ template <typename S> tl::optional<typename std::vector<S>::const_iterator> ForeverStack<N>::find_starting_point ( const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point, - std::function<void (const S &, NodeId)> insert_segment_resolution) + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors) { auto iterator = segments.begin (); @@ -435,8 +438,9 @@ ForeverStack<N>::find_starting_point ( // if we're after the first path segment and meet `self` or `crate`, it's // an error - we should only be seeing `super` keywords at this point - if (check_leading_kw_at_start (seg, !is_start (iterator, segments) - && is_self_or_crate)) + if (check_leading_kw_at_start (collect_errors, seg, + !is_start (iterator, segments) + && is_self_or_crate)) return tl::nullopt; if (seg.is_crate_path_seg ()) @@ -459,8 +463,9 @@ ForeverStack<N>::find_starting_point ( starting_point = find_closest_module (starting_point); if (starting_point.get ().is_root ()) { - rust_error_at (seg.get_locus (), ErrorCode::E0433, - "too many leading %<super%> keywords"); + collect_errors.emplace_back ( + seg.get_locus (), ErrorCode::E0433, + "too many leading %<super%> keywords"); return tl::nullopt; } @@ -486,7 +491,8 @@ tl::optional<typename ForeverStack<N>::Node &> ForeverStack<N>::resolve_segments ( Node &starting_point, const std::vector<S> &segments, typename std::vector<S>::const_iterator iterator, - std::function<void (const S &, NodeId)> insert_segment_resolution) + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors) { Node *current_node = &starting_point; for (; !is_last (iterator, segments); iterator++) @@ -508,9 +514,10 @@ ForeverStack<N>::resolve_segments ( rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ()); // check that we don't encounter *any* leading keywords afterwards - if (check_leading_kw_at_start (seg, seg.is_crate_path_seg () - || seg.is_super_path_seg () - || seg.is_lower_self_seg ())) + if (check_leading_kw_at_start (collect_errors, seg, + seg.is_crate_path_seg () + || seg.is_super_path_seg () + || seg.is_lower_self_seg ())) return tl::nullopt; tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt; @@ -618,11 +625,25 @@ template <Namespace N> template <typename S> tl::optional<Rib::Definition> ForeverStack<N>::resolve_path ( - const std::vector<S> &segments, - std::function<void (const S &, NodeId)> insert_segment_resolution) + const std::vector<S> &segments, bool has_opening_scope_resolution, + std::function<void (const S &, NodeId)> insert_segment_resolution, + std::vector<Error> &collect_errors) { // TODO: What to do if segments.empty() ? + // handle paths with opening scopes + std::function<void (void)> cleanup_current = [] () {}; + if (has_opening_scope_resolution) + { + Node *last_current = &cursor_reference.get (); + if (get_rust_edition () == Edition::E2015) + cursor_reference = root; + else + cursor_reference = extern_prelude; + cleanup_current + = [this, last_current] () { cursor_reference = *last_current; }; + } + // if there's only one segment, we just use `get` if (segments.size () == 1) { @@ -633,6 +654,7 @@ ForeverStack<N>::resolve_path ( lang_item.value ()); insert_segment_resolution (seg, seg_id); + cleanup_current (); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (seg_id); } @@ -646,40 +668,45 @@ ForeverStack<N>::resolve_path ( if (res && !res->is_ambiguous ()) insert_segment_resolution (segments.back (), res->get_node_id ()); + cleanup_current (); return res; } std::reference_wrapper<Node> starting_point = cursor (); - return find_starting_point (segments, starting_point, - insert_segment_resolution) - .and_then ([this, &segments, &starting_point, &insert_segment_resolution] ( - typename std::vector<S>::const_iterator iterator) { - return resolve_segments (starting_point.get (), segments, iterator, - insert_segment_resolution); - }) - .and_then ([this, &segments, &insert_segment_resolution] ( - Node final_node) -> tl::optional<Rib::Definition> { - // leave resolution within impl blocks to type checker - if (final_node.rib.kind == Rib::Kind::TraitOrImpl) - return tl::nullopt; - - auto &seg = unwrap_type_segment (segments.back ()); - std::string seg_name = seg.as_string (); - - // assuming this can't be a lang item segment - tl::optional<Rib::Definition> res - = resolve_final_segment (final_node, seg_name, - seg.is_lower_self_seg ()); - // Ok we didn't find it in the rib, Lets try the prelude... - if (!res) - res = get_lang_prelude (seg_name); - - if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); - - return res; - }); + auto res + = find_starting_point (segments, starting_point, insert_segment_resolution, + collect_errors) + .and_then ( + [this, &segments, &starting_point, &insert_segment_resolution, + &collect_errors] (typename std::vector<S>::const_iterator iterator) { + return resolve_segments (starting_point.get (), segments, iterator, + insert_segment_resolution, collect_errors); + }) + .and_then ([this, &segments, &insert_segment_resolution] ( + Node &final_node) -> tl::optional<Rib::Definition> { + // leave resolution within impl blocks to type checker + if (final_node.rib.kind == Rib::Kind::TraitOrImpl) + return tl::nullopt; + + auto &seg = unwrap_type_segment (segments.back ()); + std::string seg_name = seg.as_string (); + + // assuming this can't be a lang item segment + tl::optional<Rib::Definition> res + = resolve_final_segment (final_node, seg_name, + seg.is_lower_self_seg ()); + // Ok we didn't find it in the rib, Lets try the prelude... + if (!res) + res = get_lang_prelude (seg_name); + + if (res && !res->is_ambiguous ()) + insert_segment_resolution (segments.back (), res->get_node_id ()); + + return res; + }); + cleanup_current (); + return res; } template <Namespace N> 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 7d32374..6ec0422 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -129,6 +129,54 @@ Late::new_label (Identifier name, NodeId id) } void +Late::visit (AST::ForLoopExpr &expr) +{ + visit_outer_attrs (expr); + + ctx.bindings.enter (BindingSource::For); + + visit (expr.get_pattern ()); + + ctx.bindings.exit (); + + visit (expr.get_iterator_expr ()); + visit (expr.get_loop_label ()); + visit (expr.get_loop_block ()); +} + +void +Late::visit (AST::IfLetExpr &expr) +{ + visit_outer_attrs (expr); + + ctx.bindings.enter (BindingSource::Let); + + for (auto &pattern : expr.get_patterns ()) + visit (pattern); + + ctx.bindings.exit (); + + visit (expr.get_value_expr ()); + visit (expr.get_if_block ()); +} + +void +Late::visit (AST::MatchArm &arm) +{ + visit_outer_attrs (arm); + + ctx.bindings.enter (BindingSource::Match); + + for (auto &pattern : arm.get_patterns ()) + visit (pattern); + + ctx.bindings.exit (); + + if (arm.has_match_arm_guard ()) + visit (arm.get_guard_expr ()); +} + +void Late::visit (AST::LetStmt &let) { DefaultASTVisitor::visit_outer_attrs (let); @@ -138,8 +186,13 @@ Late::visit (AST::LetStmt &let) // this makes variable shadowing work properly if (let.has_init_expr ()) visit (let.get_init_expr ()); + + ctx.bindings.enter (BindingSource::Let); + visit (let.get_pattern ()); + ctx.bindings.exit (); + if (let.has_else_expr ()) visit (let.get_init_expr ()); @@ -167,9 +220,68 @@ Late::visit (AST::IdentifierPattern &identifier) // but values does not allow shadowing... since functions cannot shadow // do we insert functions in labels as well? + if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ())) + { + if (ctx.bindings.peek ().get_source () == BindingSource::Param) + rust_error_at ( + identifier.get_locus (), ErrorCode::E0415, + "identifier %qs is bound more than once in the same parameter list", + identifier.as_string ().c_str ()); + else + rust_error_at ( + identifier.get_locus (), ErrorCode::E0416, + "identifier %qs is bound more than once in the same pattern", + identifier.as_string ().c_str ()); + return; + } + + ctx.bindings.peek ().insert_ident (identifier.get_ident ()); + + if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ())) + { + // FIXME: map usage instead + std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), + identifier.get_node_id ()); + } + else + { + // We do want to ignore duplicated data because some situations rely on + // it. + std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), + identifier.get_node_id ()); + } +} + +void +Late::visit (AST::AltPattern &pattern) +{ + ctx.bindings.peek ().push (Binding::Kind::Or); + for (auto &alt : pattern.get_alts ()) + { + ctx.bindings.peek ().push (Binding::Kind::Product); + visit (alt); + ctx.bindings.peek ().merge (); + } + ctx.bindings.peek ().merge (); +} + +void +Late::visit_function_params (AST::Function &function) +{ + ctx.bindings.enter (BindingSource::Param); + + for (auto ¶m : function.get_function_params ()) + visit (param); + + ctx.bindings.exit (); +} + +void +Late::visit (AST::StructPatternFieldIdent &field) +{ // We do want to ignore duplicated data because some situations rely on it. - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + std::ignore = ctx.values.insert_shadowable (field.get_identifier (), + field.get_node_id ()); } void @@ -187,6 +299,9 @@ Late::visit (AST::SelfParam ¶m) void Late::visit (AST::BreakExpr &expr) { + if (expr.has_label ()) + resolve_label (expr.get_label_unchecked ().get_lifetime ()); + if (expr.has_break_expr ()) { auto &break_expr = expr.get_break_expr (); @@ -213,6 +328,38 @@ Late::visit (AST::BreakExpr &expr) } void +Late::visit (AST::LoopLabel &label) +{ + auto &lifetime = label.get_lifetime (); + ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()), + lifetime.get_node_id ()); +} + +void +Late::resolve_label (AST::Lifetime &lifetime) +{ + if (auto resolved = ctx.labels.get (lifetime.as_string ())) + { + if (resolved->get_node_id () != lifetime.get_node_id ()) + ctx.map_usage (Usage (lifetime.get_node_id ()), + Definition (resolved->get_node_id ())); + } + else + rust_error_at (lifetime.get_locus (), ErrorCode::E0426, + "use of undeclared label %qs", + lifetime.as_string ().c_str ()); +} + +void +Late::visit (AST::ContinueExpr &expr) +{ + if (expr.has_label ()) + resolve_label (expr.get_label_unchecked ()); + + DefaultResolver::visit (expr); +} + +void Late::visit (AST::IdentifierExpr &expr) { // TODO: same thing as visit(PathInExpression) here? @@ -307,14 +454,13 @@ Late::visit (AST::PathInExpression &expr) return; } - auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values, - Namespace::Types); + auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types); if (!resolved) { if (!ctx.lookup (expr.get_segments ().front ().get_node_id ())) - rust_error_at (expr.get_locus (), - "could not resolve path expression: %qs", + rust_error_at (expr.get_locus (), ErrorCode::E0433, + "Cannot find path %qs in this scope", expr.as_simple_path ().as_string ().c_str ()); return; } @@ -340,13 +486,9 @@ Late::visit (AST::TypePath &type) DefaultResolver::visit (type); - // take care of only simple cases - // TODO: remove this? - rust_assert (!type.has_opening_scope_resolution_op ()); - // this *should* mostly work // TODO: make sure typepath-like path resolution (?) is working - auto resolved = ctx.resolve_path (type.get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (type, Namespace::Types); if (!resolved.has_value ()) { @@ -363,6 +505,14 @@ Late::visit (AST::TypePath &type) return; } + if (ctx.types.forward_declared (resolved->get_node_id (), + type.get_node_id ())) + { + rust_error_at (type.get_locus (), ErrorCode::E0128, + "type parameters with a default cannot use forward " + "declared identifiers"); + } + ctx.map_usage (Usage (type.get_node_id ()), Definition (resolved->get_node_id ())); } @@ -394,8 +544,7 @@ Late::visit (AST::StructExprStruct &s) visit_inner_attrs (s); DefaultResolver::visit (s.get_struct_name ()); - auto resolved - = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); @@ -409,8 +558,7 @@ Late::visit (AST::StructExprStructBase &s) DefaultResolver::visit (s.get_struct_name ()); visit (s.get_struct_base ()); - auto resolved - = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); @@ -427,8 +575,7 @@ Late::visit (AST::StructExprStructFields &s) for (auto &field : s.get_fields ()) visit (field); - auto resolved - = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); + auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); @@ -482,14 +629,35 @@ void Late::visit (AST::ClosureExprInner &closure) { add_captures (closure, ctx); - DefaultResolver::visit (closure); + + visit_outer_attrs (closure); + + ctx.bindings.enter (BindingSource::Param); + + for (auto ¶m : closure.get_params ()) + visit (param); + + ctx.bindings.exit (); + + visit (closure.get_definition_expr ()); } void Late::visit (AST::ClosureExprInnerTyped &closure) { add_captures (closure, ctx); - DefaultResolver::visit (closure); + + visit_outer_attrs (closure); + + ctx.bindings.enter (BindingSource::Param); + + for (auto ¶m : closure.get_params ()) + visit (param); + + ctx.bindings.exit (); + + visit (closure.get_return_type ()); + visit (closure.get_definition_block ()); } } // namespace Resolver2_0 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 ac376b5..171d9bf 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -37,17 +37,27 @@ public: void new_label (Identifier name, NodeId id); + // Specialized visit bits + void visit_function_params (AST::Function &function) override; + // some more label declarations void visit (AST::LetStmt &) override; // TODO: Do we need this? // void visit (AST::Method &) override; void visit (AST::IdentifierPattern &) override; + void visit (AST::StructPatternFieldIdent &) override; + void visit (AST::AltPattern &) override; void visit (AST::SelfParam &) override; + void visit (AST::MatchArm &) override; + void visit (AST::ForLoopExpr &) override; + void visit (AST::IfLetExpr &) override; // resolutions void visit (AST::IdentifierExpr &) override; void visit (AST::StructExprFieldIdentifier &) override; void visit (AST::BreakExpr &) override; + void visit (AST::ContinueExpr &) override; + void visit (AST::LoopLabel &) override; void visit (AST::PathInExpression &) override; void visit (AST::TypePath &) override; void visit (AST::Trait &) override; @@ -61,6 +71,8 @@ public: void visit (AST::ClosureExprInnerTyped &) override; private: + void resolve_label (AST::Lifetime &lifetime); + /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ void setup_builtin_types (); diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 92c4863..f098e48 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -23,6 +23,65 @@ namespace Rust { namespace Resolver2_0 { +BindingLayer::BindingLayer (BindingSource source) : source (source) +{ + push (Binding::Kind::Product); +} + +bool +BindingLayer::bind_test (Identifier ident, Binding::Kind kind) +{ + for (auto &bind : bindings) + { + if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind) + { + return true; + } + } + return false; +} + +void +BindingLayer::push (Binding::Kind kind) +{ + bindings.push_back (Binding (kind)); +} + +bool +BindingLayer::is_and_bound (Identifier ident) +{ + return bind_test (ident, Binding::Kind::Product); +} + +bool +BindingLayer::is_or_bound (Identifier ident) +{ + return bind_test (ident, Binding::Kind::Or); +} + +void +BindingLayer::insert_ident (Identifier ident) +{ + bindings.back ().set.insert (ident); +} + +void +BindingLayer::merge () +{ + auto last_binding = bindings.back (); + bindings.pop_back (); + for (auto &value : last_binding.set) + { + bindings.back ().set.insert (value); + } +} + +BindingSource +BindingLayer::get_source () const +{ + return source; +} + NameResolutionContext::NameResolutionContext () : mappings (Analysis::Mappings::get ()) {} diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index ea81bde..19ba750 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -23,6 +23,7 @@ #include "rust-forever-stack.h" #include "rust-hir-map.h" #include "rust-rib.h" +#include "rust-stacked-contexts.h" namespace Rust { namespace Resolver2_0 { @@ -156,6 +157,62 @@ public: NodeId id; }; +struct Binding +{ + enum class Kind + { + Product, + Or, + } kind; + + std::unordered_set<Identifier> set; + + Binding (Binding::Kind kind) : kind (kind) {} +}; + +/** + * Used to identify the source of a binding, and emit the correct error message. + */ +enum class BindingSource +{ + Match, + Let, + For, + /* Closure param or function param */ + Param +}; + +class BindingLayer +{ + BindingSource source; + std::vector<Binding> bindings; + + bool bind_test (Identifier ident, Binding::Kind kind); + +public: + void push (Binding::Kind kind); + + BindingLayer (BindingSource source); + + /** + * Identifies if the identifier has been used in a product binding context. + * eg. `let (a, a) = test();` + */ + bool is_and_bound (Identifier ident); + + /** + * Identifies if the identifier has been used in a or context. + * eg. `let (a, 1) | (a, 2) = test()` + */ + bool is_or_bound (Identifier ident); + + void insert_ident (Identifier ident); + + void merge (); + + BindingSource get_source () const; +}; + // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext { @@ -212,6 +269,7 @@ public: ForeverStack<Namespace::Labels> labels; Analysis::Mappings &mappings; + StackedContexts<BindingLayer> bindings; // TODO: Rename // TODO: Use newtype pattern for Usage and Definition @@ -220,8 +278,10 @@ public: tl::optional<NodeId> lookup (NodeId usage) const; template <typename S> - tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments, - Namespace ns) + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &segments, + bool has_opening_scope_resolution, + std::vector<Error> &collect_errors, Namespace ns) { std::function<void (const S &, NodeId)> insert_segment_resolution = [this] (const S &seg, NodeId id) { @@ -232,33 +292,105 @@ public: switch (ns) { case Namespace::Values: - return values.resolve_path (segments, insert_segment_resolution); + return values.resolve_path (segments, has_opening_scope_resolution, + insert_segment_resolution, collect_errors); case Namespace::Types: - return types.resolve_path (segments, insert_segment_resolution); + return types.resolve_path (segments, has_opening_scope_resolution, + insert_segment_resolution, collect_errors); case Namespace::Macros: - return macros.resolve_path (segments, insert_segment_resolution); + return macros.resolve_path (segments, has_opening_scope_resolution, + insert_segment_resolution, collect_errors); case Namespace::Labels: - return labels.resolve_path (segments, insert_segment_resolution); + return labels.resolve_path (segments, has_opening_scope_resolution, + insert_segment_resolution, collect_errors); default: rust_unreachable (); } } template <typename S, typename... Args> - tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments, - Args... ns_args) + tl::optional<Rib::Definition> + resolve_path (const std::vector<S> &segments, + bool has_opening_scope_resolution, + tl::optional<std::vector<Error> &> collect_errors, + Namespace ns_first, Args... ns_args) { - std::initializer_list<Namespace> namespaces = {ns_args...}; + std::initializer_list<Namespace> namespaces = {ns_first, ns_args...}; for (auto ns : namespaces) { - if (auto ret = resolve_path (segments, ns)) + std::vector<Error> collect_errors_inner; + if (auto ret = resolve_path (segments, has_opening_scope_resolution, + collect_errors_inner, ns)) return ret; + if (!collect_errors_inner.empty ()) + { + if (collect_errors.has_value ()) + { + std::move (collect_errors_inner.begin (), + collect_errors_inner.end (), + std::back_inserter (collect_errors.value ())); + } + else + { + for (auto &e : collect_errors_inner) + e.emit (); + } + return tl::nullopt; + } } return tl::nullopt; } + template <typename... Args> + tl::optional<Rib::Definition> + resolve_path (const AST::SimplePath &path, + tl::optional<std::vector<Error> &> collect_errors, + Namespace ns_first, Args... ns_args) + { + return resolve_path (path.get_segments (), + path.has_opening_scope_resolution (), collect_errors, + ns_first, ns_args...); + } + + template <typename... Args> + tl::optional<Rib::Definition> + resolve_path (const AST::PathInExpression &path, + tl::optional<std::vector<Error> &> collect_errors, + Namespace ns_first, Args... ns_args) + { + return resolve_path (path.get_segments (), path.opening_scope_resolution (), + collect_errors, ns_first, ns_args...); + } + + template <typename... Args> + tl::optional<Rib::Definition> + resolve_path (const AST::TypePath &path, + tl::optional<std::vector<Error> &> collect_errors, + Namespace ns_first, Args... ns_args) + { + return resolve_path (path.get_segments (), + path.has_opening_scope_resolution_op (), + collect_errors, ns_first, ns_args...); + } + + template <typename P, typename... Args> + tl::optional<Rib::Definition> resolve_path (const P &path, Namespace ns_first, + Args... ns_args) + { + return resolve_path (path, tl::nullopt, ns_first, ns_args...); + } + + template <typename P, typename... Args> + tl::optional<Rib::Definition> + resolve_path (const P &path_segments, bool has_opening_scope_resolution, + Namespace ns_first, Args... ns_args) + { + return resolve_path (path_segments, has_opening_scope_resolution, + tl::nullopt, ns_first, ns_args...); + } + private: /* Map of "usage" nodes which have been resolved to a "definition" node */ std::map<Usage, Definition> resolved_nodes; 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 8863be7..2f036fe 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -113,7 +113,17 @@ TopLevel::visit (AST::Module &module) // This was copied from the old early resolver method // 'accumulate_escaped_macros' if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); + { + 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); @@ -125,8 +135,7 @@ TopLevel::visit (AST::Module &module) void TopLevel::visit (AST::Trait &trait) { - insert_or_error_out (trait.get_identifier ().as_string (), trait, - Namespace::Types); + insert_or_error_out (trait.get_identifier (), trait, Namespace::Types); DefaultResolver::visit (trait); } @@ -538,6 +547,8 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths, { if (glob.has_path ()) paths.emplace_back (glob.get_path ()); + else + paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ())); } void |