aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
diff options
context:
space:
mode:
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.cc222
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 &param)
}
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