aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-10-21 14:13:47 +0000
committerGitHub <noreply@github.com>2022-10-21 14:13:47 +0000
commit490aa25d5564313c1957bf28533fe902a0aaa1f2 (patch)
tree3fee40077e3efdb231b96772bd58c02522ce6f3a /gcc
parent60b21d2f58f46c93fc33f6192682abfed62d8dd9 (diff)
parent05bd0555fa398c171acc22b6cfa1d5974202a5c7 (diff)
downloadgcc-490aa25d5564313c1957bf28533fe902a0aaa1f2.zip
gcc-490aa25d5564313c1957bf28533fe902a0aaa1f2.tar.gz
gcc-490aa25d5564313c1957bf28533fe902a0aaa1f2.tar.bz2
Merge #1608
1608: Initial support for closures r=philberty a=philberty This patch series introduces initial support for closures. Rust's implementation of closures is actually pretty clever, the function signatures for closures is driven by the specific FnTrait that the closure implements, this means a CallExpr to a closure becomes a method-call expr with the receiver type being the closure itself using the normal autoderef mechanism to do method selection for an implicit impl block. See https://github.com/rust-lang/rust/blob/7807a694c2f079fd3f395821bcc357eee8650071/library/core/src/ops/function.rs#L54-L71 The other implicit part of this is that arguments being passed to a closure _must_ be passed as a tuple. The down side of allowing libcore to specify the signatures of the closure functions is that we are limited in how we pass arguments, but using a tuple and then using similar machinery from the match-expr to restructure the parameter access to become the tuple accessors makes it look seamless. For example: ```rust let closure_annotated = |i: i32| -> i32 { i + 123 }; let i = 1; closure_annotated(i); ``` Wil generate a function and call-expr such as: ```c i32 test::main::{{closure}} (struct {{closure}} $closure, struct (i32) args) { _1 = args.__0; // this is 'i' return _1 + 123; } __attribute__((cdecl)) i32 test::main () { struct { i32 __0; } D.137; i32 D.140; const i32 a; const struct{{closure}} closure_annotated; const i32 i; try { a = 1; i = 1; D.137.__0 = i; _1 = test::main::{{closure}} (closure_annotated, D.137); <...> } finally { closure_annotated = {CLOBBER(eol)}; } } ``` Note this patch series does not implement the argument capture yet but this patch set is good start to the implementation so far. Addresses #195 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in2
-rw-r--r--gcc/rust/ast/rust-expr.h9
-rw-r--r--gcc/rust/ast/rust-path.h2
-rw-r--r--gcc/rust/backend/rust-compile-block.h6
-rw-r--r--gcc/rust/backend/rust-compile-context.h31
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc306
-rw-r--r--gcc/rust/backend/rust-compile-expr.h16
-rw-r--r--gcc/rust/backend/rust-compile-type.cc10
-rw-r--r--gcc/rust/backend/rust-mangle.cc6
-rw-r--r--gcc/rust/backend/rust-tree.h5
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc8
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.h3
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc10
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h3
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc10
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h3
-rw-r--r--gcc/rust/checks/lints/rust-lint-marklive.h5
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc113
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc810
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h746
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc18
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.h24
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.cc232
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h63
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc23
-rw-r--r--gcc/rust/hir/rust-hir-dump.cc6
-rw-r--r--gcc/rust/hir/rust-hir-dump.h3
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h213
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc37
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h68
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h9
-rw-r--r--gcc/rust/hir/tree/rust-hir.h1
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.cc58
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h48
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc15
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc315
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h10
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h2
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc32
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc69
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc98
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h79
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h23
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h40
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc71
-rw-r--r--gcc/rust/typecheck/rust-tyty.h38
-rw-r--r--gcc/rust/util/rust-lang-item.h7
-rw-r--r--gcc/testsuite/rust/execute/torture/closure1.rs18
-rw-r--r--gcc/testsuite/rust/execute/torture/closure2.rs32
51 files changed, 2455 insertions, 1305 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 5499e8c..024fe23 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -89,6 +89,8 @@ GRS_OBJS = \
rust/rust-ast-lower-base.o \
rust/rust-ast-lower-pattern.o \
rust/rust-ast-lower-item.o \
+ rust/rust-ast-lower-expr.o \
+ rust/rust-ast-lower-type.o \
rust/rust-early-name-resolver.o \
rust/rust-name-resolver.o \
rust/rust-ast-resolve.o \
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index c764f9c..c58fae5 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -2134,8 +2134,6 @@ struct ClosureParam
private:
std::vector<Attribute> outer_attrs;
std::unique_ptr<Pattern> pattern;
-
- // bool has_type_given;
std::unique_ptr<Type> type;
Location locus;
@@ -2202,19 +2200,19 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- // TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<Pattern> &get_pattern ()
{
rust_assert (pattern != nullptr);
return pattern;
}
- // TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<Type> &get_type ()
{
rust_assert (has_type_given ());
return type;
}
+
+ Location get_locus () const { return locus; }
};
// Base closure definition expression AST node - abstract
@@ -2248,6 +2246,8 @@ public:
{
outer_attrs = std::move (new_attrs);
}
+
+ bool get_has_move () const { return has_move; }
};
// Represents a non-type-specified closure expression AST node
@@ -2307,7 +2307,6 @@ public:
return closure_inner == nullptr;
}
- // TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<Expr> &get_definition_expr ()
{
rust_assert (closure_inner != nullptr);
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 80ff960..4643054 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -898,6 +898,8 @@ public:
rust_assert (has_return_type ());
return return_type;
}
+
+ Location get_locus () const { return locus; }
};
// Segment used in type path with a function argument
diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h
index cdd17f1..8f62f45 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -57,8 +57,7 @@ public:
// Empty visit for unused Expression HIR nodes.
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
- void visit (HIR::ClosureExprInner &) override {}
- void visit (HIR::ClosureExprInnerTyped &) override {}
+ void visit (HIR::ClosureExpr &) override {}
void visit (HIR::StructExprFieldIdentifier &) override {}
void visit (HIR::StructExprFieldIdentifierValue &) override {}
void visit (HIR::StructExprFieldIndexValue &) override {}
@@ -146,8 +145,7 @@ public:
// Empty visit for unused Expression HIR nodes.
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
- void visit (HIR::ClosureExprInner &) override {}
- void visit (HIR::ClosureExprInnerTyped &) override {}
+ void visit (HIR::ClosureExpr &) override {}
void visit (HIR::StructExprFieldIdentifier &) override {}
void visit (HIR::StructExprFieldIdentifierValue &) override {}
void visit (HIR::StructExprFieldIndexValue &) override {}
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 415b13e..658b9a3 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -147,6 +147,35 @@ public:
mono_fns[dId].push_back ({ref, fn});
}
+ void insert_closure_decl (const TyTy::ClosureType *ref, tree fn)
+ {
+ auto dId = ref->get_def_id ();
+ auto it = mono_closure_fns.find (dId);
+ if (it == mono_closure_fns.end ())
+ mono_closure_fns[dId] = {};
+
+ mono_closure_fns[dId].push_back ({ref, fn});
+ }
+
+ tree lookup_closure_decl (const TyTy::ClosureType *ref)
+ {
+ auto dId = ref->get_def_id ();
+ auto it = mono_closure_fns.find (dId);
+ if (it == mono_closure_fns.end ())
+ return error_mark_node;
+
+ for (auto &i : it->second)
+ {
+ const TyTy::ClosureType *t = i.first;
+ tree fn = i.second;
+
+ if (ref->is_equal (*t))
+ return fn;
+ }
+
+ return error_mark_node;
+ }
+
bool lookup_function_decl (HirId id, tree *fn, DefId dId = UNKNOWN_DEFID,
const TyTy::BaseType *ref = nullptr,
const std::string &asm_name = std::string ())
@@ -343,6 +372,8 @@ private:
std::vector<tree> loop_begin_labels;
std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
mono_fns;
+ std::map<DefId, std::vector<std::pair<const TyTy::ClosureType *, tree>>>
+ mono_closure_fns;
std::map<HirId, tree> implicit_pattern_bindings;
std::map<hashval_t, tree> main_variants;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 9ff2be6..b077a12 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1589,9 +1589,7 @@ CompileExpr::visit (HIR::CallExpr &expr)
}
// must be a tuple constructor
- bool is_fn = tyty->get_kind () == TyTy::TypeKind::FNDEF
- || tyty->get_kind () == TyTy::TypeKind::FNPTR;
- bool is_adt_ctor = !is_fn;
+ bool is_adt_ctor = tyty->get_kind () == TyTy::TypeKind::ADT;
if (is_adt_ctor)
{
rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
@@ -1692,6 +1690,14 @@ CompileExpr::visit (HIR::CallExpr &expr)
return true;
};
+ auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
+
+ // is this a closure call?
+ bool possible_trait_call
+ = generate_possible_fn_trait_call (expr, fn_address, &translated);
+ if (possible_trait_call)
+ return;
+
bool is_varadic = false;
if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
{
@@ -1699,13 +1705,13 @@ CompileExpr::visit (HIR::CallExpr &expr)
is_varadic = fn->is_varadic ();
}
- size_t required_num_args;
+ size_t required_num_args = expr.get_arguments ().size ();
if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
{
const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (tyty);
required_num_args = fn->num_params ();
}
- else
+ else if (tyty->get_kind () == TyTy::TypeKind::FNPTR)
{
const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (tyty);
required_num_args = fn->num_params ();
@@ -1746,8 +1752,7 @@ CompileExpr::visit (HIR::CallExpr &expr)
args.push_back (rvalue);
}
- // must be a call to a function
- auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
+ // must be a regular call to a function
translated = ctx->get_backend ()->call_expression (fn_address, args, nullptr,
expr.get_locus ());
}
@@ -2798,5 +2803,292 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr)
expr.get_locus ());
}
+void
+CompileExpr::visit (HIR::ClosureExpr &expr)
+{
+ TyTy::BaseType *closure_expr_ty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &closure_expr_ty))
+ {
+ rust_fatal_error (expr.get_locus (),
+ "did not resolve type for this ClosureExpr");
+ return;
+ }
+ rust_assert (closure_expr_ty->get_kind () == TyTy::TypeKind::CLOSURE);
+ TyTy::ClosureType *closure_tyty
+ = static_cast<TyTy::ClosureType *> (closure_expr_ty);
+ tree compiled_closure_tyty = TyTyResolveCompile::compile (ctx, closure_tyty);
+
+ // generate closure function
+ generate_closure_function (expr, *closure_tyty, compiled_closure_tyty);
+
+ // lets ignore state capture for now we need to instantiate the struct anyway
+ // then generate the function
+
+ std::vector<tree> vals;
+ // TODO
+ // setup argument captures based on the mode?
+
+ translated
+ = ctx->get_backend ()->constructor_expression (compiled_closure_tyty, false,
+ vals, -1, expr.get_locus ());
+}
+
+tree
+CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
+ TyTy::ClosureType &closure_tyty,
+ tree compiled_closure_tyty)
+{
+ TyTy::FnType *fn_tyty = nullptr;
+ tree compiled_fn_type
+ = generate_closure_fntype (expr, closure_tyty, compiled_closure_tyty,
+ &fn_tyty);
+ if (compiled_fn_type == error_mark_node)
+ return error_mark_node;
+
+ const Resolver::CanonicalPath &parent_canonical_path
+ = closure_tyty.get_ident ().path;
+ Resolver::CanonicalPath path = parent_canonical_path.append (
+ Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "{{closure}}"));
+
+ std::string ir_symbol_name = path.get ();
+ std::string asm_name = ctx->mangle_item (&closure_tyty, path);
+
+ unsigned int flags = 0;
+ tree fndecl
+ = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name,
+ flags, expr.get_locus ());
+
+ // insert into the context
+ ctx->insert_function_decl (fn_tyty, fndecl);
+ ctx->insert_closure_decl (&closure_tyty, fndecl);
+
+ // setup the parameters
+ std::vector<Bvariable *> param_vars;
+
+ // closure self
+ Bvariable *self_param
+ = ctx->get_backend ()->parameter_variable (fndecl, "$closure",
+ compiled_closure_tyty,
+ expr.get_locus ());
+ DECL_ARTIFICIAL (self_param->get_decl ()) = 1;
+ param_vars.push_back (self_param);
+
+ // setup the implicit argument captures
+ // TODO
+
+ // args tuple
+ tree args_type
+ = TyTyResolveCompile::compile (ctx, &closure_tyty.get_parameters ());
+ Bvariable *args_param
+ = ctx->get_backend ()->parameter_variable (fndecl, "args", args_type,
+ expr.get_locus ());
+ param_vars.push_back (args_param);
+
+ // setup the implicit mappings for the arguments. Since argument passing to
+ // closure functions is done via passing a tuple but the closure body expects
+ // just normal arguments this means we need to destructure them similar to
+ // what we do in MatchExpr's. This means when we have a closure-param of a we
+ // actually setup the destructure to take from the args tuple
+
+ tree args_param_expr = args_param->get_tree (expr.get_locus ());
+ size_t i = 0;
+ for (auto &closure_param : expr.get_params ())
+ {
+ tree compiled_param_var = ctx->get_backend ()->struct_field_expression (
+ args_param_expr, i, closure_param.get_locus ());
+
+ const HIR::Pattern &param_pattern = *closure_param.get_pattern ();
+ ctx->insert_pattern_binding (
+ param_pattern.get_pattern_mappings ().get_hirid (), compiled_param_var);
+ i++;
+ }
+
+ if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
+ return error_mark_node;
+
+ // lookup locals
+ HIR::Expr *function_body = expr.get_expr ().get ();
+ auto body_mappings = function_body->get_mappings ();
+ Resolver::Rib *rib = nullptr;
+ bool ok
+ = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib);
+ rust_assert (ok);
+
+ std::vector<Bvariable *> locals
+ = compile_locals_for_block (ctx, *rib, fndecl);
+
+ tree enclosing_scope = NULL_TREE;
+ Location start_location = function_body->get_locus ();
+ Location end_location = function_body->get_locus ();
+ bool is_block_expr
+ = function_body->get_expression_type () == HIR::Expr::ExprType::Block;
+ if (is_block_expr)
+ {
+ HIR::BlockExpr *body = static_cast<HIR::BlockExpr *> (function_body);
+ start_location = body->get_locus ();
+ end_location = body->get_end_locus ();
+ }
+
+ tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals,
+ start_location, end_location);
+ ctx->push_block (code_block);
+
+ TyTy::BaseType *tyret = &closure_tyty.get_result_type ();
+ bool function_has_return = !closure_tyty.get_result_type ().is_unit ();
+ Bvariable *return_address = nullptr;
+ if (function_has_return)
+ {
+ tree return_type = TyTyResolveCompile::compile (ctx, tyret);
+
+ bool address_is_taken = false;
+ tree ret_var_stmt = NULL_TREE;
+
+ return_address = ctx->get_backend ()->temporary_variable (
+ fndecl, code_block, return_type, NULL, address_is_taken,
+ expr.get_locus (), &ret_var_stmt);
+
+ ctx->add_statement (ret_var_stmt);
+ }
+
+ ctx->push_fn (fndecl, return_address);
+
+ if (is_block_expr)
+ {
+ HIR::BlockExpr *body = static_cast<HIR::BlockExpr *> (function_body);
+ compile_function_body (ctx, fndecl, *body, true);
+ }
+ else
+ {
+ tree value = CompileExpr::Compile (function_body, ctx);
+ tree return_expr
+ = ctx->get_backend ()->return_statement (fndecl, {value},
+ function_body->get_locus ());
+ ctx->add_statement (return_expr);
+ }
+
+ tree bind_tree = ctx->pop_block ();
+
+ gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
+ DECL_SAVED_TREE (fndecl) = bind_tree;
+
+ ctx->pop_fn ();
+ ctx->push_function (fndecl);
+
+ return fndecl;
+}
+
+tree
+CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr,
+ const TyTy::ClosureType &closure_tyty,
+ tree compiled_closure_tyty,
+ TyTy::FnType **fn_tyty)
+{
+ // grab the specified_bound
+ rust_assert (closure_tyty.num_specified_bounds () == 1);
+ const TyTy::TypeBoundPredicate &predicate
+ = *closure_tyty.get_specified_bounds ().begin ();
+
+ // ensure the fn_once_output associated type is set
+ closure_tyty.setup_fn_once_output ();
+
+ // the function signature is based on the trait bound that the closure
+ // implements which is determined at the type resolution time
+ //
+ // https://github.com/rust-lang/rust/blob/7807a694c2f079fd3f395821bcc357eee8650071/library/core/src/ops/function.rs#L54-L71
+
+ TyTy::TypeBoundPredicateItem item = TyTy::TypeBoundPredicateItem::error ();
+ if (predicate.get_name ().compare ("FnOnce") == 0)
+ {
+ item = predicate.lookup_associated_item ("call_once");
+ }
+ else if (predicate.get_name ().compare ("FnMut") == 0)
+ {
+ item = predicate.lookup_associated_item ("call_mut");
+ }
+ else if (predicate.get_name ().compare ("Fn") == 0)
+ {
+ item = predicate.lookup_associated_item ("call");
+ }
+ else
+ {
+ // FIXME error message?
+ gcc_unreachable ();
+ return error_mark_node;
+ }
+
+ rust_assert (!item.is_error ());
+
+ TyTy::BaseType *item_tyty = item.get_tyty_for_receiver (&closure_tyty);
+ rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
+ *fn_tyty = static_cast<TyTy::FnType *> (item_tyty);
+ return TyTyResolveCompile::compile (ctx, item_tyty);
+}
+
+bool
+CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr,
+ tree receiver, tree *result)
+{
+ TyTy::FnType *fn_sig = nullptr;
+ bool found_overload = ctx->get_tyctx ()->lookup_operator_overload (
+ expr.get_mappings ().get_hirid (), &fn_sig);
+ if (!found_overload)
+ return false;
+
+ auto id = fn_sig->get_ty_ref ();
+ auto dId = fn_sig->get_id ();
+
+ tree function = error_mark_node;
+ bool found_closure = ctx->lookup_function_decl (id, &function, dId, fn_sig);
+ if (!found_closure)
+ {
+ // something went wrong we still return true as this was meant to be an fn
+ // trait call
+ *result = error_mark_node;
+ return true;
+ }
+
+ // need to apply any autoderef's to the self argument
+ HirId autoderef_mappings_id = expr.get_mappings ().get_hirid ();
+ std::vector<Resolver::Adjustment> *adjustments = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id,
+ &adjustments);
+ rust_assert (ok);
+
+ // apply adjustments for the fn call
+ tree self = resolve_adjustements (*adjustments, receiver, expr.get_locus ());
+
+ // resolve the arguments
+ std::vector<tree> tuple_arg_vals;
+ for (auto &argument : expr.get_arguments ())
+ {
+ auto rvalue = CompileExpr::Compile (argument.get (), ctx);
+ tuple_arg_vals.push_back (rvalue);
+ }
+
+ // this is always the 2nd argument in the function signature
+ tree fnty = TREE_TYPE (function);
+ tree fn_arg_tys = TYPE_ARG_TYPES (fnty);
+ tree tuple_args_tyty_chain = TREE_CHAIN (fn_arg_tys);
+ tree tuple_args_tyty = TREE_VALUE (tuple_args_tyty_chain);
+
+ tree tuple_args
+ = ctx->get_backend ()->constructor_expression (tuple_args_tyty, false,
+ tuple_arg_vals, -1,
+ expr.get_locus ());
+
+ // args are always self, and the tuple of the args we are passing where
+ // self is the path of the call-expr in this case the fn_address
+ std::vector<tree> args;
+ args.push_back (self);
+ args.push_back (tuple_args);
+
+ tree call_address = address_expression (function, expr.get_locus ());
+ *result = ctx->get_backend ()->call_expression (call_address, args,
+ nullptr /* static chain ?*/,
+ expr.get_locus ());
+ return true;
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index f5cb06d..a259daf 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -67,10 +67,9 @@ public:
void visit (HIR::RangeToExpr &expr) override;
void visit (HIR::RangeFullExpr &expr) override;
void visit (HIR::RangeFromToInclExpr &expr) override;
+ void visit (HIR::ClosureExpr &expr) override;
// TODO
- void visit (HIR::ClosureExprInner &) override {}
- void visit (HIR::ClosureExprInnerTyped &) override {}
void visit (HIR::ErrorPropagationExpr &) override {}
void visit (HIR::RangeToInclExpr &) override {}
void visit (HIR::ForLoopExpr &) override {}
@@ -143,6 +142,19 @@ protected:
const TyTy::ArrayType &array_tyty, tree array_type,
HIR::ArrayElemsCopied &elems);
+protected:
+ tree generate_closure_function (HIR::ClosureExpr &expr,
+ TyTy::ClosureType &closure_tyty,
+ tree compiled_closure_tyty);
+
+ tree generate_closure_fntype (HIR::ClosureExpr &expr,
+ const TyTy::ClosureType &closure_tyty,
+ tree compiled_closure_tyty,
+ TyTy::FnType **fn_tyty);
+
+ bool generate_possible_fn_trait_call (HIR::CallExpr &expr, tree receiver,
+ tree *result);
+
private:
CompileExpr (Context *ctx);
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 77d8474..5e56e0a 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -97,9 +97,15 @@ TyTyResolveCompile::visit (const TyTy::InferType &)
}
void
-TyTyResolveCompile::visit (const TyTy::ClosureType &)
+TyTyResolveCompile::visit (const TyTy::ClosureType &type)
{
- gcc_unreachable ();
+ std::vector<Backend::typed_identifier> fields;
+ tree type_record = ctx->get_backend ()->struct_type (fields);
+ RS_CLOSURE_FLAG (type_record) = 1;
+
+ std::string named_struct_str = type.get_ident ().path.get () + "{{closure}}";
+ translated = ctx->get_backend ()->named_type (named_struct_str, type_record,
+ type.get_ident ().locus);
}
void
diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc
index 4d20207..83aefa7 100644
--- a/gcc/rust/backend/rust-mangle.cc
+++ b/gcc/rust/backend/rust-mangle.cc
@@ -13,6 +13,8 @@ static const std::string kMangledRef = "$RF$";
static const std::string kMangledPtr = "$BP$";
static const std::string kMangledLeftSqParen = "$u5b$"; // [
static const std::string kMangledRightSqParen = "$u5d$"; // ]
+static const std::string kMangledLeftBrace = "$u7b$"; // {
+static const std::string kMangledRightBrace = "$u7d$"; // }
static const std::string kQualPathBegin = "_" + kMangledSubstBegin;
static const std::string kMangledComma = "$C$";
@@ -66,6 +68,10 @@ legacy_mangle_name (const std::string &name)
m = kMangledLeftSqParen;
else if (c == ']')
m = kMangledRightSqParen;
+ else if (c == '{')
+ m = kMangledLeftBrace;
+ else if (c == '}')
+ m = kMangledRightBrace;
else if (c == ',')
m = kMangledComma;
else if (c == ':')
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 378254c..4a11016 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -82,6 +82,11 @@
#define SLICE_TYPE_P(TYPE) \
(TREE_CODE (TYPE) == RECORD_TYPE && TREE_LANG_FLAG_0 (TYPE))
+// lambda?
+#define RS_CLOSURE_FLAG TREE_LANG_FLAG_1
+#define RS_CLOSURE_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == RECORD_TYPE && TREE_LANG_FLAG_1 (TYPE))
+
/* Returns true if NODE is a pointer to member function type. */
#define TYPE_PTRMEMFUNC_P(NODE) \
(TREE_CODE (NODE) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (NODE))
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 35fde40..a828058 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -408,7 +408,7 @@ PrivacyReporter::visit (HIR::FieldAccessExpr &expr)
}
void
-PrivacyReporter::visit (HIR::ClosureExprInner &expr)
+PrivacyReporter::visit (HIR::ClosureExpr &expr)
{
// Not handled yet
}
@@ -425,12 +425,6 @@ PrivacyReporter::visit (HIR::BlockExpr &expr)
}
void
-PrivacyReporter::visit (HIR::ClosureExprInnerTyped &expr)
-{
- // Not handled yet
-}
-
-void
PrivacyReporter::visit (HIR::ContinueExpr &expr)
{}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 546b108..38a5f08 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -83,8 +83,7 @@ types
virtual void visit (HIR::QualifiedPathInExpression &expr);
virtual void visit (HIR::PathInExpression &expr);
- virtual void visit (HIR::ClosureExprInnerTyped &);
- virtual void visit (HIR::ClosureExprInner &expr);
+ virtual void visit (HIR::ClosureExpr &expr);
virtual void visit (HIR::StructExprStructFields &);
virtual void visit (HIR::StructExprStruct &);
virtual void visit (HIR::LiteralExpr &expr);
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index a2a6dc2..3254a98 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -382,8 +382,10 @@ ConstChecker::visit (FieldAccessExpr &expr)
}
void
-ConstChecker::visit (ClosureExprInner &expr)
-{}
+ConstChecker::visit (ClosureExpr &expr)
+{
+ expr.get_expr ()->accept_vis (*this);
+}
void
ConstChecker::visit (BlockExpr &expr)
@@ -396,10 +398,6 @@ ConstChecker::visit (BlockExpr &expr)
}
void
-ConstChecker::visit (ClosureExprInnerTyped &expr)
-{}
-
-void
ConstChecker::visit (ContinueExpr &expr)
{}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index 90b675b..f0175df 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -111,9 +111,8 @@ private:
virtual void visit (CallExpr &expr) override;
virtual void visit (MethodCallExpr &expr) override;
virtual void visit (FieldAccessExpr &expr) override;
- virtual void visit (ClosureExprInner &expr) override;
+ virtual void visit (ClosureExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
- virtual void visit (ClosureExprInnerTyped &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
virtual void visit (RangeFromToExpr &expr) override;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index e3f3253..55a2159 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -453,8 +453,10 @@ UnsafeChecker::visit (FieldAccessExpr &expr)
}
void
-UnsafeChecker::visit (ClosureExprInner &expr)
-{}
+UnsafeChecker::visit (ClosureExpr &expr)
+{
+ expr.get_expr ()->accept_vis (*this);
+}
void
UnsafeChecker::visit (BlockExpr &expr)
@@ -467,10 +469,6 @@ UnsafeChecker::visit (BlockExpr &expr)
}
void
-UnsafeChecker::visit (ClosureExprInnerTyped &expr)
-{}
-
-void
UnsafeChecker::visit (ContinueExpr &expr)
{}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index ae1eb509..fe564a2 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -88,9 +88,8 @@ private:
virtual void visit (CallExpr &expr) override;
virtual void visit (MethodCallExpr &expr) override;
virtual void visit (FieldAccessExpr &expr) override;
- virtual void visit (ClosureExprInner &expr) override;
+ virtual void visit (ClosureExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
- virtual void visit (ClosureExprInnerTyped &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
virtual void visit (RangeFromToExpr &expr) override;
diff --git a/gcc/rust/checks/lints/rust-lint-marklive.h b/gcc/rust/checks/lints/rust-lint-marklive.h
index 119af8b..ed5ed13 100644
--- a/gcc/rust/checks/lints/rust-lint-marklive.h
+++ b/gcc/rust/checks/lints/rust-lint-marklive.h
@@ -285,6 +285,11 @@ public:
item->accept_vis (*this);
}
+ void visit (HIR::ClosureExpr &expr) override
+ {
+ expr.get_expr ()->accept_vis (*this);
+ }
+
private:
std::vector<HirId> worklist;
std::set<HirId> liveSymbols;
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index d52d108..592d9e8 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -658,119 +658,6 @@ ASTLoweringBase::lower_self (AST::SelfParam &self)
self.get_locus ());
}
-void
-ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment)
-{
- std::vector<HIR::GenericArgsBinding> binding_args; // TODO
-
- std::string segment_name = segment.get_ident_segment ().as_string ();
- bool has_separating_scope_resolution
- = segment.get_separating_scope_resolution ();
-
- auto generic_args = lower_generic_args (segment.get_generic_args ());
-
- auto crate_num = mappings->get_current_crate ();
- auto hirid = mappings->get_next_hir_id (crate_num);
- Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
- UNKNOWN_LOCAL_DEFID);
-
- translated_segment
- = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name,
- has_separating_scope_resolution,
- generic_args, segment.get_locus ());
-}
-
-void
-ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
-{
- auto crate_num = mappings->get_current_crate ();
- auto hirid = mappings->get_next_hir_id (crate_num);
- Analysis::NodeMapping qual_mappings (
- crate_num, path.get_qualified_path_type ().get_node_id (), hirid,
- UNKNOWN_LOCAL_DEFID);
-
- HIR::Type *qual_type = ASTLoweringType::translate (
- path.get_qualified_path_type ().get_type ().get ());
- HIR::TypePath *qual_trait = ASTLowerTypePath::translate (
- path.get_qualified_path_type ().get_as_type_path ());
-
- HIR::QualifiedPathType qual_path_type (
- qual_mappings, std::unique_ptr<HIR::Type> (qual_type),
- std::unique_ptr<HIR::TypePath> (qual_trait),
- path.get_qualified_path_type ().get_locus ());
-
- translated_segment = nullptr;
- path.get_associated_segment ()->accept_vis (*this);
- if (translated_segment == nullptr)
- {
- rust_fatal_error (path.get_associated_segment ()->get_locus (),
- "failed to translate AST TypePathSegment");
- return;
- }
- std::unique_ptr<HIR::TypePathSegment> associated_segment (translated_segment);
-
- std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
- for (auto &seg : path.get_segments ())
- {
- translated_segment = nullptr;
- seg->accept_vis (*this);
- if (translated_segment == nullptr)
- {
- rust_fatal_error (seg->get_locus (),
- "failed to translte AST TypePathSegment");
- }
- translated_segments.push_back (
- std::unique_ptr<HIR::TypePathSegment> (translated_segment));
- }
-
- Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
- mappings->get_next_localdef_id (crate_num));
- translated = new HIR::QualifiedPathInType (std::move (mapping),
- std::move (qual_path_type),
- std::move (associated_segment),
- std::move (translated_segments),
- path.get_locus ());
-}
-
-void
-ASTLoweringType::visit (AST::TraitObjectTypeOneBound &type)
-{
- std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
- HIR::TypeParamBound *translated_bound
- = ASTLoweringTypeBounds::translate (&type.get_trait_bound ());
- bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (translated_bound));
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- mappings->get_next_localdef_id (crate_num));
-
- translated = new HIR::TraitObjectType (mapping, std::move (bounds),
- type.get_locus (), type.is_dyn ());
-}
-
-void
-ASTLoweringType::visit (AST::TraitObjectType &type)
-{
- std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
-
- for (auto &bound : type.get_type_param_bounds ())
- {
- HIR::TypeParamBound *translated_bound
- = ASTLoweringTypeBounds::translate (bound.get ());
- bounds.push_back (
- std::unique_ptr<HIR::TypeParamBound> (translated_bound));
- }
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- mappings->get_next_localdef_id (crate_num));
-
- translated = new HIR::TraitObjectType (mapping, std::move (bounds),
- type.get_locus (), type.is_dyn ());
-}
-
HIR::Type *
ASTLoweringBase::lower_type_no_bounds (AST::TypeNoBounds *type)
{
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 5479e63..16fe13c8 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -313,6 +313,8 @@ protected:
HIR::Literal lower_literal (const AST::Literal &literal);
HIR::ExternBlock *lower_extern_block (AST::ExternBlock &extern_block);
+
+ HIR::ClosureParam lower_closure_param (AST::ClosureParam &param);
};
} // namespace HIR
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
new file mode 100644
index 0000000..df4ba9d
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -0,0 +1,810 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast-lower-expr.h"
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-struct-field-expr.h"
+#include "rust-ast-lower-pattern.h"
+#include "rust-ast-lower-type.h"
+
+namespace Rust {
+namespace HIR {
+
+ASTLoweringExpr::ASTLoweringExpr ()
+ : ASTLoweringBase (), translated (nullptr), translated_array_elems (nullptr),
+ terminated (false)
+{}
+
+HIR::Expr *
+ASTLoweringExpr::translate (AST::Expr *expr, bool *terminated)
+{
+ ASTLoweringExpr resolver;
+ expr->accept_vis (resolver);
+ if (resolver.translated == nullptr)
+ {
+ rust_fatal_error (expr->get_locus (), "Failed to lower expr: [%s]",
+ expr->as_string ().c_str ());
+ return nullptr;
+ }
+
+ resolver.mappings->insert_hir_expr (resolver.translated);
+ resolver.mappings->insert_location (
+ resolver.translated->get_mappings ().get_hirid (), expr->get_locus ());
+
+ if (terminated != nullptr)
+ *terminated = resolver.terminated;
+
+ return resolver.translated;
+}
+
+void
+ASTLoweringExpr::visit (AST::TupleIndexExpr &expr)
+{
+ HIR::Expr *tuple_expr
+ = ASTLoweringExpr::translate (expr.get_tuple_expr ().get (), &terminated);
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::TupleIndexExpr (mapping, std::unique_ptr<HIR::Expr> (tuple_expr),
+ expr.get_tuple_index (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::TupleExpr &expr)
+{
+ std::vector<std::unique_ptr<HIR::Expr> > tuple_elements;
+ for (auto &e : expr.get_tuple_elems ())
+ {
+ HIR::Expr *t = ASTLoweringExpr::translate (e.get ());
+ tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::TupleExpr (std::move (mapping), std::move (tuple_elements),
+ expr.get_inner_attrs (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::IfExpr &expr)
+{
+ translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::IfExprConseqElse &expr)
+{
+ translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::IfExprConseqIf &expr)
+{
+ translated = ASTLoweringIfBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::BlockExpr &expr)
+{
+ translated = ASTLoweringBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr)
+{
+ translated = ASTLoweringBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::PathInExpression &expr)
+{
+ translated = ASTLowerPathInExpression::translate (&expr);
+}
+
+void
+ASTLoweringExpr::visit (AST::QualifiedPathInExpression &expr)
+{
+ translated = ASTLowerQualPathInExpression::translate (&expr);
+}
+
+void
+ASTLoweringExpr::visit (AST::ReturnExpr &expr)
+{
+ terminated = true;
+ HIR::Expr *return_expr
+ = expr.has_returned_expr ()
+ ? ASTLoweringExpr::translate (expr.get_returned_expr ().get ())
+ : nullptr;
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::ReturnExpr (mapping, expr.get_locus (),
+ std::unique_ptr<HIR::Expr> (return_expr));
+}
+
+void
+ASTLoweringExpr::visit (AST::CallExpr &expr)
+{
+ HIR::Expr *func
+ = ASTLoweringExpr::translate (expr.get_function_expr ().get ());
+
+ auto const &in_params = expr.get_params ();
+ std::vector<std::unique_ptr<HIR::Expr> > params;
+ for (auto &param : in_params)
+ {
+ auto trans = ASTLoweringExpr::translate (param.get ());
+ params.push_back (std::unique_ptr<HIR::Expr> (trans));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (
+ crate_num, UNKNOWN_NODEID /* this can map back to the AST*/,
+ mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::CallExpr (mapping, std::unique_ptr<HIR::Expr> (func),
+ std::move (params), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::MethodCallExpr &expr)
+{
+ HIR::PathExprSegment method_path
+ = lower_path_expr_seg (expr.get_method_name ());
+
+ HIR::Expr *receiver
+ = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
+
+ auto const &in_params = expr.get_params ();
+ std::vector<std::unique_ptr<HIR::Expr> > params;
+ for (auto &param : in_params)
+ {
+ auto trans = ASTLoweringExpr::translate (param.get ());
+ params.push_back (std::unique_ptr<HIR::Expr> (trans));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::MethodCallExpr (mapping, std::unique_ptr<HIR::Expr> (receiver),
+ method_path, std::move (params),
+ expr.get_outer_attrs (), expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::AssignmentExpr &expr)
+{
+ HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+ HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::AssignmentExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
+ std::unique_ptr<HIR::Expr> (rhs),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::IdentifierExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping1 (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+ Analysis::NodeMapping mapping2 (mapping1);
+
+ HIR::PathIdentSegment ident_seg (expr.get_ident ());
+ HIR::PathExprSegment seg (mapping1, ident_seg, expr.get_locus (),
+ HIR::GenericArgs::create_empty ());
+ translated = new HIR::PathInExpression (mapping2, {seg}, expr.get_locus (),
+ false, expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ArrayExpr &expr)
+{
+ expr.get_array_elems ()->accept_vis (*this);
+ rust_assert (translated_array_elems != nullptr);
+ HIR::ArrayElems *elems = translated_array_elems;
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::ArrayExpr (mapping, std::unique_ptr<HIR::ArrayElems> (elems),
+ expr.get_inner_attrs (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ArrayIndexExpr &expr)
+{
+ HIR::Expr *array_expr
+ = ASTLoweringExpr::translate (expr.get_array_expr ().get ());
+ HIR::Expr *array_index_expr
+ = ASTLoweringExpr::translate (expr.get_index_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::ArrayIndexExpr (mapping, std::unique_ptr<HIR::Expr> (array_expr),
+ std::unique_ptr<HIR::Expr> (array_index_expr),
+ expr.get_outer_attrs (), expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ArrayElemsValues &elems)
+{
+ std::vector<std::unique_ptr<HIR::Expr> > elements;
+ for (auto &elem : elems.get_values ())
+ {
+ HIR::Expr *translated_elem = ASTLoweringExpr::translate (elem.get ());
+ elements.push_back (std::unique_ptr<HIR::Expr> (translated_elem));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (mappings->get_current_crate (),
+ elems.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated_array_elems
+ = new HIR::ArrayElemsValues (mapping, std::move (elements));
+}
+
+void
+ASTLoweringExpr::visit (AST::ArrayElemsCopied &elems)
+{
+ HIR::Expr *element
+ = ASTLoweringExpr::translate (elems.get_elem_to_copy ().get ());
+ HIR::Expr *num_copies
+ = ASTLoweringExpr::translate (elems.get_num_copies ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (mappings->get_current_crate (),
+ elems.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated_array_elems
+ = new HIR::ArrayElemsCopied (mapping, std::unique_ptr<HIR::Expr> (element),
+ std::unique_ptr<HIR::Expr> (num_copies));
+}
+
+void
+ASTLoweringExpr::visit (AST::LiteralExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Literal l = lower_literal (expr.get_literal ());
+ translated = new HIR::LiteralExpr (mapping, std::move (l), expr.get_locus (),
+ expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ArithmeticOrLogicalExpr &expr)
+{
+ HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+ rust_assert (lhs != nullptr);
+ HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+ rust_assert (rhs != nullptr);
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::ArithmeticOrLogicalExpr (
+ mapping, std::unique_ptr<HIR::Expr> (lhs), std::unique_ptr<HIR::Expr> (rhs),
+ expr.get_expr_type (), expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ComparisonExpr &expr)
+{
+ HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+ rust_assert (lhs != nullptr);
+ HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+ rust_assert (rhs != nullptr);
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::ComparisonExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
+ std::unique_ptr<HIR::Expr> (rhs),
+ expr.get_expr_type (), expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::LazyBooleanExpr &expr)
+{
+ HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+ rust_assert (lhs != nullptr);
+ HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+ rust_assert (rhs != nullptr);
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::LazyBooleanExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
+ std::unique_ptr<HIR::Expr> (rhs),
+ expr.get_expr_type (), expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::NegationExpr &expr)
+{
+ HIR::Expr *negated_value
+ = ASTLoweringExpr::translate (expr.get_negated_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+ translated
+ = new HIR::NegationExpr (mapping,
+ std::unique_ptr<HIR::Expr> (negated_value),
+ expr.get_expr_type (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::TypeCastExpr &expr)
+{
+ HIR::Expr *expr_to_cast_to
+ = ASTLoweringExpr::translate (expr.get_casted_expr ().get ());
+ HIR::Type *type_to_cast_to
+ = lower_type_no_bounds (expr.get_type_to_cast_to ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::TypeCastExpr (mapping,
+ std::unique_ptr<HIR::Expr> (expr_to_cast_to),
+ std::unique_ptr<HIR::Type> (type_to_cast_to),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::CompoundAssignmentExpr &expr)
+{
+ ArithmeticOrLogicalOperator op;
+ switch (expr.get_expr_type ())
+ {
+ case CompoundAssignmentOperator::ADD:
+ op = ArithmeticOrLogicalOperator::ADD;
+ break;
+ case CompoundAssignmentOperator::SUBTRACT:
+ op = ArithmeticOrLogicalOperator::SUBTRACT;
+ break;
+ case CompoundAssignmentOperator::MULTIPLY:
+ op = ArithmeticOrLogicalOperator::MULTIPLY;
+ break;
+ case CompoundAssignmentOperator::DIVIDE:
+ op = ArithmeticOrLogicalOperator::DIVIDE;
+ break;
+ case CompoundAssignmentOperator::MODULUS:
+ op = ArithmeticOrLogicalOperator::MODULUS;
+ break;
+ case CompoundAssignmentOperator::BITWISE_AND:
+ op = ArithmeticOrLogicalOperator::BITWISE_AND;
+ break;
+ case CompoundAssignmentOperator::BITWISE_OR:
+ op = ArithmeticOrLogicalOperator::BITWISE_OR;
+ break;
+ case CompoundAssignmentOperator::BITWISE_XOR:
+ op = ArithmeticOrLogicalOperator::BITWISE_XOR;
+ break;
+ case CompoundAssignmentOperator::LEFT_SHIFT:
+ op = ArithmeticOrLogicalOperator::LEFT_SHIFT;
+ break;
+ case CompoundAssignmentOperator::RIGHT_SHIFT:
+ op = ArithmeticOrLogicalOperator::RIGHT_SHIFT;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ HIR::Expr *asignee_expr
+ = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+ HIR::Expr *value = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::CompoundAssignmentExpr (
+ mapping, std::unique_ptr<HIR::Expr> (asignee_expr),
+ std::unique_ptr<HIR::Expr> (value), op, expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::StructExprStruct &struct_expr)
+{
+ HIR::PathInExpression *path
+ = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
+ HIR::PathInExpression copied_path (*path);
+ delete path;
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::StructExprStruct (mapping, copied_path,
+ struct_expr.get_inner_attrs (),
+ struct_expr.get_outer_attrs (),
+ struct_expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr)
+{
+ // bit of a hack for now
+ HIR::PathInExpression *path
+ = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
+ HIR::PathInExpression copied_path (*path);
+ delete path;
+
+ HIR::StructBase *base = nullptr;
+ if (struct_expr.has_struct_base ())
+ {
+ HIR::Expr *translated_base = ASTLoweringExpr::translate (
+ struct_expr.get_struct_base ().get_base_struct ().get ());
+ base = new HIR::StructBase (std::unique_ptr<HIR::Expr> (translated_base));
+ }
+
+ auto const &in_fields = struct_expr.get_fields ();
+ std::vector<std::unique_ptr<HIR::StructExprField> > fields;
+ for (auto &field : in_fields)
+ {
+ HIR::StructExprField *translated
+ = ASTLowerStructExprField::translate (field.get ());
+ fields.push_back (std::unique_ptr<HIR::StructExprField> (translated));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::StructExprStructFields (mapping, copied_path, std::move (fields),
+ struct_expr.get_locus (), base,
+ struct_expr.get_inner_attrs (),
+ struct_expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExpr::visit (AST::GroupedExpr &expr)
+{
+ HIR::Expr *paren_expr
+ = ASTLoweringExpr::translate (expr.get_expr_in_parens ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::GroupedExpr (mapping, std::unique_ptr<HIR::Expr> (paren_expr),
+ expr.get_inner_attrs (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::FieldAccessExpr &expr)
+{
+ HIR::Expr *receiver
+ = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+ translated
+ = new HIR::FieldAccessExpr (mapping, std::unique_ptr<HIR::Expr> (receiver),
+ expr.get_field_name (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::LoopExpr &expr)
+{
+ translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::WhileLoopExpr &expr)
+{
+ translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::ForLoopExpr &expr)
+{
+ translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::BreakExpr &expr)
+{
+ HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+ HIR::Expr *break_expr
+ = expr.has_break_expr ()
+ ? ASTLoweringExpr::translate (expr.get_break_expr ().get ())
+ : nullptr;
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::BreakExpr (mapping, expr.get_locus (), std ::move (break_label),
+ std::unique_ptr<HIR::Expr> (break_expr),
+ expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ContinueExpr &expr)
+{
+ HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::ContinueExpr (mapping, expr.get_locus (),
+ std ::move (break_label), expr.get_outer_attrs ());
+}
+
+void
+ASTLoweringExpr::visit (AST::BorrowExpr &expr)
+{
+ HIR::Expr *borrow_lvalue
+ = ASTLoweringExpr::translate (expr.get_borrowed_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::BorrowExpr *borrow_expr
+ = new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue),
+ expr.get_is_mut () ? Mutability::Mut
+ : Mutability::Imm,
+ expr.get_outer_attrs (), expr.get_locus ());
+
+ if (expr.get_is_double_borrow ())
+ {
+ NodeId artifical_bouble_borrow_id = mappings->get_next_node_id ();
+ Analysis::NodeMapping mapping (crate_num, artifical_bouble_borrow_id,
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ borrow_expr
+ = new HIR::BorrowExpr (mapping,
+ std::unique_ptr<HIR::Expr> (borrow_expr),
+ expr.get_is_mut () ? Mutability::Mut
+ : Mutability::Imm,
+ expr.get_outer_attrs (), expr.get_locus ());
+ }
+
+ translated = borrow_expr;
+}
+
+void
+ASTLoweringExpr::visit (AST::DereferenceExpr &expr)
+{
+ HIR::Expr *dref_lvalue
+ = ASTLoweringExpr::translate (expr.get_dereferenced_expr ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::DereferenceExpr (mapping,
+ std::unique_ptr<HIR::Expr> (dref_lvalue),
+ expr.get_outer_attrs (), expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::MatchExpr &expr)
+{
+ translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
+}
+
+void
+ASTLoweringExpr::visit (AST::RangeFromToExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_from
+ = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+ HIR::Expr *range_to = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+ translated
+ = new HIR::RangeFromToExpr (mapping,
+ std::unique_ptr<HIR::Expr> (range_from),
+ std::unique_ptr<HIR::Expr> (range_to),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::RangeFromExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_from
+ = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+
+ translated
+ = new HIR::RangeFromExpr (mapping, std::unique_ptr<HIR::Expr> (range_from),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::RangeToExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_to = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+ translated
+ = new HIR::RangeToExpr (mapping, std::unique_ptr<HIR::Expr> (range_to),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::RangeFullExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::RangeFullExpr (mapping, expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::RangeFromToInclExpr &expr)
+{
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *range_from
+ = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
+ HIR::Expr *range_to = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
+
+ translated
+ = new HIR::RangeFromToInclExpr (mapping,
+ std::unique_ptr<HIR::Expr> (range_from),
+ std::unique_ptr<HIR::Expr> (range_to),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ClosureExprInner &expr)
+{
+ HIR::Expr *closure_expr
+ = ASTLoweringExpr::translate (expr.get_definition_expr ().get ());
+
+ std::vector<HIR::ClosureParam> closure_params;
+ for (auto &param : expr.get_params ())
+ {
+ HIR::ClosureParam p = lower_closure_param (param);
+ closure_params.push_back (std::move (p));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated
+ = new HIR::ClosureExpr (mapping, std::move (closure_params),
+ nullptr /* closure_return_type */,
+ std::unique_ptr<HIR::Expr> (closure_expr),
+ expr.get_has_move (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+void
+ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr)
+{
+ HIR::Type *closure_return_type = nullptr;
+ HIR::Expr *closure_expr
+ = ASTLoweringExpr::translate (expr.get_definition_block ().get ());
+
+ std::vector<HIR::ClosureParam> closure_params;
+ for (auto &param : expr.get_params ())
+ {
+ HIR::ClosureParam p = lower_closure_param (param);
+ closure_params.push_back (std::move (p));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated
+ = new HIR::ClosureExpr (mapping, std::move (closure_params),
+ std::unique_ptr<HIR::Type> (closure_return_type),
+ std::unique_ptr<HIR::Expr> (closure_expr),
+ expr.get_has_move (), expr.get_outer_attrs (),
+ expr.get_locus ());
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index be045e9..0963e40 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -19,11 +19,7 @@
#ifndef RUST_AST_LOWER_EXPR
#define RUST_AST_LOWER_EXPR
-#include "rust-diagnostics.h"
#include "rust-ast-lower-base.h"
-#include "rust-ast-lower-block.h"
-#include "rust-ast-lower-struct-field-expr.h"
-#include "rust-ast-lower-pattern.h"
namespace Rust {
namespace HIR {
@@ -76,703 +72,55 @@ class ASTLoweringExpr : public ASTLoweringBase
using Rust::HIR::ASTLoweringBase::visit;
public:
- static HIR::Expr *translate (AST::Expr *expr, bool *terminated = nullptr)
- {
- ASTLoweringExpr resolver;
- expr->accept_vis (resolver);
- if (resolver.translated == nullptr)
- {
- rust_fatal_error (expr->get_locus (), "Failed to lower expr: [%s]",
- expr->as_string ().c_str ());
- return nullptr;
- }
-
- resolver.mappings->insert_hir_expr (resolver.translated);
- resolver.mappings->insert_location (
- resolver.translated->get_mappings ().get_hirid (), expr->get_locus ());
-
- if (terminated != nullptr)
- *terminated = resolver.terminated;
-
- return resolver.translated;
- }
-
- void visit (AST::TupleIndexExpr &expr) override
- {
- HIR::Expr *tuple_expr
- = ASTLoweringExpr::translate (expr.get_tuple_expr ().get (), &terminated);
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::TupleIndexExpr (mapping,
- std::unique_ptr<HIR::Expr> (tuple_expr),
- expr.get_tuple_index (),
- expr.get_outer_attrs (), expr.get_locus ());
- }
-
- void visit (AST::TupleExpr &expr) override
- {
- std::vector<std::unique_ptr<HIR::Expr> > tuple_elements;
- for (auto &e : expr.get_tuple_elems ())
- {
- HIR::Expr *t = ASTLoweringExpr::translate (e.get ());
- tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t));
- }
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::TupleExpr (std::move (mapping), std::move (tuple_elements),
- expr.get_inner_attrs (), expr.get_outer_attrs (),
- expr.get_locus ());
- }
-
- void visit (AST::IfExpr &expr) override
- {
- translated = ASTLoweringIfBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::IfExprConseqElse &expr) override
- {
- translated = ASTLoweringIfBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::IfExprConseqIf &expr) override
- {
- translated = ASTLoweringIfBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::BlockExpr &expr) override
- {
- translated = ASTLoweringBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::UnsafeBlockExpr &expr) override
- {
- translated = ASTLoweringBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::PathInExpression &expr) override
- {
- translated = ASTLowerPathInExpression::translate (&expr);
- }
-
- void visit (AST::QualifiedPathInExpression &expr) override
- {
- translated = ASTLowerQualPathInExpression::translate (&expr);
- }
-
- void visit (AST::ReturnExpr &expr) override
- {
- terminated = true;
- HIR::Expr *return_expr
- = expr.has_returned_expr ()
- ? ASTLoweringExpr::translate (expr.get_returned_expr ().get ())
- : nullptr;
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::ReturnExpr (mapping, expr.get_locus (),
- std::unique_ptr<HIR::Expr> (return_expr));
- }
-
- void visit (AST::CallExpr &expr) override
- {
- HIR::Expr *func
- = ASTLoweringExpr::translate (expr.get_function_expr ().get ());
-
- auto const &in_params = expr.get_params ();
- std::vector<std::unique_ptr<HIR::Expr> > params;
- for (auto &param : in_params)
- {
- auto trans = ASTLoweringExpr::translate (param.get ());
- params.push_back (std::unique_ptr<HIR::Expr> (trans));
- }
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (
- crate_num, UNKNOWN_NODEID /* this can map back to the AST*/,
- mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::CallExpr (mapping, std::unique_ptr<HIR::Expr> (func),
- std::move (params), expr.get_outer_attrs (),
- expr.get_locus ());
- }
-
- void visit (AST::MethodCallExpr &expr) override
- {
- HIR::PathExprSegment method_path
- = lower_path_expr_seg (expr.get_method_name ());
-
- HIR::Expr *receiver
- = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
-
- auto const &in_params = expr.get_params ();
- std::vector<std::unique_ptr<HIR::Expr> > params;
- for (auto &param : in_params)
- {
- auto trans = ASTLoweringExpr::translate (param.get ());
- params.push_back (std::unique_ptr<HIR::Expr> (trans));
- }
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::MethodCallExpr (mapping, std::unique_ptr<HIR::Expr> (receiver),
- method_path, std::move (params),
- expr.get_outer_attrs (), expr.get_locus ());
- }
-
- void visit (AST::AssignmentExpr &expr) override
- {
- HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
- HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::AssignmentExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
- std::unique_ptr<HIR::Expr> (rhs),
- expr.get_locus ());
- }
-
- void visit (AST::IdentifierExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping1 (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
- Analysis::NodeMapping mapping2 (mapping1);
-
- HIR::PathIdentSegment ident_seg (expr.get_ident ());
- HIR::PathExprSegment seg (mapping1, ident_seg, expr.get_locus (),
- HIR::GenericArgs::create_empty ());
- translated = new HIR::PathInExpression (mapping2, {seg}, expr.get_locus (),
- false, expr.get_outer_attrs ());
- }
-
- void visit (AST::ArrayExpr &expr) override
- {
- expr.get_array_elems ()->accept_vis (*this);
- rust_assert (translated_array_elems != nullptr);
- HIR::ArrayElems *elems = translated_array_elems;
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::ArrayExpr (mapping, std::unique_ptr<HIR::ArrayElems> (elems),
- expr.get_inner_attrs (), expr.get_outer_attrs (),
- expr.get_locus ());
- }
-
- void visit (AST::ArrayIndexExpr &expr) override
- {
- HIR::Expr *array_expr
- = ASTLoweringExpr::translate (expr.get_array_expr ().get ());
- HIR::Expr *array_index_expr
- = ASTLoweringExpr::translate (expr.get_index_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::ArrayIndexExpr (mapping,
- std::unique_ptr<HIR::Expr> (array_expr),
- std::unique_ptr<HIR::Expr> (array_index_expr),
- expr.get_outer_attrs (), expr.get_locus ());
- }
-
- void visit (AST::ArrayElemsValues &elems) override
- {
- std::vector<std::unique_ptr<HIR::Expr> > elements;
- for (auto &elem : elems.get_values ())
- {
- HIR::Expr *translated_elem = ASTLoweringExpr::translate (elem.get ());
- elements.push_back (std::unique_ptr<HIR::Expr> (translated_elem));
- }
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (mappings->get_current_crate (),
- elems.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated_array_elems
- = new HIR::ArrayElemsValues (mapping, std::move (elements));
- }
-
- void visit (AST::ArrayElemsCopied &elems) override
- {
- HIR::Expr *element
- = ASTLoweringExpr::translate (elems.get_elem_to_copy ().get ());
- HIR::Expr *num_copies
- = ASTLoweringExpr::translate (elems.get_num_copies ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (mappings->get_current_crate (),
- elems.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated_array_elems
- = new HIR::ArrayElemsCopied (mapping,
- std::unique_ptr<HIR::Expr> (element),
- std::unique_ptr<HIR::Expr> (num_copies));
- }
-
- void visit (AST::LiteralExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- HIR::Literal l = lower_literal (expr.get_literal ());
- translated
- = new HIR::LiteralExpr (mapping, std::move (l), expr.get_locus (),
- expr.get_outer_attrs ());
- }
-
- void visit (AST::ArithmeticOrLogicalExpr &expr) override
- {
- HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
- rust_assert (lhs != nullptr);
- HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
- rust_assert (rhs != nullptr);
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::ArithmeticOrLogicalExpr (mapping,
- std::unique_ptr<HIR::Expr> (lhs),
- std::unique_ptr<HIR::Expr> (rhs),
- expr.get_expr_type (),
- expr.get_locus ());
- }
-
- void visit (AST::ComparisonExpr &expr) override
- {
- HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
- rust_assert (lhs != nullptr);
- HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
- rust_assert (rhs != nullptr);
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::ComparisonExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
- std::unique_ptr<HIR::Expr> (rhs),
- expr.get_expr_type (), expr.get_locus ());
- }
-
- void visit (AST::LazyBooleanExpr &expr) override
- {
- HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
- rust_assert (lhs != nullptr);
- HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
- rust_assert (rhs != nullptr);
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::LazyBooleanExpr (mapping, std::unique_ptr<HIR::Expr> (lhs),
- std::unique_ptr<HIR::Expr> (rhs),
- expr.get_expr_type (), expr.get_locus ());
- }
-
- void visit (AST::NegationExpr &expr) override
- {
- HIR::Expr *negated_value
- = ASTLoweringExpr::translate (expr.get_negated_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
- translated
- = new HIR::NegationExpr (mapping,
- std::unique_ptr<HIR::Expr> (negated_value),
- expr.get_expr_type (), expr.get_outer_attrs (),
- expr.get_locus ());
- }
-
- void visit (AST::TypeCastExpr &expr) override
- {
- HIR::Expr *expr_to_cast_to
- = ASTLoweringExpr::translate (expr.get_casted_expr ().get ());
- HIR::Type *type_to_cast_to
- = lower_type_no_bounds (expr.get_type_to_cast_to ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::TypeCastExpr (mapping,
- std::unique_ptr<HIR::Expr> (expr_to_cast_to),
- std::unique_ptr<HIR::Type> (type_to_cast_to),
- expr.get_locus ());
- }
-
- void visit (AST::CompoundAssignmentExpr &expr) override
- {
- ArithmeticOrLogicalOperator op;
- switch (expr.get_expr_type ())
- {
- case CompoundAssignmentOperator::ADD:
- op = ArithmeticOrLogicalOperator::ADD;
- break;
- case CompoundAssignmentOperator::SUBTRACT:
- op = ArithmeticOrLogicalOperator::SUBTRACT;
- break;
- case CompoundAssignmentOperator::MULTIPLY:
- op = ArithmeticOrLogicalOperator::MULTIPLY;
- break;
- case CompoundAssignmentOperator::DIVIDE:
- op = ArithmeticOrLogicalOperator::DIVIDE;
- break;
- case CompoundAssignmentOperator::MODULUS:
- op = ArithmeticOrLogicalOperator::MODULUS;
- break;
- case CompoundAssignmentOperator::BITWISE_AND:
- op = ArithmeticOrLogicalOperator::BITWISE_AND;
- break;
- case CompoundAssignmentOperator::BITWISE_OR:
- op = ArithmeticOrLogicalOperator::BITWISE_OR;
- break;
- case CompoundAssignmentOperator::BITWISE_XOR:
- op = ArithmeticOrLogicalOperator::BITWISE_XOR;
- break;
- case CompoundAssignmentOperator::LEFT_SHIFT:
- op = ArithmeticOrLogicalOperator::LEFT_SHIFT;
- break;
- case CompoundAssignmentOperator::RIGHT_SHIFT:
- op = ArithmeticOrLogicalOperator::RIGHT_SHIFT;
- break;
- default:
- gcc_unreachable ();
- }
-
- HIR::Expr *asignee_expr
- = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
- HIR::Expr *value
- = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::CompoundAssignmentExpr (
- mapping, std::unique_ptr<HIR::Expr> (asignee_expr),
- std::unique_ptr<HIR::Expr> (value), op, expr.get_locus ());
- }
-
- void visit (AST::StructExprStruct &struct_expr) override
- {
- HIR::PathInExpression *path
- = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
- HIR::PathInExpression copied_path (*path);
- delete path;
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::StructExprStruct (mapping, copied_path,
- struct_expr.get_inner_attrs (),
- struct_expr.get_outer_attrs (),
- struct_expr.get_locus ());
- }
-
- void visit (AST::StructExprStructFields &struct_expr) override
- {
- // bit of a hack for now
- HIR::PathInExpression *path
- = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
- HIR::PathInExpression copied_path (*path);
- delete path;
-
- HIR::StructBase *base = nullptr;
- if (struct_expr.has_struct_base ())
- {
- HIR::Expr *translated_base = ASTLoweringExpr::translate (
- struct_expr.get_struct_base ().get_base_struct ().get ());
- base
- = new HIR::StructBase (std::unique_ptr<HIR::Expr> (translated_base));
- }
-
- auto const &in_fields = struct_expr.get_fields ();
- std::vector<std::unique_ptr<HIR::StructExprField> > fields;
- for (auto &field : in_fields)
- {
- HIR::StructExprField *translated
- = ASTLowerStructExprField::translate (field.get ());
- fields.push_back (std::unique_ptr<HIR::StructExprField> (translated));
- }
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::StructExprStructFields (
- mapping, copied_path, std::move (fields), struct_expr.get_locus (), base,
- struct_expr.get_inner_attrs (), struct_expr.get_outer_attrs ());
- }
-
- void visit (AST::GroupedExpr &expr) override
- {
- HIR::Expr *paren_expr
- = ASTLoweringExpr::translate (expr.get_expr_in_parens ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::GroupedExpr (mapping, std::unique_ptr<HIR::Expr> (paren_expr),
- expr.get_inner_attrs (), expr.get_outer_attrs (),
- expr.get_locus ());
- }
-
- void visit (AST::FieldAccessExpr &expr) override
- {
- HIR::Expr *receiver
- = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
- translated
- = new HIR::FieldAccessExpr (mapping,
- std::unique_ptr<HIR::Expr> (receiver),
- expr.get_field_name (),
- expr.get_outer_attrs (), expr.get_locus ());
- }
-
- void visit (AST::LoopExpr &expr) override
- {
- translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::WhileLoopExpr &expr) override
- {
- translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::ForLoopExpr &expr) override
- {
- translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::BreakExpr &expr) override
- {
- HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
- HIR::Expr *break_expr
- = expr.has_break_expr ()
- ? ASTLoweringExpr::translate (expr.get_break_expr ().get ())
- : nullptr;
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::BreakExpr (mapping, expr.get_locus (),
- std ::move (break_label),
- std::unique_ptr<HIR::Expr> (break_expr),
- expr.get_outer_attrs ());
- }
-
- void visit (AST::ContinueExpr &expr) override
- {
- HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::ContinueExpr (mapping, expr.get_locus (),
- std ::move (break_label),
- expr.get_outer_attrs ());
- }
-
- void visit (AST::BorrowExpr &expr) override
- {
- HIR::Expr *borrow_lvalue
- = ASTLoweringExpr::translate (expr.get_borrowed_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- HIR::BorrowExpr *borrow_expr
- = new HIR::BorrowExpr (mapping,
- std::unique_ptr<HIR::Expr> (borrow_lvalue),
- expr.get_is_mut () ? Mutability::Mut
- : Mutability::Imm,
- expr.get_outer_attrs (), expr.get_locus ());
-
- if (expr.get_is_double_borrow ())
- {
- NodeId artifical_bouble_borrow_id = mappings->get_next_node_id ();
- Analysis::NodeMapping mapping (crate_num, artifical_bouble_borrow_id,
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- borrow_expr
- = new HIR::BorrowExpr (mapping,
- std::unique_ptr<HIR::Expr> (borrow_expr),
- expr.get_is_mut () ? Mutability::Mut
- : Mutability::Imm,
- expr.get_outer_attrs (), expr.get_locus ());
- }
-
- translated = borrow_expr;
- }
-
- void visit (AST::DereferenceExpr &expr) override
- {
- HIR::Expr *dref_lvalue
- = ASTLoweringExpr::translate (expr.get_dereferenced_expr ().get ());
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated
- = new HIR::DereferenceExpr (mapping,
- std::unique_ptr<HIR::Expr> (dref_lvalue),
- expr.get_outer_attrs (), expr.get_locus ());
- }
-
- void visit (AST::MatchExpr &expr) override
- {
- translated = ASTLoweringExprWithBlock::translate (&expr, &terminated);
- }
-
- void visit (AST::RangeFromToExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- HIR::Expr *range_from
- = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
- HIR::Expr *range_to
- = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
-
- translated
- = new HIR::RangeFromToExpr (mapping,
- std::unique_ptr<HIR::Expr> (range_from),
- std::unique_ptr<HIR::Expr> (range_to),
- expr.get_locus ());
- }
-
- void visit (AST::RangeFromExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- HIR::Expr *range_from
- = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
-
- translated
- = new HIR::RangeFromExpr (mapping,
- std::unique_ptr<HIR::Expr> (range_from),
- expr.get_locus ());
- }
-
- void visit (AST::RangeToExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- HIR::Expr *range_to
- = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
-
- translated
- = new HIR::RangeToExpr (mapping, std::unique_ptr<HIR::Expr> (range_to),
- expr.get_locus ());
- }
-
- void visit (AST::RangeFullExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::RangeFullExpr (mapping, expr.get_locus ());
- }
-
- void visit (AST::RangeFromToInclExpr &expr) override
- {
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- HIR::Expr *range_from
- = ASTLoweringExpr::translate (expr.get_from_expr ().get ());
- HIR::Expr *range_to
- = ASTLoweringExpr::translate (expr.get_to_expr ().get ());
-
- translated
- = new HIR::RangeFromToInclExpr (mapping,
- std::unique_ptr<HIR::Expr> (range_from),
- std::unique_ptr<HIR::Expr> (range_to),
- expr.get_locus ());
- }
+ static HIR::Expr *translate (AST::Expr *expr, bool *terminated = nullptr);
+
+ void visit (AST::TupleIndexExpr &expr) override;
+ void visit (AST::TupleExpr &expr) override;
+ void visit (AST::IfExpr &expr) override;
+ void visit (AST::IfExprConseqElse &expr) override;
+ void visit (AST::IfExprConseqIf &expr) override;
+ void visit (AST::BlockExpr &expr) override;
+ void visit (AST::UnsafeBlockExpr &expr) override;
+ void visit (AST::PathInExpression &expr) override;
+ void visit (AST::QualifiedPathInExpression &expr) override;
+ void visit (AST::ReturnExpr &expr) override;
+ void visit (AST::CallExpr &expr) override;
+ void visit (AST::MethodCallExpr &expr) override;
+ void visit (AST::AssignmentExpr &expr) override;
+ void visit (AST::IdentifierExpr &expr) override;
+ void visit (AST::ArrayExpr &expr) override;
+ void visit (AST::ArrayIndexExpr &expr) override;
+ void visit (AST::ArrayElemsValues &elems) override;
+ void visit (AST::ArrayElemsCopied &elems) override;
+ void visit (AST::LiteralExpr &expr) override;
+ void visit (AST::ArithmeticOrLogicalExpr &expr) override;
+ void visit (AST::ComparisonExpr &expr) override;
+ void visit (AST::LazyBooleanExpr &expr) override;
+ void visit (AST::NegationExpr &expr) override;
+ void visit (AST::TypeCastExpr &expr) override;
+ void visit (AST::CompoundAssignmentExpr &expr) override;
+ void visit (AST::StructExprStruct &struct_expr) override;
+ void visit (AST::StructExprStructFields &struct_expr) override;
+ void visit (AST::GroupedExpr &expr) override;
+ void visit (AST::FieldAccessExpr &expr) override;
+ void visit (AST::LoopExpr &expr) override;
+ void visit (AST::WhileLoopExpr &expr) override;
+ void visit (AST::ForLoopExpr &expr) override;
+ void visit (AST::BreakExpr &expr) override;
+ void visit (AST::ContinueExpr &expr) override;
+ void visit (AST::BorrowExpr &expr) override;
+ void visit (AST::DereferenceExpr &expr) override;
+ void visit (AST::MatchExpr &expr) override;
+ void visit (AST::RangeFromToExpr &expr) override;
+ void visit (AST::RangeFromExpr &expr) override;
+ void visit (AST::RangeToExpr &expr) override;
+ void visit (AST::RangeFullExpr &expr) override;
+ void visit (AST::RangeFromToInclExpr &expr) override;
+ void visit (AST::ClosureExprInner &expr) override;
+ void visit (AST::ClosureExprInnerTyped &expr) override;
private:
- ASTLoweringExpr ()
- : ASTLoweringBase (), translated (nullptr),
- translated_array_elems (nullptr), terminated (false)
- {}
+ ASTLoweringExpr ();
HIR::Expr *translated;
HIR::ArrayElems *translated_array_elems;
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 2421ca8..2c9a0dc 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -22,6 +22,24 @@
namespace Rust {
namespace HIR {
+ASTLoweringPattern::ASTLoweringPattern () : translated (nullptr) {}
+
+HIR::Pattern *
+ASTLoweringPattern::translate (AST::Pattern *pattern)
+{
+ ASTLoweringPattern resolver;
+ pattern->accept_vis (resolver);
+
+ rust_assert (resolver.translated != nullptr);
+
+ resolver.mappings->insert_hir_pattern (resolver.translated);
+ resolver.mappings->insert_location (
+ resolver.translated->get_pattern_mappings ().get_hirid (),
+ pattern->get_locus ());
+
+ return resolver.translated;
+}
+
void
ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
{
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h
index aab99f6..4ab81a8 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.h
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -29,39 +29,19 @@ class ASTLoweringPattern : public ASTLoweringBase
using Rust::HIR::ASTLoweringBase::visit;
public:
- static HIR::Pattern *translate (AST::Pattern *pattern)
- {
- ASTLoweringPattern resolver;
- pattern->accept_vis (resolver);
-
- rust_assert (resolver.translated != nullptr);
-
- resolver.mappings->insert_hir_pattern (resolver.translated);
- resolver.mappings->insert_location (
- resolver.translated->get_pattern_mappings ().get_hirid (),
- pattern->get_locus ());
-
- return resolver.translated;
- }
+ static HIR::Pattern *translate (AST::Pattern *pattern);
void visit (AST::IdentifierPattern &pattern) override;
-
void visit (AST::PathInExpression &pattern) override;
-
void visit (AST::StructPattern &pattern) override;
-
void visit (AST::TupleStructPattern &pattern) override;
-
void visit (AST::WildcardPattern &pattern) override;
-
void visit (AST::TuplePattern &pattern) override;
-
void visit (AST::LiteralPattern &pattern) override;
-
void visit (AST::RangePattern &pattern) override;
private:
- ASTLoweringPattern () : translated (nullptr) {}
+ ASTLoweringPattern ();
HIR::Pattern *translated;
};
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
new file mode 100644
index 0000000..92a14f4
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -0,0 +1,232 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast-lower-type.h"
+
+namespace Rust {
+namespace HIR {
+
+HIR::TypePath *
+ASTLowerTypePath::translate (AST::TypePath &type)
+{
+ ASTLowerTypePath resolver;
+ type.accept_vis (resolver);
+ rust_assert (resolver.translated != nullptr);
+ return resolver.translated;
+}
+
+void
+ASTLowerTypePath::visit (AST::TypePathSegmentFunction &segment)
+{
+ auto crate_num = mappings->get_current_crate ();
+ auto hirid = mappings->get_next_hir_id (crate_num);
+ Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ());
+
+ AST::TypePathFunction &fn = segment.get_type_path_function ();
+ std::vector<std::unique_ptr<HIR::Type>> inputs;
+ for (auto &param : fn.get_params ())
+ {
+ HIR::Type *hir_type = ASTLoweringType::translate (param.get ());
+ inputs.push_back (std::unique_ptr<HIR::Type> (hir_type));
+ }
+
+ HIR::Type *result_type
+ = fn.has_return_type ()
+ ? ASTLoweringType::translate (fn.get_return_type ().get ())
+ : nullptr;
+
+ HIR::TypePathFunction function_path (std::move (inputs),
+ std::unique_ptr<HIR::Type> (
+ result_type));
+
+ translated_segment = new HIR::TypePathSegmentFunction (
+ mapping, std::move (ident), segment.get_separating_scope_resolution (),
+ std::move (function_path), segment.get_locus ());
+}
+
+void
+ASTLowerTypePath::visit (AST::TypePathSegment &segment)
+{
+ auto crate_num = mappings->get_current_crate ();
+ auto hirid = mappings->get_next_hir_id (crate_num);
+ Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ());
+ translated_segment
+ = new HIR::TypePathSegment (std::move (mapping), ident,
+ segment.get_separating_scope_resolution (),
+ segment.get_locus ());
+}
+
+void
+ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment)
+{
+ std::vector<HIR::GenericArgsBinding> binding_args; // TODO
+
+ std::string segment_name = segment.get_ident_segment ().as_string ();
+ bool has_separating_scope_resolution
+ = segment.get_separating_scope_resolution ();
+
+ auto generic_args = lower_generic_args (segment.get_generic_args ());
+
+ auto crate_num = mappings->get_current_crate ();
+ auto hirid = mappings->get_next_hir_id (crate_num);
+ Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
+ UNKNOWN_LOCAL_DEFID);
+
+ translated_segment
+ = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name,
+ has_separating_scope_resolution,
+ generic_args, segment.get_locus ());
+}
+
+void
+ASTLowerTypePath::visit (AST::TypePath &path)
+{
+ std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
+
+ for (auto &seg : path.get_segments ())
+ {
+ translated_segment = nullptr;
+ seg->accept_vis (*this);
+ if (translated_segment == nullptr)
+ {
+ rust_fatal_error (seg->get_locus (),
+ "failed to translate AST TypePathSegment");
+ }
+ translated_segments.push_back (
+ std::unique_ptr<HIR::TypePathSegment> (translated_segment));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ auto hirid = mappings->get_next_hir_id (crate_num);
+ Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
+ mappings->get_next_localdef_id (crate_num));
+
+ translated
+ = new HIR::TypePath (std::move (mapping), std::move (translated_segments),
+ path.get_locus (),
+ path.has_opening_scope_resolution_op ());
+}
+
+HIR::QualifiedPathInType *
+ASTLowerQualifiedPathInType::translate (AST::QualifiedPathInType &type)
+{
+ ASTLowerQualifiedPathInType resolver;
+ type.accept_vis (resolver);
+ rust_assert (resolver.translated != nullptr);
+ return resolver.translated;
+}
+
+void
+ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
+{
+ auto crate_num = mappings->get_current_crate ();
+ auto hirid = mappings->get_next_hir_id (crate_num);
+ Analysis::NodeMapping qual_mappings (
+ crate_num, path.get_qualified_path_type ().get_node_id (), hirid,
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Type *qual_type = ASTLoweringType::translate (
+ path.get_qualified_path_type ().get_type ().get ());
+ HIR::TypePath *qual_trait = ASTLowerTypePath::translate (
+ path.get_qualified_path_type ().get_as_type_path ());
+
+ HIR::QualifiedPathType qual_path_type (
+ qual_mappings, std::unique_ptr<HIR::Type> (qual_type),
+ std::unique_ptr<HIR::TypePath> (qual_trait),
+ path.get_qualified_path_type ().get_locus ());
+
+ translated_segment = nullptr;
+ path.get_associated_segment ()->accept_vis (*this);
+ if (translated_segment == nullptr)
+ {
+ rust_fatal_error (path.get_associated_segment ()->get_locus (),
+ "failed to translate AST TypePathSegment");
+ return;
+ }
+ std::unique_ptr<HIR::TypePathSegment> associated_segment (translated_segment);
+
+ std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
+ for (auto &seg : path.get_segments ())
+ {
+ translated_segment = nullptr;
+ seg->accept_vis (*this);
+ if (translated_segment == nullptr)
+ {
+ rust_fatal_error (seg->get_locus (),
+ "failed to translte AST TypePathSegment");
+ }
+ translated_segments.push_back (
+ std::unique_ptr<HIR::TypePathSegment> (translated_segment));
+ }
+
+ Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
+ mappings->get_next_localdef_id (crate_num));
+ translated = new HIR::QualifiedPathInType (std::move (mapping),
+ std::move (qual_path_type),
+ std::move (associated_segment),
+ std::move (translated_segments),
+ path.get_locus ());
+}
+
+void
+ASTLoweringType::visit (AST::TraitObjectTypeOneBound &type)
+{
+ std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
+ HIR::TypeParamBound *translated_bound
+ = ASTLoweringTypeBounds::translate (&type.get_trait_bound ());
+ bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (translated_bound));
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated = new HIR::TraitObjectType (mapping, std::move (bounds),
+ type.get_locus (), type.is_dyn ());
+}
+
+void
+ASTLoweringType::visit (AST::TraitObjectType &type)
+{
+ std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
+
+ for (auto &bound : type.get_type_param_bounds ())
+ {
+ HIR::TypeParamBound *translated_bound
+ = ASTLoweringTypeBounds::translate (bound.get ());
+ bounds.push_back (
+ std::unique_ptr<HIR::TypeParamBound> (translated_bound));
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated = new HIR::TraitObjectType (mapping, std::move (bounds),
+ type.get_locus (), type.is_dyn ());
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 46f765a..d593b48 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -32,59 +32,12 @@ protected:
using Rust::HIR::ASTLoweringBase::visit;
public:
- static HIR::TypePath *translate (AST::TypePath &type)
- {
- ASTLowerTypePath resolver;
- type.accept_vis (resolver);
- rust_assert (resolver.translated != nullptr);
- return resolver.translated;
- }
-
- void visit (AST::TypePathSegmentFunction &) override { gcc_unreachable (); }
-
- void visit (AST::TypePathSegment &segment) override
- {
- auto crate_num = mappings->get_current_crate ();
- auto hirid = mappings->get_next_hir_id (crate_num);
- Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
- UNKNOWN_LOCAL_DEFID);
-
- HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ());
- translated_segment
- = new HIR::TypePathSegment (std::move (mapping), ident,
- segment.get_separating_scope_resolution (),
- segment.get_locus ());
- }
+ static HIR::TypePath *translate (AST::TypePath &type);
+ void visit (AST::TypePathSegmentFunction &segment) override;
+ void visit (AST::TypePathSegment &segment) override;
void visit (AST::TypePathSegmentGeneric &segment) override;
-
- void visit (AST::TypePath &path) override
- {
- std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
-
- for (auto &seg : path.get_segments ())
- {
- translated_segment = nullptr;
- seg->accept_vis (*this);
- if (translated_segment == nullptr)
- {
- rust_fatal_error (seg->get_locus (),
- "failed to translate AST TypePathSegment");
- }
- translated_segments.push_back (
- std::unique_ptr<HIR::TypePathSegment> (translated_segment));
- }
-
- auto crate_num = mappings->get_current_crate ();
- auto hirid = mappings->get_next_hir_id (crate_num);
- Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
- mappings->get_next_localdef_id (crate_num));
-
- translated
- = new HIR::TypePath (std::move (mapping), std::move (translated_segments),
- path.get_locus (),
- path.has_opening_scope_resolution_op ());
- }
+ void visit (AST::TypePath &path) override;
protected:
HIR::TypePathSegment *translated_segment;
@@ -98,13 +51,7 @@ class ASTLowerQualifiedPathInType : public ASTLowerTypePath
using ASTLowerTypePath::visit;
public:
- static HIR::QualifiedPathInType *translate (AST::QualifiedPathInType &type)
- {
- ASTLowerQualifiedPathInType resolver;
- type.accept_vis (resolver);
- rust_assert (resolver.translated != nullptr);
- return resolver.translated;
- }
+ static HIR::QualifiedPathInType *translate (AST::QualifiedPathInType &type);
void visit (AST::QualifiedPathInType &path) override;
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index fa3a83d..52b7003 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -22,9 +22,12 @@
#include "rust-ast-lower-expr.h"
#include "rust-ast-lower-block.h"
#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-pattern.h"
+#include "rust-ast-lower-struct-field-expr.h"
namespace Rust {
namespace HIR {
+using HIR::ClosureParam;
Visibility
translate_visibility (const AST::Visibility &vis)
@@ -473,5 +476,25 @@ ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr)
expr.get_locus (),
expr.get_outer_attrs ());
}
+
+ClosureParam
+ASTLoweringBase::lower_closure_param (AST::ClosureParam &param)
+{
+ HIR::Pattern *param_pattern
+ = ASTLoweringPattern::translate (param.get_pattern ().get ());
+
+ HIR::Type *param_type
+ = param.has_type_given ()
+ ? ASTLoweringType::translate (param.get_type ().get ())
+ : nullptr;
+
+ return HIR::ClosureParam (std::unique_ptr<HIR::Pattern> (param_pattern),
+ param.get_locus (),
+ param.has_type_given ()
+ ? std::unique_ptr<HIR::Type> (param_type)
+ : nullptr,
+ param.get_outer_attrs ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index bb139a7..11d4cd1 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -197,7 +197,7 @@ void
Dump::visit (FieldAccessExpr &)
{}
void
-Dump::visit (ClosureExprInner &)
+Dump::visit (ClosureExpr &)
{}
void
Dump::visit (BlockExpr &block_expr)
@@ -212,9 +212,7 @@ Dump::visit (BlockExpr &block_expr)
stream << "]";
indent--;
}
-void
-Dump::visit (ClosureExprInnerTyped &)
-{}
+
void
Dump::visit (ContinueExpr &)
{}
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 8b9e893..1953efe 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -78,9 +78,8 @@ private:
virtual void visit (CallExpr &) override;
virtual void visit (MethodCallExpr &) override;
virtual void visit (FieldAccessExpr &) override;
- virtual void visit (ClosureExprInner &) override;
+ virtual void visit (ClosureExpr &) override;
virtual void visit (BlockExpr &) override;
- virtual void visit (ClosureExprInnerTyped &) override;
virtual void visit (ContinueExpr &) override;
virtual void visit (BreakExpr &) override;
virtual void visit (RangeFromToExpr &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index e173d37..66d8509 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -1985,21 +1985,22 @@ protected:
struct ClosureParam
{
private:
+ std::vector<AST::Attribute> outer_attrs;
std::unique_ptr<Pattern> pattern;
-
- // bool has_type_given;
std::unique_ptr<Type> type;
-
- // TODO: should this store location data?
+ Location locus;
public:
// Returns whether the type of the parameter has been given.
bool has_type_given () const { return type != nullptr; }
// Constructor for closure parameter
- ClosureParam (std::unique_ptr<Pattern> param_pattern,
- std::unique_ptr<Type> param_type = nullptr)
- : pattern (std::move (param_pattern)), type (std::move (param_type))
+ ClosureParam (std::unique_ptr<Pattern> param_pattern, Location locus,
+ std::unique_ptr<Type> param_type = nullptr,
+ std::vector<AST::Attribute> outer_attrs = {})
+ : outer_attrs (std::move (outer_attrs)),
+ pattern (std::move (param_pattern)), type (std::move (param_type)),
+ locus (locus)
{}
// Copy constructor required due to cloning as a result of unique_ptrs
@@ -2007,6 +2008,8 @@ public:
: pattern (other.pattern->clone_pattern ())
{
// guard to protect from null pointer dereference
+ if (other.pattern != nullptr)
+ pattern = other.pattern->clone_pattern ();
if (other.type != nullptr)
type = other.type->clone_type ();
}
@@ -2016,8 +2019,17 @@ public:
// Assignment operator must be overloaded to clone as well
ClosureParam &operator= (ClosureParam const &other)
{
- pattern = other.pattern->clone_pattern ();
- type = other.type->clone_type ();
+ outer_attrs = other.outer_attrs;
+
+ // guard to protect from null pointer dereference
+ if (other.pattern != nullptr)
+ pattern = other.pattern->clone_pattern ();
+ else
+ pattern = nullptr;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
return *this;
}
@@ -2026,31 +2038,79 @@ public:
ClosureParam (ClosureParam &&other) = default;
ClosureParam &operator= (ClosureParam &&other) = default;
- // Returns whether closure parameter is in an error state.
- bool is_error () const { return pattern == nullptr; }
+ std::string as_string () const;
+
+ const std::vector<AST::Attribute> &get_outer_attrs () const
+ {
+ return outer_attrs;
+ }
+ std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }
- // Creates an error state closure parameter.
- static ClosureParam create_error () { return ClosureParam (nullptr); }
+ std::unique_ptr<Pattern> &get_pattern ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
- std::string as_string () const;
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (has_type_given ());
+ return type;
+ }
+
+ Location get_locus () const { return locus; }
};
// Base closure definition expression HIR node - abstract
class ClosureExpr : public ExprWithoutBlock
{
+private:
bool has_move;
std::vector<ClosureParam> params;
Location locus;
+ std::unique_ptr<Type> return_type;
+ std::unique_ptr<Expr> expr;
-protected:
+public:
ClosureExpr (Analysis::NodeMapping mappings,
- std::vector<ClosureParam> closure_params, bool has_move,
+ std::vector<ClosureParam> closure_params,
+ std::unique_ptr<Type> closure_return_type,
+ std::unique_ptr<Expr> closure_expr, bool has_move,
AST::AttrVec outer_attribs, Location locus)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
- has_move (has_move), params (std::move (closure_params)), locus (locus)
+ has_move (has_move), params (std::move (closure_params)), locus (locus),
+ return_type (std::move (closure_return_type)),
+ expr (std::move (closure_expr))
{}
-public:
+ // Copy constructor requires cloning
+ ClosureExpr (ClosureExpr const &other)
+ : ExprWithoutBlock (other.get_mappings (), other.get_outer_attrs ())
+ {
+ return_type
+ = other.has_return_type () ? other.return_type->clone_type () : nullptr;
+ expr = other.expr->clone_expr ();
+ params = other.params;
+ has_move = other.has_move;
+ }
+
+ // Overload assignment operator to clone unique_ptrs
+ ClosureExpr &operator= (ClosureExpr const &other)
+ {
+ mappings = other.mappings;
+ return_type
+ = other.has_return_type () ? other.return_type->clone_type () : nullptr;
+ expr = other.expr->clone_expr ();
+ params = other.params;
+ has_move = other.has_move;
+
+ return *this;
+ }
+
+ // move constructors
+ ClosureExpr (ClosureExpr &&other) = default;
+ ClosureExpr &operator= (ClosureExpr &&other) = default;
+
std::string as_string () const override;
Location get_locus () const override final { return locus; }
@@ -2059,47 +2119,19 @@ public:
{
return ExprType::Closure;
}
-};
-
-// Represents a non-type-specified closure expression HIR node
-class ClosureExprInner : public ClosureExpr
-{
- std::unique_ptr<Expr> closure_inner;
-
-public:
- std::string as_string () const override;
- // Constructor for a ClosureExprInner
- ClosureExprInner (Analysis::NodeMapping mappings,
- std::unique_ptr<Expr> closure_inner_expr,
- std::vector<ClosureParam> closure_params, Location locus,
- bool is_move = false,
- AST::AttrVec outer_attribs = AST::AttrVec ())
- : ClosureExpr (std::move (mappings), std::move (closure_params), is_move,
- std::move (outer_attribs), locus),
- closure_inner (std::move (closure_inner_expr))
- {}
+ bool get_has_move () const { return has_move; }
- // Copy constructor must be defined to allow copying via cloning of unique_ptr
- ClosureExprInner (ClosureExprInner const &other)
- : ClosureExpr (other), closure_inner (other.closure_inner->clone_expr ())
- {}
+ bool has_return_type () const { return return_type != nullptr; }
- // Overload assignment operator to clone closure_inner
- ClosureExprInner &operator= (ClosureExprInner const &other)
+ std::unique_ptr<Type> &get_return_type ()
{
- ClosureExpr::operator= (other);
- closure_inner = other.closure_inner->clone_expr ();
- // params = other.params;
- // has_move = other.has_move;
- // outer_attrs = other.outer_attrs;
-
- return *this;
- }
+ rust_assert (has_return_type ());
+ return return_type;
+ };
+ std::unique_ptr<Expr> &get_expr () { return expr; }
- // move constructors
- ClosureExprInner (ClosureExprInner &&other) = default;
- ClosureExprInner &operator= (ClosureExprInner &&other) = default;
+ std::vector<ClosureParam> &get_params () { return params; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
@@ -2107,16 +2139,16 @@ public:
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
- ClosureExprInner *clone_expr_impl () const override
+ ClosureExpr *clone_expr_impl () const override
{
- return new ClosureExprInner (*this);
+ return new ClosureExpr (*this);
}
/* Use covariance to implement clone function as returning this object rather
* than base */
- ClosureExprInner *clone_expr_without_block_impl () const override
+ ClosureExpr *clone_expr_without_block_impl () const override
{
- return new ClosureExprInner (*this);
+ return new ClosureExpr (*this);
}
};
@@ -2239,71 +2271,6 @@ protected:
}
};
-// Represents a type-specified closure expression HIR node
-class ClosureExprInnerTyped : public ClosureExpr
-{
- std::unique_ptr<Type> return_type;
- std::unique_ptr<BlockExpr>
- expr; // only used because may be polymorphic in future
-
-public:
- std::string as_string () const override;
-
- // Constructor potentially with a move
- ClosureExprInnerTyped (Analysis::NodeMapping mappings,
- std::unique_ptr<Type> closure_return_type,
- std::unique_ptr<BlockExpr> closure_expr,
- std::vector<ClosureParam> closure_params,
- Location locus, bool is_move = false,
- AST::AttrVec outer_attribs = AST::AttrVec ())
- : ClosureExpr (std::move (mappings), std::move (closure_params), is_move,
- std::move (outer_attribs), locus),
- return_type (std::move (closure_return_type)),
- expr (std::move (closure_expr))
- {}
-
- // Copy constructor requires cloning
- ClosureExprInnerTyped (ClosureExprInnerTyped const &other)
- : ClosureExpr (other), return_type (other.return_type->clone_type ()),
- expr (other.expr->clone_block_expr ())
- {}
-
- // Overload assignment operator to clone unique_ptrs
- ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other)
- {
- ClosureExpr::operator= (other);
- return_type = other.return_type->clone_type ();
- expr = other.expr->clone_block_expr ();
- // params = other.params;
- // has_move = other.has_move;
- // outer_attrs = other.outer_attrs;
-
- return *this;
- }
-
- // move constructors
- ClosureExprInnerTyped (ClosureExprInnerTyped &&other) = default;
- ClosureExprInnerTyped &operator= (ClosureExprInnerTyped &&other) = default;
-
- void accept_vis (HIRFullVisitor &vis) override;
- void accept_vis (HIRExpressionVisitor &vis) override;
-
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ClosureExprInnerTyped *clone_expr_impl () const override
- {
- return new ClosureExprInnerTyped (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ClosureExprInnerTyped *clone_expr_without_block_impl () const override
- {
- return new ClosureExprInnerTyped (*this);
- }
-};
-
// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 2798ba9..717facf 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -94,9 +94,7 @@ class MethodCallExpr;
class FieldAccessExpr;
struct ClosureParam;
class ClosureExpr;
-class ClosureExprInner;
class BlockExpr;
-class ClosureExprInnerTyped;
class ContinueExpr;
class BreakExpr;
class RangeExpr;
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index 4e25532..7e5b49d 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -1133,15 +1133,8 @@ ClosureExpr::as_string () const
}
}
- return str;
-}
-
-std::string
-ClosureExprInnerTyped::as_string () const
-{
- std::string str = ClosureExpr::as_string ();
-
- str += "\n Return type: " + return_type->as_string ();
+ str += "\n Return type: "
+ + (has_return_type () ? return_type->as_string () : "none");
str += "\n Body: " + expr->as_string ();
@@ -1516,16 +1509,6 @@ UnsafeBlockExpr::as_string () const
}
std::string
-ClosureExprInner::as_string () const
-{
- std::string str = ClosureExpr::as_string ();
-
- str += "\n Expression: " + closure_inner->as_string ();
-
- return str;
-}
-
-std::string
IfExpr::as_string () const
{
std::string str ("IfExpr: ");
@@ -4038,7 +4021,7 @@ FieldAccessExpr::accept_vis (HIRFullVisitor &vis)
}
void
-ClosureExprInner::accept_vis (HIRFullVisitor &vis)
+ClosureExpr::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
}
@@ -4050,12 +4033,6 @@ BlockExpr::accept_vis (HIRFullVisitor &vis)
}
void
-ClosureExprInnerTyped::accept_vis (HIRFullVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
ContinueExpr::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
@@ -4986,7 +4963,7 @@ IfExpr::accept_vis (HIRExpressionVisitor &vis)
}
void
-ClosureExprInner::accept_vis (HIRExpressionVisitor &vis)
+ClosureExpr::accept_vis (HIRExpressionVisitor &vis)
{
vis.visit (*this);
}
@@ -5076,12 +5053,6 @@ QualifiedPathInExpression::accept_vis (HIRPatternVisitor &vis)
}
void
-ClosureExprInnerTyped::accept_vis (HIRExpressionVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
ExprStmtWithBlock::accept_vis (HIRStmtVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 03cf5f5..06f3acb 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -529,24 +529,9 @@ protected:
struct TypePathFunction
{
private:
- // TODO: remove
- /*bool has_inputs;
- TypePathFnInputs inputs;*/
- // inlined from TypePathFnInputs
std::vector<std::unique_ptr<Type> > inputs;
-
- // bool has_type;
std::unique_ptr<Type> return_type;
- // FIXME: think of better way to mark as invalid than taking up storage
- bool is_invalid;
-
- // TODO: should this have location info?
-
-protected:
- // Constructor only used to create invalid type path functions.
- TypePathFunction (bool is_invalid) : is_invalid (is_invalid) {}
-
public:
// Returns whether the return type of the function has been specified.
bool has_return_type () const { return return_type != nullptr; }
@@ -554,31 +539,19 @@ public:
// Returns whether the function has inputs.
bool has_inputs () const { return !inputs.empty (); }
- // Returns whether function is in an error state.
- bool is_error () const { return is_invalid; }
-
- // Creates an error state function.
- static TypePathFunction create_error () { return TypePathFunction (true); }
-
- // Constructor
- TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
- Type *type = nullptr)
- : inputs (std::move (inputs)), return_type (type), is_invalid (false)
- {}
- // FIXME: deprecated
-
// Constructor
TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
- std::unique_ptr<Type> type = nullptr)
- : inputs (std::move (inputs)), return_type (std::move (type)),
- is_invalid (false)
+ std::unique_ptr<Type> type)
+ : inputs (std::move (inputs)), return_type (std::move (type))
{}
// Copy constructor with clone
TypePathFunction (TypePathFunction const &other)
- : return_type (other.return_type->clone_type ()),
- is_invalid (other.is_invalid)
{
+ return_type = other.has_return_type ()
+ ? other.get_return_type ()->clone_type ()
+ : nullptr;
+
inputs.reserve (other.inputs.size ());
for (const auto &e : other.inputs)
inputs.push_back (e->clone_type ());
@@ -589,8 +562,9 @@ public:
// Overloaded assignment operator to clone type
TypePathFunction &operator= (TypePathFunction const &other)
{
- return_type = other.return_type->clone_type ();
- is_invalid = other.is_invalid;
+ return_type = other.has_return_type ()
+ ? other.get_return_type ()->clone_type ()
+ : nullptr;
inputs.reserve (other.inputs.size ());
for (const auto &e : other.inputs)
@@ -604,6 +578,23 @@ public:
TypePathFunction &operator= (TypePathFunction &&other) = default;
std::string as_string () const;
+
+ const std::vector<std::unique_ptr<Type> > &get_params () const
+ {
+ return inputs;
+ };
+ std::vector<std::unique_ptr<Type> > &get_params () { return inputs; };
+
+ const std::unique_ptr<Type> &get_return_type () const
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ };
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ };
};
// Segment used in type path with a function argument
@@ -638,10 +629,9 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
- virtual SegmentType get_type () const override final
- {
- return SegmentType::FUNCTION;
- }
+ SegmentType get_type () const override final { return SegmentType::FUNCTION; }
+
+ TypePathFunction &get_function_path () { return function_path; }
protected:
// Use covariance to override base class method
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index b3c0b93..a922792 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -63,9 +63,8 @@ public:
virtual void visit (CallExpr &expr) = 0;
virtual void visit (MethodCallExpr &expr) = 0;
virtual void visit (FieldAccessExpr &expr) = 0;
- virtual void visit (ClosureExprInner &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
- virtual void visit (ClosureExprInnerTyped &expr) = 0;
+ virtual void visit (ClosureExpr &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
virtual void visit (RangeFromToExpr &expr) = 0;
@@ -206,9 +205,8 @@ public:
virtual void visit (CallExpr &) override {}
virtual void visit (MethodCallExpr &) override {}
virtual void visit (FieldAccessExpr &) override {}
- virtual void visit (ClosureExprInner &) override {}
+ virtual void visit (ClosureExpr &) override {}
virtual void visit (BlockExpr &) override {}
- virtual void visit (ClosureExprInnerTyped &) override {}
virtual void visit (ContinueExpr &) override {}
virtual void visit (BreakExpr &) override {}
virtual void visit (RangeFromToExpr &) override {}
@@ -419,8 +417,7 @@ public:
virtual void visit (HIR::QualifiedPathInExpression &expr) = 0;
virtual void visit (HIR::PathInExpression &expr) = 0;
- virtual void visit (ClosureExprInnerTyped &) = 0;
- virtual void visit (ClosureExprInner &expr) = 0;
+ virtual void visit (ClosureExpr &) = 0;
virtual void visit (StructExprStructFields &) = 0;
virtual void visit (StructExprStruct &) = 0;
virtual void visit (LiteralExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 26bf302..97c20c9 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -238,6 +238,7 @@ class ExprWithoutBlock;
// Base expression HIR node - abstract
class Expr : public Node
{
+protected:
AST::AttrVec outer_attrs;
Analysis::NodeMapping mappings;
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index 4cc4e26..60b3eba 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -565,6 +565,64 @@ ResolveExpr::visit (AST::RangeFromToInclExpr &expr)
ResolveExpr::go (expr.get_to_expr ().get (), prefix, canonical_prefix);
}
+void
+ResolveExpr::visit (AST::ClosureExprInner &expr)
+{
+ NodeId scope_node_id = expr.get_node_id ();
+ resolver->get_name_scope ().push (scope_node_id);
+ resolver->get_type_scope ().push (scope_node_id);
+ resolver->get_label_scope ().push (scope_node_id);
+ resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
+ resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
+ resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+
+ for (auto &p : expr.get_params ())
+ {
+ resolve_closure_param (p);
+ }
+
+ ResolveExpr::go (expr.get_definition_expr ().get (), prefix,
+ canonical_prefix);
+
+ resolver->get_name_scope ().pop ();
+ resolver->get_type_scope ().pop ();
+ resolver->get_label_scope ().pop ();
+}
+
+void
+ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
+{
+ NodeId scope_node_id = expr.get_node_id ();
+ resolver->get_name_scope ().push (scope_node_id);
+ resolver->get_type_scope ().push (scope_node_id);
+ resolver->get_label_scope ().push (scope_node_id);
+ resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
+ resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
+ resolver->push_new_label_rib (resolver->get_type_scope ().peek ());
+
+ for (auto &p : expr.get_params ())
+ {
+ resolve_closure_param (p);
+ }
+
+ ResolveType::go (expr.get_return_type ().get ());
+ ResolveExpr::go (expr.get_definition_block ().get (), prefix,
+ canonical_prefix);
+
+ resolver->get_name_scope ().pop ();
+ resolver->get_type_scope ().pop ();
+ resolver->get_label_scope ().pop ();
+}
+
+void
+ResolveExpr::resolve_closure_param (AST::ClosureParam &param)
+{
+ PatternDeclaration::go (param.get_pattern ().get ());
+
+ if (param.has_type_given ())
+ ResolveType::go (param.get_type ().get ());
+}
+
ResolveExpr::ResolveExpr (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 11a846a..c11718e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -34,90 +34,52 @@ public:
const CanonicalPath &canonical_prefix);
void visit (AST::TupleIndexExpr &expr) override;
-
void visit (AST::TupleExpr &expr) override;
-
void visit (AST::PathInExpression &expr) override;
-
void visit (AST::QualifiedPathInExpression &expr) override;
-
void visit (AST::ReturnExpr &expr) override;
-
void visit (AST::CallExpr &expr) override;
-
void visit (AST::MethodCallExpr &expr) override;
-
void visit (AST::AssignmentExpr &expr) override;
-
void visit (AST::IdentifierExpr &expr) override;
-
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
-
void visit (AST::CompoundAssignmentExpr &expr) override;
-
void visit (AST::ComparisonExpr &expr) override;
-
void visit (AST::LazyBooleanExpr &expr) override;
-
void visit (AST::NegationExpr &expr) override;
-
void visit (AST::TypeCastExpr &expr) override;
-
void visit (AST::IfExpr &expr) override;
-
void visit (AST::IfExprConseqElse &expr) override;
-
void visit (AST::IfExprConseqIf &expr) override;
-
void visit (AST::IfLetExpr &expr) override;
-
void visit (AST::BlockExpr &expr) override;
-
void visit (AST::UnsafeBlockExpr &expr) override;
-
void visit (AST::ArrayElemsValues &elems) override;
-
void visit (AST::ArrayExpr &expr) override;
-
void visit (AST::ArrayIndexExpr &expr) override;
-
void visit (AST::ArrayElemsCopied &elems) override;
-
- // this this an empty struct constructor like 'S {}'
void visit (AST::StructExprStruct &struct_expr) override;
-
- // this this a struct constructor with fields
void visit (AST::StructExprStructFields &struct_expr) override;
-
void visit (AST::GroupedExpr &expr) override;
-
void visit (AST::FieldAccessExpr &expr) override;
-
void visit (AST::LoopExpr &expr) override;
-
void visit (AST::BreakExpr &expr) override;
-
void visit (AST::WhileLoopExpr &expr) override;
-
void visit (AST::ForLoopExpr &expr) override;
-
void visit (AST::ContinueExpr &expr) override;
-
void visit (AST::BorrowExpr &expr) override;
-
void visit (AST::DereferenceExpr &expr) override;
-
void visit (AST::MatchExpr &expr) override;
-
void visit (AST::RangeFromToExpr &expr) override;
-
void visit (AST::RangeFromExpr &expr) override;
-
void visit (AST::RangeToExpr &expr) override;
-
void visit (AST::RangeFullExpr &expr) override;
-
void visit (AST::RangeFromToInclExpr &expr) override;
+ void visit (AST::ClosureExprInner &expr) override;
+ void visit (AST::ClosureExprInnerTyped &expr) override;
+
+protected:
+ void resolve_closure_param (AST::ClosureParam &param);
private:
ResolveExpr (const CanonicalPath &prefix,
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 6b08613..e42bab6 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -149,7 +149,20 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
break;
case AST::TypePathSegment::SegmentType::FUNCTION:
- gcc_unreachable ();
+ AST::TypePathSegmentFunction *fnseg
+ = static_cast<AST::TypePathSegmentFunction *> (segment.get ());
+
+ AST::TypePathFunction &fn = fnseg->get_type_path_function ();
+ for (auto &param : fn.get_params ())
+ {
+ ResolveType::go (param.get ());
+ }
+
+ if (fn.has_return_type ())
+ {
+ ResolveType::go (fn.get_return_type ().get ());
+ }
+
break;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 3411a2da..8911a1d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -178,16 +178,6 @@ TypeCheckExpr::visit (HIR::CallExpr &expr)
{
TyTy::BaseType *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ());
- bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::ADT
- || function_tyty->get_kind () == TyTy::TypeKind::FNDEF
- || function_tyty->get_kind () == TyTy::TypeKind::FNPTR;
- if (!valid_tyty)
- {
- rust_error_at (expr.get_locus (),
- "Failed to resolve expression of function call");
- return;
- }
-
rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}",
function_tyty->get_name ().c_str ());
@@ -214,6 +204,24 @@ TypeCheckExpr::visit (HIR::CallExpr &expr)
rust_assert (adt->number_of_variants () == 1);
variant = *adt->get_variants ().at (0);
}
+
+ infered
+ = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
+ return;
+ }
+
+ bool resolved_fn_trait_call
+ = resolve_fn_trait_call (expr, function_tyty, &infered);
+ if (resolved_fn_trait_call)
+ return;
+
+ bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::FNDEF
+ || function_tyty->get_kind () == TyTy::TypeKind::FNPTR;
+ if (!valid_tyty)
+ {
+ rust_error_at (expr.get_locus (),
+ "Failed to resolve expression of function call");
+ return;
}
infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
@@ -1162,7 +1170,8 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
rust_debug ("type-checking method_call: {%s}", lookup->debug_str ().c_str ());
TyTy::BaseType *function_ret_tyty
- = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self, context);
+ = TyTy::TypeCheckMethodCallExpr::go (static_cast<TyTy::FnType *> (lookup),
+ expr, adjusted_self, context);
if (function_ret_tyty == nullptr
|| function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
{
@@ -1418,6 +1427,128 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
}
}
+void
+TypeCheckExpr::visit (HIR::ClosureExpr &expr)
+{
+ TypeCheckContextItem &current_context = context->peek_context ();
+ TyTy::FnType *current_context_fndecl = current_context.get_context_type ();
+
+ HirId ref = expr.get_mappings ().get_hirid ();
+ DefId id = expr.get_mappings ().get_defid ();
+ RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()};
+
+ // get from parent context
+ std::vector<TyTy::SubstitutionParamMapping> subst_refs
+ = current_context_fndecl->clone_substs ();
+
+ std::vector<TyTy::TyVar> parameter_types;
+ for (auto &p : expr.get_params ())
+ {
+ if (p.has_type_given ())
+ {
+ TyTy::BaseType *param_tyty
+ = TypeCheckType::Resolve (p.get_type ().get ());
+ TyTy::TyVar param_ty (param_tyty->get_ref ());
+ parameter_types.push_back (param_ty);
+
+ TypeCheckPattern::Resolve (p.get_pattern ().get (),
+ param_ty.get_tyty ());
+ }
+ else
+ {
+ TyTy::TyVar param_ty
+ = TyTy::TyVar::get_implicit_infer_var (p.get_locus ());
+ parameter_types.push_back (param_ty);
+
+ TypeCheckPattern::Resolve (p.get_pattern ().get (),
+ param_ty.get_tyty ());
+ }
+ }
+
+ // we generate an implicit hirid for the closure args
+ HirId implicit_args_id = mappings->get_next_hir_id ();
+ TyTy::TupleType *closure_args
+ = new TyTy::TupleType (implicit_args_id, expr.get_locus (),
+ parameter_types);
+ context->insert_implicit_type (closure_args);
+
+ Location result_type_locus = expr.has_return_type ()
+ ? expr.get_return_type ()->get_locus ()
+ : expr.get_locus ();
+ TyTy::TyVar result_type
+ = expr.has_return_type ()
+ ? TyTy::TyVar (
+ TypeCheckType::Resolve (expr.get_return_type ().get ())->get_ref ())
+ : TyTy::TyVar::get_implicit_infer_var (expr.get_locus ());
+
+ // resolve the block
+ Location closure_expr_locus = expr.get_expr ()->get_locus ();
+ TyTy::BaseType *closure_expr_ty
+ = TypeCheckExpr::Resolve (expr.get_expr ().get ());
+ coercion_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (result_type.get_tyty (),
+ result_type_locus),
+ TyTy::TyWithLocation (closure_expr_ty, closure_expr_locus),
+ expr.get_locus ());
+
+ // generate the closure type
+ infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type,
+ subst_refs);
+
+ // FIXME
+ // all closures automatically inherit the appropriate fn trait. Lets just
+ // assume FnOnce for now. I think this is based on the return type of the
+ // closure
+
+ Analysis::RustLangItem::ItemType lang_item_type
+ = Analysis::RustLangItem::ItemType::FN_ONCE;
+ DefId respective_lang_item_id = UNKNOWN_DEFID;
+ bool lang_item_defined
+ = mappings->lookup_lang_item (lang_item_type, &respective_lang_item_id);
+ if (!lang_item_defined)
+ {
+ // FIXME
+ // we need to have a unified way or error'ing when we are missing lang
+ // items that is useful
+ rust_fatal_error (
+ expr.get_locus (), "unable to find lang item: %<%s%>",
+ Analysis::RustLangItem::ToString (lang_item_type).c_str ());
+ }
+ rust_assert (lang_item_defined);
+
+ // these lang items are always traits
+ HIR::Item *item = mappings->lookup_defid (respective_lang_item_id);
+ rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
+ HIR::Trait *trait_item = static_cast<HIR::Trait *> (item);
+
+ TraitReference *trait = TraitResolver::Resolve (*trait_item);
+ rust_assert (!trait->is_error ());
+
+ TyTy::TypeBoundPredicate predicate (*trait, expr.get_locus ());
+
+ // resolve the trait bound where the <(Args)> are the parameter tuple type
+ HIR::GenericArgs args = HIR::GenericArgs::create_empty (expr.get_locus ());
+
+ // lets generate an implicit Type so that it resolves to the implict tuple
+ // type we have created
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_mappings ().get_nodeid (),
+ implicit_args_id, UNKNOWN_LOCAL_DEFID);
+ HIR::TupleType *implicit_tuple
+ = new HIR::TupleType (mapping,
+ {} // we dont need to fill this out because it will
+ // auto resolve because the hir id's match
+ ,
+ expr.get_locus ());
+ args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
+
+ // apply the arguments
+ predicate.apply_generic_arguments (&args);
+
+ // finally inherit the trait bound
+ infered->inherit_bounds ({predicate});
+}
+
bool
TypeCheckExpr::resolve_operator_overload (
Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExprMeta expr,
@@ -1623,6 +1754,168 @@ TypeCheckExpr::resolve_operator_overload (
return true;
}
+HIR::PathIdentSegment
+TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
+ const TyTy::BaseType &receiver)
+{
+ // Question
+ // do we need to probe possible bounds here? I think not, i think when we
+ // support Fn traits they are explicitly specified
+
+ // FIXME
+ // the logic to map the FnTrait to their respective call trait-item is
+ // duplicated over in the backend/rust-compile-expr.cc
+ for (const auto &bound : receiver.get_specified_bounds ())
+ {
+ bool found_fn = bound.get_name ().compare ("Fn") == 0;
+ bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
+ bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
+
+ if (found_fn)
+ {
+ return HIR::PathIdentSegment ("call");
+ }
+ else if (found_fn_mut)
+ {
+ return HIR::PathIdentSegment ("call_mut");
+ }
+ else if (found_fn_once)
+ {
+ return HIR::PathIdentSegment ("call_once");
+ }
+ }
+
+ // nothing
+ return HIR::PathIdentSegment ("");
+}
+
+bool
+TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
+ TyTy::BaseType *receiver_tyty,
+ TyTy::BaseType **result)
+{
+ // we turn this into a method call expr
+ HIR::PathIdentSegment method_name
+ = resolve_possible_fn_trait_call_method_name (*receiver_tyty);
+ if (method_name.is_error ())
+ return false;
+
+ auto candidates = MethodResolver::Probe (receiver_tyty, method_name);
+ if (candidates.empty ())
+ return false;
+
+ if (candidates.size () > 1)
+ {
+ RichLocation r (expr.get_locus ());
+ for (auto &c : candidates)
+ r.add_range (c.candidate.locus);
+
+ rust_error_at (
+ r, "multiple candidates found for function trait method call %<%s%>",
+ method_name.as_string ().c_str ());
+ return false;
+ }
+
+ if (receiver_tyty->get_kind () == TyTy::TypeKind::CLOSURE)
+ {
+ const TyTy::ClosureType &closure
+ = static_cast<TyTy::ClosureType &> (*receiver_tyty);
+ closure.setup_fn_once_output ();
+ }
+
+ auto candidate = *candidates.begin ();
+ rust_debug_loc (expr.get_locus (),
+ "resolved call-expr to fn trait: {%u} {%s}",
+ candidate.candidate.ty->get_ref (),
+ candidate.candidate.ty->debug_str ().c_str ());
+
+ // Get the adjusted self
+ Adjuster adj (receiver_tyty);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+
+ // store the adjustments for code-generation to know what to do which must be
+ // stored onto the receiver to so as we don't trigger duplicate deref mappings
+ // ICE when an argument is a method call
+ HirId autoderef_mappings_id = expr.get_mappings ().get_hirid ();
+ context->insert_autoderef_mappings (autoderef_mappings_id,
+ std::move (candidate.adjustments));
+ context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
+
+ PathProbeCandidate &resolved_candidate = candidate.candidate;
+ TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+ NodeId resolved_node_id
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+
+ if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ RichLocation r (expr.get_locus ());
+ r.add_range (resolved_candidate.locus);
+ rust_error_at (r, "associated impl item is not a method");
+ return false;
+ }
+
+ TyTy::BaseType *lookup = lookup_tyty;
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
+ if (!fn->is_method ())
+ {
+ RichLocation r (expr.get_locus ());
+ r.add_range (resolved_candidate.locus);
+ rust_error_at (r, "associated function is not a method");
+ return false;
+ }
+
+ // fn traits only support tuple argument passing so we need to implicitly set
+ // this up to get the same type checking we get in the rest of the pipeline
+
+ std::vector<TyTy::TyVar> call_args;
+ for (auto &arg : expr.get_arguments ())
+ {
+ TyTy::BaseType *a = TypeCheckExpr::Resolve (arg.get ());
+ call_args.push_back (TyTy::TyVar (a->get_ref ()));
+ }
+
+ // crate implicit tuple
+ HirId implicit_arg_id = mappings->get_next_hir_id ();
+ Analysis::NodeMapping mapping (mappings->get_current_crate (), UNKNOWN_NODEID,
+ implicit_arg_id, UNKNOWN_LOCAL_DEFID);
+
+ TyTy::TupleType *tuple
+ = new TyTy::TupleType (implicit_arg_id, expr.get_locus (), call_args);
+ context->insert_implicit_type (implicit_arg_id, tuple);
+
+ std::vector<TyTy::Argument> args;
+ TyTy::Argument a (mapping, tuple,
+ expr.get_locus () /*FIXME is there a better location*/);
+ args.push_back (std::move (a));
+
+ TyTy::BaseType *function_ret_tyty
+ = TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args,
+ expr.get_locus (), expr.get_locus (),
+ adjusted_self, context);
+ if (function_ret_tyty == nullptr
+ || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (expr.get_locus (),
+ "failed check fn trait call-expr MethodCallExpr");
+ return false;
+ }
+
+ // store the expected fntype
+ context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn);
+
+ // set up the resolved name on the path
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ resolved_node_id);
+
+ // return the result of the function back
+ *result = function_ret_tyty;
+
+ return true;
+}
+
bool
TypeCheckExpr::validate_arithmetic_type (
const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 9e3db00..3ac8c4d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -69,10 +69,9 @@ public:
void visit (HIR::RangeFullExpr &expr) override;
void visit (HIR::RangeFromToInclExpr &expr) override;
void visit (HIR::WhileLoopExpr &expr) override;
+ void visit (HIR::ClosureExpr &expr) override;
// TODO
- void visit (HIR::ClosureExprInnerTyped &) override {}
- void visit (HIR::ClosureExprInner &expr) override {}
void visit (HIR::ErrorPropagationExpr &expr) override {}
void visit (HIR::RangeToInclExpr &expr) override {}
void visit (HIR::WhileLetLoopExpr &expr) override {}
@@ -104,6 +103,13 @@ protected:
HIR::OperatorExprMeta expr, TyTy::BaseType *lhs,
TyTy::BaseType *rhs);
+ bool resolve_fn_trait_call (HIR::CallExpr &expr,
+ TyTy::BaseType *function_tyty,
+ TyTy::BaseType **result);
+
+ HIR::PathIdentSegment
+ resolve_possible_fn_trait_call_method_name (const TyTy::BaseType &receiver);
+
private:
TypeCheckExpr ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index de3467b..d785835 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -70,6 +70,8 @@ public:
return item.trait_item;
}
+ TyTy::FnType *get_context_type ();
+
private:
union Item
{
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
index 2d9051f..34b60b3 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -154,5 +154,37 @@ TypeCheckContext::peek_context ()
return return_type_stack.back ().first;
}
+// TypeCheckContextItem
+
+TyTy::FnType *
+TypeCheckContextItem::get_context_type ()
+{
+ auto &context = *TypeCheckContext::get ();
+
+ HirId reference = UNKNOWN_HIRID;
+ switch (get_type ())
+ {
+ case ITEM:
+ reference = get_item ()->get_mappings ().get_hirid ();
+ break;
+
+ case IMPL_ITEM:
+ reference = get_impl_item ().second->get_mappings ().get_hirid ();
+ break;
+
+ case TRAIT_ITEM:
+ reference = get_trait_item ()->get_mappings ().get_hirid ();
+ break;
+ }
+
+ rust_assert (reference != UNKNOWN_HIRID);
+
+ TyTy::BaseType *lookup = nullptr;
+ bool ok = context.lookup_type (reference, &lookup);
+ rust_assert (ok);
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+ return static_cast<TyTy::FnType *> (lookup);
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index d7647b7..53eccb7 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -84,16 +84,71 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
= HIR::GenericArgs::create_empty (type_path.get_locus ());
auto &final_seg = type_path.get_final_segment ();
- if (final_seg->is_generic_segment ())
+ switch (final_seg->get_type ())
{
- auto final_generic_seg
- = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ());
- if (final_generic_seg->has_generic_args ())
- {
- args = final_generic_seg->get_generic_args ();
- }
+ case HIR::TypePathSegment::SegmentType::GENERIC: {
+ auto final_generic_seg
+ = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ());
+ if (final_generic_seg->has_generic_args ())
+ {
+ args = final_generic_seg->get_generic_args ();
+ }
+ }
+ break;
+
+ case HIR::TypePathSegment::SegmentType::FUNCTION: {
+ auto final_function_seg
+ = static_cast<HIR::TypePathSegmentFunction *> (final_seg.get ());
+ auto &fn = final_function_seg->get_function_path ();
+
+ // we need to make implicit generic args which must be an implicit Tuple
+ auto crate_num = mappings->get_current_crate ();
+ HirId implicit_args_id = mappings->get_next_hir_id ();
+ Analysis::NodeMapping mapping (crate_num,
+ final_seg->get_mappings ().get_nodeid (),
+ implicit_args_id, UNKNOWN_LOCAL_DEFID);
+
+ std::vector<std::unique_ptr<HIR::Type>> params_copy;
+ for (auto &p : fn.get_params ())
+ {
+ params_copy.push_back (p->clone_type ());
+ }
+
+ HIR::TupleType *implicit_tuple
+ = new HIR::TupleType (mapping, std::move (params_copy),
+ final_seg->get_locus ());
+
+ std::vector<std::unique_ptr<HIR::Type>> inputs;
+ inputs.push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
+
+ args = HIR::GenericArgs ({} /* lifetimes */,
+ std::move (inputs) /* type_args*/,
+ {} /* binding_args*/, {} /* const_args */,
+ final_seg->get_locus ());
+
+ // resolve the fn_once_output type
+ TyTy::BaseType *fn_once_output_ty
+ = fn.has_return_type ()
+ ? TypeCheckType::Resolve (fn.get_return_type ().get ())
+ : TyTy::TupleType::get_unit_type (
+ final_seg->get_mappings ().get_hirid ());
+ context->insert_implicit_type (final_seg->get_mappings ().get_hirid (),
+ fn_once_output_ty);
+
+ // setup the associated type.. ??
+ // fn_once_output_ty->debug ();
+ }
+ break;
+
+ default:
+ /* nothing to do */
+ break;
}
+ // FIXME
+ // I think this should really be just be if the !args.is_empty() because
+ // someone might wrongly apply generic arguments where they should not and
+ // they will be missing error diagnostics
if (predicate.requires_generic_args ())
{
// this is applying generic arguments to a trait reference
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 49aa2ef..18a34be 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -216,29 +216,77 @@ TypeCheckCallExpr::visit (FnPtr &type)
// method call checker
-void
-TypeCheckMethodCallExpr::visit (FnType &type)
+TypeCheckMethodCallExpr::TypeCheckMethodCallExpr (
+ Analysis::NodeMapping call_mappings, std::vector<Argument> &args,
+ Location call_locus, Location receiver_locus, TyTy::BaseType *adjusted_self,
+ Resolver::TypeCheckContext *context)
+ : call_mappings (call_mappings), arguments (args), call_locus (call_locus),
+ receiver_locus (receiver_locus), adjusted_self (adjusted_self),
+ context (context), mappings (Analysis::Mappings::get ())
+{}
+
+BaseType *
+TypeCheckMethodCallExpr::go (FnType *ref, HIR::MethodCallExpr &call,
+ TyTy::BaseType *adjusted_self,
+ Resolver::TypeCheckContext *context)
+{
+ std::vector<Argument> args;
+ for (auto &arg : call.get_arguments ())
+ {
+ BaseType *argument_expr_tyty
+ = Resolver::TypeCheckExpr::Resolve (arg.get ());
+ if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (arg->get_locus (),
+ "failed to resolve type for argument");
+ return new ErrorType (ref->get_ref ());
+ }
+
+ Argument a (arg->get_mappings (), argument_expr_tyty, arg->get_locus ());
+ args.push_back (std::move (a));
+ }
+
+ TypeCheckMethodCallExpr checker (call.get_mappings (), args,
+ call.get_locus (),
+ call.get_receiver ()->get_locus (),
+ adjusted_self, context);
+ return checker.check (*ref);
+}
+
+BaseType *
+TypeCheckMethodCallExpr::go (FnType *ref, Analysis::NodeMapping call_mappings,
+ std::vector<Argument> &args, Location call_locus,
+ Location receiver_locus,
+ TyTy::BaseType *adjusted_self,
+ Resolver::TypeCheckContext *context)
+{
+ TypeCheckMethodCallExpr checker (call_mappings, args, call_locus,
+ receiver_locus, adjusted_self, context);
+ return checker.check (*ref);
+}
+
+BaseType *
+TypeCheckMethodCallExpr::check (FnType &type)
{
Resolver::TypeCheckBase::unify_site (
- call.get_mappings ().get_hirid (), TyWithLocation (type.get_self_type ()),
- TyWithLocation (adjusted_self, call.get_receiver ()->get_locus ()),
- call.get_locus ());
+ call_mappings.get_hirid (), TyWithLocation (type.get_self_type ()),
+ TyWithLocation (adjusted_self, receiver_locus), call_locus);
// +1 for the receiver self
- size_t num_args_to_call = call.num_params () + 1;
+ size_t num_args_to_call = arguments.size () + 1;
if (num_args_to_call != type.num_params ())
{
- rust_error_at (call.get_locus (),
+ rust_error_at (call_locus,
"unexpected number of arguments %lu expected %lu",
- (unsigned long) call.num_params (),
+ (unsigned long) num_args_to_call,
(unsigned long) type.num_params ());
- return;
+ return new ErrorType (type.get_ref ());
}
size_t i = 1;
- for (auto &argument : call.get_arguments ())
+ for (auto &argument : arguments)
{
- Location arg_locus = argument->get_locus ();
+ Location arg_locus = argument.get_locus ();
auto fnparam = type.param_at (i);
HIR::Pattern *fn_param_pattern = fnparam.first;
@@ -248,25 +296,15 @@ TypeCheckMethodCallExpr::visit (FnType &type)
? mappings->lookup_location (param_ty->get_ref ())
: fn_param_pattern->get_locus ();
- auto argument_expr_tyty
- = Resolver::TypeCheckExpr::Resolve (argument.get ());
- if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (
- argument->get_locus (),
- "failed to resolve type for argument expr in CallExpr");
- return;
- }
-
- HirId coercion_side_id = argument->get_mappings ().get_hirid ();
+ auto argument_expr_tyty = argument.get_argument_type ();
+ HirId coercion_side_id = argument.get_mappings ().get_hirid ();
auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
coercion_side_id, TyWithLocation (param_ty, param_locus),
- TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
+ TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
- return;
+ rust_error_at (arg_locus, "Type Resolution failure on parameter");
+ return new ErrorType (type.get_ref ());
}
i++;
@@ -274,15 +312,15 @@ TypeCheckMethodCallExpr::visit (FnType &type)
if (i != num_args_to_call)
{
- rust_error_at (call.get_locus (),
+ rust_error_at (call_locus,
"unexpected number of arguments %lu expected %lu",
- (unsigned long) i, (unsigned long) call.num_params ());
- return;
+ (unsigned long) i, (unsigned long) arguments.size ());
+ return new ErrorType (type.get_ref ());
}
type.monomorphize ();
- resolved = type.get_return_type ()->monomorphized_clone ();
+ return type.get_return_type ()->monomorphized_clone ();
}
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index 51817e6..eef567a 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -84,58 +84,51 @@ private:
Analysis::Mappings *mappings;
};
-class TypeCheckMethodCallExpr : private TyVisitor
+class Argument
{
public:
- // Resolve the Method parameters and return back the return type
- static BaseType *go (BaseType *ref, HIR::MethodCallExpr &call,
- TyTy::BaseType *adjusted_self,
- Resolver::TypeCheckContext *context)
- {
- TypeCheckMethodCallExpr checker (call, adjusted_self, context);
- ref->accept_vis (checker);
- return checker.resolved;
- }
+ Argument (Analysis::NodeMapping mapping, BaseType *argument_type,
+ Location locus)
+ : mapping (mapping), argument_type (argument_type), locus (locus)
+ {}
- void visit (InferType &) override { gcc_unreachable (); }
- void visit (TupleType &) override { gcc_unreachable (); }
- void visit (ArrayType &) override { gcc_unreachable (); }
- void visit (SliceType &) override { gcc_unreachable (); }
- void visit (BoolType &) override { gcc_unreachable (); }
- void visit (IntType &) override { gcc_unreachable (); }
- void visit (UintType &) override { gcc_unreachable (); }
- void visit (FloatType &) override { gcc_unreachable (); }
- void visit (USizeType &) override { gcc_unreachable (); }
- void visit (ISizeType &) override { gcc_unreachable (); }
- void visit (ErrorType &) override { gcc_unreachable (); }
- void visit (ADTType &) override { gcc_unreachable (); };
- void visit (CharType &) override { gcc_unreachable (); }
- void visit (ReferenceType &) override { gcc_unreachable (); }
- void visit (PointerType &) override { gcc_unreachable (); }
- void visit (ParamType &) override { gcc_unreachable (); }
- void visit (StrType &) override { gcc_unreachable (); }
- void visit (NeverType &) override { gcc_unreachable (); }
- void visit (PlaceholderType &) override { gcc_unreachable (); }
- void visit (ProjectionType &) override { gcc_unreachable (); }
- void visit (DynamicObjectType &) override { gcc_unreachable (); }
+ Location get_locus () const { return locus; }
- // FIXME
- void visit (FnPtr &type) override { gcc_unreachable (); }
+ BaseType *get_argument_type () { return argument_type; }
- // call fns
- void visit (FnType &type) override;
- void visit (ClosureType &type) override { gcc_unreachable (); }
+ Analysis::NodeMapping get_mappings () const { return mapping; }
private:
- TypeCheckMethodCallExpr (HIR::MethodCallExpr &c,
+ Analysis::NodeMapping mapping;
+ BaseType *argument_type;
+ Location locus;
+};
+
+class TypeCheckMethodCallExpr
+{
+public:
+ static BaseType *go (FnType *ref, HIR::MethodCallExpr &call,
+ TyTy::BaseType *adjusted_self,
+ Resolver::TypeCheckContext *context);
+
+ static BaseType *go (FnType *ref, Analysis::NodeMapping call_mappings,
+ std::vector<Argument> &args, Location call_locus,
+ Location receiver_locus, TyTy::BaseType *adjusted_self,
+ Resolver::TypeCheckContext *context);
+
+protected:
+ BaseType *check (FnType &type);
+
+ TypeCheckMethodCallExpr (Analysis::NodeMapping call_mappings,
+ std::vector<Argument> &args, Location call_locus,
+ Location receiver_locus,
TyTy::BaseType *adjusted_self,
- Resolver::TypeCheckContext *context)
- : resolved (nullptr), call (c), adjusted_self (adjusted_self),
- context (context), mappings (Analysis::Mappings::get ())
- {}
+ Resolver::TypeCheckContext *context);
- BaseType *resolved;
- HIR::MethodCallExpr &call;
+ Analysis::NodeMapping call_mappings;
+ std::vector<Argument> &arguments;
+ Location call_locus;
+ Location receiver_locus;
TyTy::BaseType *adjusted_self;
Resolver::TypeCheckContext *context;
Analysis::Mappings *mappings;
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index cc8a180..23e52d9 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -871,6 +871,29 @@ public:
ok = true;
}
+ void visit (const ClosureType &type) override
+ {
+ if (base->get_def_id () != type.get_def_id ())
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ if (!base->get_parameters ().can_eq (&type.get_parameters (), false))
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ if (!base->get_result_type ().can_eq (&type.get_result_type (), false))
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const ClosureType *base;
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 40e7c44..fe654ca 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -624,7 +624,45 @@ class ClosureRules : public BaseRules
public:
ClosureRules (ClosureType *base) : BaseRules (base), base (base) {}
- // TODO
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (ClosureType &type) override
+ {
+ if (base->get_def_id () != type.get_def_id ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ TyTy::BaseType *args_res
+ = base->get_parameters ().unify (&type.get_parameters ());
+ if (args_res == nullptr || args_res->get_kind () == TypeKind::ERROR)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ TyTy::BaseType *res
+ = base->get_result_type ().unify (&type.get_result_type ());
+ if (res == nullptr || res->get_kind () == TypeKind::ERROR)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
private:
BaseType *get_base () override { return base; }
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 366de80..e56bdd1 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -27,6 +27,7 @@
#include "rust-substitution-mapper.h"
#include "rust-hir-trait-ref.h"
#include "rust-hir-type-bounds.h"
+#include "rust-hir-trait-resolve.h"
#include "options.h"
namespace Rust {
@@ -200,6 +201,7 @@ BaseType::bounds_compatible (const BaseType &other, Location locus,
rust_error_at (r,
"bounds not satisfied for %s %<%s%> is not satisfied",
other.get_name ().c_str (), missing_preds.c_str ());
+ // rust_assert (!emit_error);
}
}
@@ -1672,7 +1674,9 @@ ClosureType::accept_vis (TyConstVisitor &vis) const
std::string
ClosureType::as_string () const
{
- return "TODO";
+ std::string params_buf = parameters->as_string ();
+ return "|" + params_buf + "| {" + result_type.get_tyty ()->as_string ()
+ + "} {" + raw_bounds_as_string () + "}";
}
BaseType *
@@ -1692,15 +1696,26 @@ ClosureType::can_eq (const BaseType *other, bool emit_errors) const
bool
ClosureType::is_equal (const BaseType &other) const
{
- gcc_unreachable ();
- return false;
+ if (other.get_kind () != TypeKind::CLOSURE)
+ return false;
+
+ const ClosureType &other2 = static_cast<const ClosureType &> (other);
+ if (get_def_id () != other2.get_def_id ())
+ return false;
+
+ if (!get_parameters ().is_equal (other2.get_parameters ()))
+ return false;
+
+ return get_result_type ().is_equal (other2.get_result_type ());
}
BaseType *
ClosureType::clone () const
{
- return new ClosureType (get_ref (), get_ty_ref (), ident, id, parameter_types,
- result_type, clone_substs (), get_combined_refs ());
+ return new ClosureType (get_ref (), get_ty_ref (), ident, id,
+ (TyTy::TupleType *) parameters->clone (), result_type,
+ clone_substs (), get_combined_refs (),
+ specified_bounds);
}
BaseType *
@@ -1717,6 +1732,52 @@ ClosureType::handle_substitions (SubstitutionArgumentMappings mappings)
}
void
+ClosureType::setup_fn_once_output () const
+{
+ // lookup the lang items
+ auto fn_once_lang_item = Analysis::RustLangItem::ItemType::FN_ONCE;
+ auto fn_once_output_lang_item
+ = Analysis::RustLangItem::ItemType::FN_ONCE_OUTPUT;
+
+ DefId trait_id = UNKNOWN_DEFID;
+ bool trait_lang_item_defined
+ = mappings->lookup_lang_item (fn_once_lang_item, &trait_id);
+ rust_assert (trait_lang_item_defined);
+
+ DefId trait_item_id = UNKNOWN_DEFID;
+ bool trait_item_lang_item_defined
+ = mappings->lookup_lang_item (fn_once_output_lang_item, &trait_item_id);
+ rust_assert (trait_item_lang_item_defined);
+
+ // resolve to the trait
+ HIR::Item *item = mappings->lookup_defid (trait_id);
+ rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
+ HIR::Trait *trait = static_cast<HIR::Trait *> (item);
+
+ Resolver::TraitReference *trait_ref
+ = Resolver::TraitResolver::Resolve (*trait);
+ rust_assert (!trait_ref->is_error ());
+
+ // resolve to trait item
+ HIR::TraitItem *trait_item
+ = mappings->lookup_trait_item_defid (trait_item_id);
+ rust_assert (trait_item != nullptr);
+ rust_assert (trait_item->get_item_kind ()
+ == HIR::TraitItem::TraitItemKind::TYPE);
+ std::string item_identifier = trait_item->trait_identifier ();
+
+ // setup associated types #[lang = "fn_once_output"]
+ Resolver::TraitItemReference *item_reference = nullptr;
+ bool found = trait_ref->lookup_trait_item_by_type (
+ item_identifier, Resolver::TraitItemReference::TraitItemType::TYPE,
+ &item_reference);
+ rust_assert (found);
+
+ // setup
+ item_reference->associated_type_set (&get_result_type ());
+}
+
+void
ArrayType::accept_vis (TyVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 998ed63..9a9f0aa 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1626,31 +1626,35 @@ class ClosureType : public BaseType, public SubstitutionRef
{
public:
ClosureType (HirId ref, DefId id, RustIdent ident,
- std::vector<TyVar> parameter_types, TyVar result_type,
+ TyTy::TupleType *parameters, TyVar result_type,
std::vector<SubstitutionParamMapping> subst_refs,
- std::set<HirId> refs = std::set<HirId> ())
+ std::set<HirId> refs = std::set<HirId> (),
+ std::vector<TypeBoundPredicate> specified_bounds
+ = std::vector<TypeBoundPredicate> ())
: BaseType (ref, ref, TypeKind::CLOSURE, ident, refs),
SubstitutionRef (std::move (subst_refs),
SubstitutionArgumentMappings::error ()),
- parameter_types (std::move (parameter_types)),
- result_type (std::move (result_type)), id (id)
+ parameters (parameters), result_type (std::move (result_type)), id (id)
{
LocalDefId local_def_id = id.localDefId;
rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID);
+ inherit_bounds (specified_bounds);
}
ClosureType (HirId ref, HirId ty_ref, RustIdent ident, DefId id,
- std::vector<TyVar> parameter_types, TyVar result_type,
+ TyTy::TupleType *parameters, TyVar result_type,
std::vector<SubstitutionParamMapping> subst_refs,
- std::set<HirId> refs = std::set<HirId> ())
+ std::set<HirId> refs = std::set<HirId> (),
+ std::vector<TypeBoundPredicate> specified_bounds
+ = std::vector<TypeBoundPredicate> ())
: BaseType (ref, ty_ref, TypeKind::CLOSURE, ident, refs),
SubstitutionRef (std::move (subst_refs),
SubstitutionArgumentMappings::error ()),
- parameter_types (std::move (parameter_types)),
- result_type (std::move (result_type)), id (id)
+ parameters (parameters), result_type (std::move (result_type)), id (id)
{
LocalDefId local_def_id = id.localDefId;
rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID);
+ inherit_bounds (specified_bounds);
}
void accept_vis (TyVisitor &vis) override;
@@ -1669,13 +1673,8 @@ public:
bool is_concrete () const override final
{
- for (auto &param : parameter_types)
- {
- auto p = param.get_tyty ();
- if (!p->is_concrete ())
- return false;
- }
- return result_type.get_tyty ()->is_concrete ();
+ return parameters->is_concrete ()
+ && result_type.get_tyty ()->is_concrete ();
}
bool needs_generic_substitutions () const override final
@@ -1693,8 +1692,15 @@ public:
ClosureType *
handle_substitions (SubstitutionArgumentMappings mappings) override final;
+ TyTy::TupleType &get_parameters () const { return *parameters; }
+ TyTy::BaseType &get_result_type () const { return *result_type.get_tyty (); }
+
+ DefId get_def_id () const { return id; }
+
+ void setup_fn_once_output () const;
+
private:
- std::vector<TyVar> parameter_types;
+ TyTy::TupleType *parameters;
TyVar result_type;
DefId id;
};
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index a50f139..111a867 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -75,6 +75,7 @@ public:
// functions
FN_ONCE,
+ FN_ONCE_OUTPUT,
UNKNOWN,
};
@@ -225,6 +226,10 @@ public:
{
return ItemType::FN_ONCE;
}
+ else if (item.compare ("fn_once_output") == 0)
+ {
+ return ItemType::FN_ONCE_OUTPUT;
+ }
return ItemType::UNKNOWN;
}
@@ -305,6 +310,8 @@ public:
return "const_slice_ptr";
case FN_ONCE:
return "fn_once";
+ case FN_ONCE_OUTPUT:
+ return "fn_once_output";
case UNKNOWN:
return "<UNKNOWN>";
diff --git a/gcc/testsuite/rust/execute/torture/closure1.rs b/gcc/testsuite/rust/execute/torture/closure1.rs
new file mode 100644
index 0000000..62afa78
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/closure1.rs
@@ -0,0 +1,18 @@
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+fn main() -> i32 {
+ let closure_annotated = |i: i32| -> i32 { i + 1 };
+
+ let i = 1;
+ closure_annotated(i) - 2
+}
diff --git a/gcc/testsuite/rust/execute/torture/closure2.rs b/gcc/testsuite/rust/execute/torture/closure2.rs
new file mode 100644
index 0000000..45b3b5c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/closure2.rs
@@ -0,0 +1,32 @@
+// { dg-output "3\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+fn f<F: FnOnce(i32) -> i32>(g: F) {
+ let call = g(1);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, call);
+ }
+}
+
+pub fn main() -> i32 {
+ let a = |i: i32| {
+ let b = i + 2;
+ b
+ };
+ f(a);
+ 0
+}