Call Expressions
A call expression invokes a function with a list of arguments.
call_expr = expression "(" [ call_arg { "," call_arg } ] ")" ;
call_arg = [ "inout" | "borrow" ] expression ;
An inout or borrow argument must denote a place; that requirement is a post-parse legality rule of the parameter-mode system (6.1:17), not a grammar restriction (see the grammar notes in appendix A).
The number of arguments MUST match the number of parameters in the function signature.
Each argument's type MUST be the corresponding parameter's type. As everywhere, the one admitted coercion is from the never type (3.4:3); no other type difference is accepted (core calculus docs/formal/01-core-calculus.md §5.8, rule (Call)).
The type of a call expression is the function's declared return type (core calculus docs/formal/01-core-calculus.md §5.8, rule (Call)).
A call expression evaluates to the value the invocation returns: the callee's body is evaluated with each parameter bound to its corresponding argument — a by-value argument's evaluated value in fresh storage, or, for an inout/borrow argument, the argument place itself (6.1:18) — and the value the body produces (see 4.5 and 4.9) is the call expression's value (core calculus docs/formal/01-core-calculus.md §6.9, rules (D-Call)/(D-Return-Value)). When the return type is (), the call evaluates to ().
Passing an argument by value is a use of it — a move for a non-Copy type, a copy for a Copy type (3.8:11). An inout/borrow argument is not used; it takes a scoped loan for the call's duration (6.1; core calculus docs/formal/01-core-calculus.md §5.4). Those rules are specified in sections 3.8 and 6.1, not here.
fn add(x: i32, y: i32) -> i32 {
x + y
}
fn main() -> i32 {
add(40, 2) // 42
}
Arguments are evaluated left-to-right before the function is called, as specified in section 4.0 (core calculus docs/formal/01-core-calculus.md §6.2).
Call expressions can be nested:
fn add(x: i32, y: i32) -> i32 { x + y }
fn main() -> i32 {
add(add(10, 20), add(5, 7)) // 42
}