-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Define syntax for `return` in Carbon.
- Loading branch information
Showing
2 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
# Syntax: `return` | ||
|
||
<!-- | ||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM | ||
Exceptions. See /LICENSE for license information. | ||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
--> | ||
|
||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/415) | ||
|
||
<!-- toc --> | ||
|
||
## Table of contents | ||
|
||
- [Problem](#problem) | ||
- [Background](#background) | ||
- [Proposal](#proposal) | ||
- [Details](#details) | ||
- [Deferred questions](#deferred-questions) | ||
- [Alternatives considered](#alternatives-considered) | ||
- [Implicit or expression returns](#implicit-or-expression-returns) | ||
|
||
<!-- tocstop --> | ||
|
||
## Problem | ||
|
||
Carbon has functions. We should write down how those functions indicate their | ||
code should stop running and, if applicable, what result should be provided back | ||
to their caller. | ||
|
||
## Background | ||
|
||
The Carbon overview | ||
[contains](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/README.md#return) | ||
a "skeletal design" for `return`. | ||
|
||
Carbon aims for | ||
[_familiarity for experienced C++ developers with a gentle learning curve_](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code). | ||
C++ returns from functions with a `return` statement, which is documented well | ||
[here](https://en.cppreference.com/w/cpp/language/return). | ||
|
||
## Proposal | ||
|
||
Carbon will have a `return` statement that is unsurprising to C++ programmers. | ||
|
||
Each of these is a valid Carbon function: | ||
|
||
``` | ||
// A function that returns no value | ||
fn NoReturn() { | ||
// This function intentionally left blank | ||
} | ||
// A function that returns no value in a different way | ||
fn ReturnNoValue() { | ||
// Usually no expression in a function with no return value. | ||
return; | ||
} | ||
// A function that returns a value | ||
fn ReturnFive() -> Int { | ||
// Must include an expression "convertible" to `Int`. | ||
// The (lack of) definition for "convertible" is addressed later. | ||
return 5; | ||
} | ||
``` | ||
|
||
## Details | ||
|
||
We define a `return` statement in Carbon. It can occur any place a statement is | ||
allowed. It takes one optional expression, the _return value_. Functions may | ||
contain multiple `return` statements. | ||
|
||
A function that returns `Void` may have `return` statements. Most will have no | ||
return value, though some may provide a `Void`-type expression, for example the | ||
result of another `Void`-returning function. | ||
|
||
> This last affordance is provided to avoid making `Void` a special case in | ||
> templating. | ||
Functions returning `Void` are also defined to end with an implicit `return` | ||
statement. | ||
|
||
> This implicit `return` is intended to make it easier for later designs to | ||
> refer to "the (now always present) `return` statement" rather than the less | ||
> well-defined "the point the function returns". | ||
A function that returns anything other than `Void` must have at least one | ||
`return` statement. All `return` statements in the function must provide an | ||
expression "convertible" to the function's return type. If a control flow path | ||
reaches the end of the function without executing a `return` statement, it is a | ||
compile error. | ||
|
||
### Deferred questions | ||
|
||
This proposal is limited to the syntax and simple static semantics of the | ||
`return` statement. | ||
|
||
Some questions about the full validity and meaning of a `return` statement in | ||
context are left unresolved, in the expectation they will be addressed when | ||
adjacent parts of the language are specified. | ||
|
||
Those include: | ||
|
||
- **What does "convertible" mean?** | ||
|
||
When a function returns a value, we say the `return` statement takes an | ||
expression "convertible" to the function's return type. As a coarse | ||
approximation, this may mean "assignable to a variable of the function's | ||
return type", but there are likely to be subtleties. We assume this question | ||
will be addressed as the type system develops. | ||
|
||
- **What optimizations are encouraged or guaranteed for return values?** | ||
|
||
C++ has | ||
[copy elision](https://en.cppreference.com/w/cpp/language/copy_elision) and | ||
it's a good bet Carbon will too. But first we need to decide what copying | ||
means. | ||
|
||
- **What code, if any, runs between `return` and _returning_?** | ||
|
||
Carbon is likely to have approaches for deterministic cleanup that trigger | ||
when a function's code stops executing -- analogues to C++ destructors, | ||
Golang deferred functions, or Java's `finally` blocks. Once we know what | ||
they are and how we intend them to work, we can determine how to slot them | ||
in next to `return`. | ||
|
||
## Alternatives considered | ||
|
||
### Implicit or expression returns | ||
|
||
Some C-family languages allow an unadorned expression in the right context to | ||
serve as a return value. | ||
|
||
In Rust, for example, function bodies are | ||
[block expressions](https://doc.rust-lang.org/reference/expressions/block-expr.html), | ||
which may have an expression as their final clause and which take the value of | ||
that expression. | ||
|
||
This Rust function returns `5`: | ||
|
||
```rust | ||
fn return_five() -> i32 { | ||
perhaps_unrelated_action(); | ||
5 | ||
} | ||
``` | ||
|
||
Rust still has a `return` statement, so this is entirely an ergonomic feature. | ||
|
||
We can choose to add a similar feature to Carbon in the future as long as we can | ||
unambiguously discern expressions and statements in parsing. |