diff options
Diffstat (limited to 'gcc/rust/resolve/rust-late-name-resolver-2.0.cc')
-rw-r--r-- | gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 222 |
1 files changed, 183 insertions, 39 deletions
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 5aea6a4..cf7b7dc 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -27,6 +27,8 @@ #include "rust-system.h" #include "rust-tyty.h" #include "rust-hir-type-check.h" +#include "rust-ice-finalizer.h" +#include "rust-ast.h" namespace Rust { namespace Resolver2_0 { @@ -89,16 +91,18 @@ Late::setup_builtin_types () // insert it in the type context... }; - for (const auto &builtin : builtins) - { - // we should be able to use `insert_at_root` or `insert` here, since we're - // at the root :) hopefully! - auto ok = ctx.types.insert (builtin.name, builtin.node_id); - rust_assert (ok); + // There's a special Rib for putting prelude items, since prelude items need + // to satisfy certain special rules. + ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void { + for (const auto &builtin : builtins) + { + auto ok = ctx.types.insert (builtin.name, builtin.node_id); + rust_assert (ok); - ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); - ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); - } + ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); + ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); + } + }); // ...here! auto *unit_type = TyTy::TupleType::get_unit_type (); @@ -178,12 +182,39 @@ Late::visit (AST::SelfParam ¶m) } void +Late::visit (AST::BreakExpr &expr) +{ + if (expr.has_break_expr ()) + { + auto &break_expr = expr.get_break_expr (); + if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier) + { + /* This is a break with an expression, and the expression is + just a single identifier. See if the identifier is either + "rust" or "gcc", in which case we have "break rust" or "break + gcc", and so may need to emit our funny error. We cannot yet + emit the error here though, because the identifier may still + be in scope, and ICE'ing on valid programs would not be very + funny. */ + std::string ident + = static_cast<AST::IdentifierExpr &> (expr.get_break_expr ()) + .as_string (); + if (ident == "rust" || ident == "gcc") + funny_error = true; + } + } + + DefaultResolver::visit (expr); + + funny_error = false; +} + +void Late::visit (AST::IdentifierExpr &expr) { // TODO: same thing as visit(PathInExpression) here? tl::optional<Rib::Definition> resolved = tl::nullopt; - if (auto value = ctx.values.get (expr.get_ident ())) { resolved = value; @@ -192,42 +223,96 @@ Late::visit (AST::IdentifierExpr &expr) { resolved = type; } + else if (funny_error) + { + diagnostic_text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer; + emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1, + "are you trying to break %s? how dare you?", + expr.as_string ().c_str ()); + } else { - rust_error_at (expr.get_locus (), - "could not resolve identifier expression: %qs", - expr.get_ident ().as_string ().c_str ()); + if (auto type = ctx.types.get_prelude (expr.get_ident ())) + { + resolved = type; + } + else + { + rust_error_at (expr.get_locus (), ErrorCode::E0425, + "cannot find value %qs in this scope", + expr.get_ident ().as_string ().c_str ()); + return; + } + } + + if (resolved->is_ambiguous ()) + { + rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous", + expr.as_string ().c_str ()); return; } ctx.map_usage (Usage (expr.get_node_id ()), Definition (resolved->get_node_id ())); - // in the old resolver, resolutions are kept in the resolver, not the mappings - // :/ how do we deal with that? - // ctx.mappings.insert_resolved_name(expr, resolved); - // For empty types, do we perform a lookup in ctx.types or should the // toplevel instead insert a name in ctx.values? (like it currently does) } void +Late::visit (AST::StructExprFieldIdentifier &expr) +{ + tl::optional<Rib::Definition> resolved = tl::nullopt; + + if (auto value = ctx.values.get (expr.get_field_name ())) + { + resolved = value; + } + // seems like we don't need a type namespace lookup + else + { + rust_error_at (expr.get_locus (), "could not resolve struct field: %qs", + expr.get_field_name ().as_string ().c_str ()); + return; + } + + if (resolved->is_ambiguous ()) + { + rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous", + expr.as_string ().c_str ()); + return; + } + + ctx.map_usage (Usage (expr.get_node_id ()), + Definition (resolved->get_node_id ())); +} + +void Late::visit (AST::PathInExpression &expr) { // TODO: How do we have a nice error with `can't capture dynamic environment // in a function item` error here? // do we emit it in `get<Namespace::Labels>`? - auto resolved - = ctx.values.resolve_path (expr.get_segments ()).or_else ([&] () { - return ctx.types.resolve_path (expr.get_segments ()); - }); + DefaultResolver::visit (expr); + + if (expr.is_lang_item ()) + { + ctx.map_usage (Usage (expr.get_node_id ()), + Definition (Analysis::Mappings::get ().get_lang_item_node ( + expr.get_lang_item ()))); + return; + } + + auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values, + Namespace::Types); if (!resolved) { - rust_error_at (expr.get_locus (), - "could not resolve path expression: %qs", - expr.as_simple_path ().as_string ().c_str ()); + if (!ctx.lookup (expr.get_segments ().front ().get_node_id ())) + rust_error_at (expr.get_locus (), + "could not resolve path expression: %qs", + expr.as_simple_path ().as_string ().c_str ()); return; } @@ -250,17 +335,33 @@ Late::visit (AST::TypePath &type) // maybe we can overload `resolve_path<Namespace::Types>` to only do // typepath-like path resolution? that sounds good - auto str = type.get_segments ().back ()->get_ident_segment ().as_string (); - auto values = ctx.types.peek ().get_values (); + DefaultResolver::visit (type); - if (auto resolved = ctx.types.get (str)) - ctx.map_usage (Usage (type.get_node_id ()), - Definition (resolved->get_node_id ())); - else - rust_error_at (type.get_locus (), "could not resolve type path %qs", - str.c_str ()); + // take care of only simple cases + // TODO: remove this? + rust_assert (!type.has_opening_scope_resolution_op ()); - DefaultResolver::visit (type); + // this *should* mostly work + // TODO: make sure typepath-like path resolution (?) is working + auto resolved = ctx.resolve_path (type.get_segments (), Namespace::Types); + + if (!resolved.has_value ()) + { + if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) + rust_error_at (type.get_locus (), "could not resolve type path %qs", + type.as_string ().c_str ()); + return; + } + + if (resolved->is_ambiguous ()) + { + rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", + type.as_string ().c_str ()); + return; + } + + ctx.map_usage (Usage (type.get_node_id ()), + Definition (resolved->get_node_id ())); } void @@ -286,7 +387,12 @@ Late::visit (AST::StructStruct &s) void Late::visit (AST::StructExprStruct &s) { - auto resolved = ctx.types.resolve_path (s.get_struct_name ().get_segments ()); + visit_outer_attrs (s); + visit_inner_attrs (s); + DefaultResolver::visit (s.get_struct_name ()); + + auto resolved + = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); @@ -295,22 +401,34 @@ Late::visit (AST::StructExprStruct &s) void Late::visit (AST::StructExprStructBase &s) { - auto resolved = ctx.types.resolve_path (s.get_struct_name ().get_segments ()); + visit_outer_attrs (s); + visit_inner_attrs (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); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); - DefaultResolver::visit (s); } void Late::visit (AST::StructExprStructFields &s) { - auto resolved = ctx.types.resolve_path (s.get_struct_name ().get_segments ()); + visit_outer_attrs (s); + visit_inner_attrs (s); + DefaultResolver::visit (s.get_struct_name ()); + if (s.has_struct_base ()) + visit (s.get_struct_base ()); + for (auto &field : s.get_fields ()) + visit (field); + + auto resolved + = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types); ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), Definition (resolved->get_node_id ())); - - DefaultResolver::visit (s); } // needed because Late::visit (AST::GenericArg &) is non-virtual @@ -345,5 +463,31 @@ Late::visit (AST::GenericArg &arg) DefaultResolver::visit (arg); } +template <class Closure> +static void +add_captures (Closure &closure, NameResolutionContext &ctx) +{ + auto vals = ctx.values.peek ().get_values (); + for (auto &val : vals) + { + ctx.mappings.add_capture (closure.get_node_id (), + val.second.get_node_id ()); + } +} + +void +Late::visit (AST::ClosureExprInner &closure) +{ + add_captures (closure, ctx); + DefaultResolver::visit (closure); +} + +void +Late::visit (AST::ClosureExprInnerTyped &closure) +{ + add_captures (closure, ctx); + DefaultResolver::visit (closure); +} + } // namespace Resolver2_0 } // namespace Rust |