mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 19:53:46 +00:00
Rollup merge of #42016 - pietroalbini:stabilize/loop_break_value, r=nikomatsakis
Stabilize the loop_break_value feature Tracking issue: #37339. Documentation PRs already sent to the various repositories.
This commit is contained in:
commit
e38d5d5039
@ -49,7 +49,6 @@
|
||||
- [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md)
|
||||
- [linkage](language-features/linkage.md)
|
||||
- [log_syntax](language-features/log-syntax.md)
|
||||
- [loop_break_value](language-features/loop-break-value.md)
|
||||
- [macro_reexport](language-features/macro-reexport.md)
|
||||
- [macro_vis_matcher](language-features/macro-vis-matcher.md)
|
||||
- [main](language-features/main.md)
|
||||
|
@ -1,83 +0,0 @@
|
||||
# `loop_break_value`
|
||||
|
||||
The tracking issue for this feature is: [#37339]
|
||||
|
||||
[#37339]: https://github.com/rust-lang/rust/issues/37339
|
||||
|
||||
Documentation to be appended to section G of the book.
|
||||
|
||||
------------------------
|
||||
|
||||
### Loops as expressions
|
||||
|
||||
Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop
|
||||
never exits.
|
||||
A `loop` can instead evaluate to a useful value via *break with value*:
|
||||
|
||||
```rust
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
// Find the first square number over 1000:
|
||||
let mut n = 1;
|
||||
let square = loop {
|
||||
if n * n > 1000 {
|
||||
break n * n;
|
||||
}
|
||||
n += 1;
|
||||
};
|
||||
```
|
||||
|
||||
The evaluation type may be specified externally:
|
||||
|
||||
```rust
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
// Declare that value returned is unsigned 64-bit:
|
||||
let n: u64 = loop {
|
||||
break 1;
|
||||
};
|
||||
```
|
||||
|
||||
It is an error if types do not agree, either between a "break" value and an external requirement,
|
||||
or between multiple "break" values:
|
||||
|
||||
```no_compile
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
loop {
|
||||
if true {
|
||||
break 1u32;
|
||||
} else {
|
||||
break 0u8; // error: types do not agree
|
||||
}
|
||||
};
|
||||
|
||||
let n: i32 = loop {
|
||||
break 0u32; // error: type does not agree with external requirement
|
||||
};
|
||||
```
|
||||
|
||||
#### Break: label, value
|
||||
|
||||
Four forms of `break` are available, where EXPR is some expression which evaluates to a value:
|
||||
|
||||
1. `break;`
|
||||
2. `break 'label;`
|
||||
3. `break EXPR;`
|
||||
4. `break 'label EXPR;`
|
||||
|
||||
When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`.
|
||||
|
||||
Using a label allows returning a value from an inner loop:
|
||||
|
||||
```rust
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
let result = 'outer: loop {
|
||||
for n in 1..10 {
|
||||
if n > 4 {
|
||||
break 'outer n;
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
@ -30,7 +30,6 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(libc)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(quote)]
|
||||
@ -45,6 +44,7 @@
|
||||
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
|
||||
#![cfg_attr(stage0, feature(rustc_private))]
|
||||
#![cfg_attr(stage0, feature(staged_api))]
|
||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||
|
||||
#![recursion_limit="128"]
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(libc)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
@ -32,6 +31,7 @@
|
||||
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
|
||||
#![cfg_attr(stage0, feature(rustc_private))]
|
||||
#![cfg_attr(stage0, feature(staged_api))]
|
||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||
|
||||
extern crate arena;
|
||||
extern crate getopts;
|
||||
|
@ -76,7 +76,6 @@ This API is completely unstable and subject to change.
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
@ -84,6 +83,7 @@ This API is completely unstable and subject to change.
|
||||
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
|
||||
#![cfg_attr(stage0, feature(rustc_private))]
|
||||
#![cfg_attr(stage0, feature(staged_api))]
|
||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
@ -297,9 +297,6 @@ declare_features! (
|
||||
|
||||
(active, use_extern_macros, "1.15.0", Some(35896)),
|
||||
|
||||
// Allows `break {expr}` with a value inside `loop`s.
|
||||
(active, loop_break_value, "1.14.0", Some(37339)),
|
||||
|
||||
// Allows #[target_feature(...)]
|
||||
(active, target_feature, "1.15.0", None),
|
||||
|
||||
@ -423,6 +420,8 @@ declare_features! (
|
||||
(accepted, pub_restricted, "1.18.0", Some(32409)),
|
||||
// The #![windows_subsystem] attribute
|
||||
(accepted, windows_subsystem, "1.18.0", Some(37499)),
|
||||
// Allows `break {expr}` with a value inside `loop`s.
|
||||
(accepted, loop_break_value, "1.19.0", Some(37339)),
|
||||
);
|
||||
// If you change this, please modify src/doc/unstable-book as well. You must
|
||||
// move that documentation into the relevant place in the other docs, and
|
||||
@ -1301,10 +1300,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Break(_, Some(_)) => {
|
||||
gate_feature_post!(&self, loop_break_value, e.span,
|
||||
"`break` with a value is experimental");
|
||||
}
|
||||
ast::ExprKind::Lit(ref lit) => {
|
||||
if let ast::LitKind::Int(_, ref ty) = lit.node {
|
||||
match *ty {
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
loop {
|
||||
break 123; //~ ERROR `break` with a value is experimental
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
|
||||
fn main() {
|
||||
|
@ -15,7 +15,6 @@
|
||||
// like to revisit these and potentially change them. --nmatsakis
|
||||
|
||||
#![feature(never_type)]
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
trait BadDefault {
|
||||
fn default() -> Self;
|
||||
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
|
||||
#[allow(unused)]
|
||||
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(loop_break_value)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use std::ptr;
|
||||
|
@ -1,7 +1,7 @@
|
||||
error[E0571]: `break` with value from a `for` loop
|
||||
--> $DIR/loop-break-value-no-repeat.rs:23:9
|
||||
--> $DIR/loop-break-value-no-repeat.rs:22:9
|
||||
|
|
||||
23 | break 22
|
||||
22 | break 22
|
||||
| ^^^^^^^^ can only break with a value inside `loop`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user