The return statement ends the flow of execution within a
function, returning execution to the caller. Its syntax is:
return[ expression ];
If the function returns a value to the caller, that value is provided by an expression in the return statement. For example:
fn Sum(a: i32, b: i32) -> i32 {
return a + b;
}When a return type is specified, a function must always return before
control flow can reach the end of the function body. In other words,
fn DoNothing() -> i32 {} would be invalid because execution will reach the end
of the function body without returning a value.
Returning an empty tuple () is special, and similar to C++'s void returns.
When a function has no specified return type, its return type is implicitly
(). return must not have an expression argument in this case. It also has an
implicit return; at the end of the function body. For example:
// No return type is specified, so this returns `()` implicitly.
fn MaybeDraw(should_draw: bool) {
if (!should_draw) {
// No expression is passed to `return`.
return;
}
ActuallyDraw();
// There is an implicit `return;` here.
}When -> () is specified in the function signature, the return expression is
required. Omitting -> () is encouraged, but specifying it is supported for
generalized code structures, including templates. In order to
be consistent with other explicitly specified return types, return; is invalid
in this case. For example:
// `-> ()` defines an explicit return value.
fn MaybeDraw(should_draw: bool) -> () {
if (!should_draw) {
// As a consequence, a return value must be passed.
return ();
}
ActuallyDraw();
// The return value must again be explicit.
return ();
}Variables may be declared with a returned statement. Its
syntax is:
returnedvar statement
When a variable is marked as returned, it must be the only returned value
in-scope.
If a returned var is returned, the specific syntax return var must be used.
Returning expressions is not allowed while a returned var is in scope. For
example:
fn MakeCircle(radius: i32) -> Circle {
returned var c: Circle;
c.radius = radius;
// `return c` would be invalid because `returned` is in use.
return var;
}If control flow exits the scope of a returned variable in any way other than
return var, the returned var's lifetime ends as normal. When this occurs,
return may again be used with expressions. For example:
fn MakePointInArea(area: Area, preferred_x: i32, preferred_y: i32) -> Point {
if (preferred_x >= 0 && preferred_y >= 0) {
returned var p: Point = { .x = preferred_x, .y = preferred_y };
if (area.Contains(p)) {
return var;
}
// p's lifetime ends here when `return var` is not reached.
}
return area.RandomPoint();
}Consider the following common initialization code:
fn CreateMyObject() -> MyType {
return <expression>;
}
var x: MyType = CreateMyObject();The <expression> in the return statement of CreateMyObject initializes the
variable x here. There is no copy or similar. It is equivalent to:
var x: MyType = <expression>;This applies recursively, similar to C++'s guaranteed copy elision.
In the case where additional statements should be run between constructing the
return value and returning, the use of returned var allows for improved
efficiency because the returned var can directly use the address of var
declared by the caller. For example, here the returned var vector in
CreateVector uses the storage of my_vector for initialization, avoiding a
copy:
fn CreateVector(x: i32, y: i32) -> Vector {
returned var vector: Vector;
vector.x = x;
vector.y = y;
return var;
}
var my_vector: Vector = CreateVector(1, 2);As a consequence, returned var is encouraged because it makes it easier to
avoid copies.
TODO: Have some discussion of RVO and NRVO as they are found in C++ here, and the fact that Carbon provides the essential part of these as first-class featuers and therefore they are never "optimizations" or done implicitly or optionally.
- Implicit or expression returns
- Named return variable in place of a return type
- Retain the C++ rule
- Fully divorce functions and procedures
- Proposal #257: Initialization of memory and variables
- Proposal
#415: Syntax:
return - Proposal
#538:
returnwith no argument