Skip to content

Commit

Permalink
Changes resulting from Ericson2314's observations, in particular `bre…
Browse files Browse the repository at this point in the history
…ak panic!();`
  • Loading branch information
dhardy committed May 20, 2016
1 parent 4500c23 commit ba6b0cc
Showing 1 changed file with 30 additions and 26 deletions.
56 changes: 30 additions & 26 deletions text/0000-loop-break-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,17 @@ fn h() -> ! {
}
```

This proposal changes the type to `T`, where:
This proposal changes the result type of 'loop' to `T`, where:

* a loop which is never "broken" via `break` has result-type `!` (which is coercible to anything, as of today)
* where a loop is "broken" via `break;` or `break 'label;`, its result type is `()`
* where a loop is "broken" via `break EXPR;` or `break 'label EXPR;`, `EXPR` must evaluate to type `T`
* a loop's return type may be deduced from its context, e.g. `let x: T = loop { ... };`
* if a loop is "broken" via `break;` or `break 'label;`, the loop's result type must be `()`
* if a loop is "broken" via `break EXPR;` or `break 'label EXPR;`, `EXPR` must evaluate to type `T`
* as a special case, if a loop is "broken" via `break EXPR;` or `break 'label EXPR;` where `EXPR` evaluates to type `!` (does not return), this does not place a constraint on the type of the loop
* if external constaint on the loop's result type exist (e.g. `let x: S = loop { ... };`), then `T` must be coercible to this type

It is an error if these types do not agree. Examples:
It is an error if these types do not agree or if the compiler's type deduction
rules do not yield a concrete type.

Examples of errors:

```rust
// error: loop type must be () and must be i32
Expand All @@ -115,7 +118,7 @@ fn z() -> ! {
}
```

Where a loop does not break, the return type is coercible:
Examples involving `!`:

```rust
fn f() -> () {
Expand All @@ -126,6 +129,25 @@ fn g() -> u32 {
// ! coerces to u32
loop {}
}
fn z() -> ! {
loop {
break panic!();
}
}
```

Example showing the equivalence of `break;` and `break ();`:

```rust
fn y() -> () {
loop {
if coin_flip() {
break;
} else {
break ();
}
}
}
```

### Result value
Expand All @@ -135,7 +157,7 @@ in which case it yields the value resulting from the evaulation of the
statement's expression (`EXPR` above), or `()` if there is no `EXPR`
expression.

## Examples
Examples:

```rust
assert_eq!(loop { break; }, ());
Expand All @@ -148,24 +170,6 @@ let x = 'a loop {
};
assert_eq!(x, 1);
```
```rust
fn y() -> () {
loop {
if coin_flip() {
break;
} else {
break ();
}
}
}
```
```rust
fn z() -> ! {
loop {
break panic!();
}
}
```

# Drawbacks
[drawbacks]: #drawbacks
Expand Down

0 comments on commit ba6b0cc

Please sign in to comment.