diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0ff1efd8165ea..3e278a447f0b4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -331,7 +331,7 @@ pub fn lower_crate<'a, 'hir>( lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), - allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()), + allow_try_trait: Some([sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), } .lower_crate(krate) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6d5531d330783..00f0fe4a28894 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -11,7 +11,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(bool_to_option)] -#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(iter_zip)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fb37c5e9c1eff..a96d37c652d12 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -416,7 +416,6 @@ symbols! { constructor, contents, context, - control_flow_enum, convert, copy, copy_closures, diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 7b688cd3e2199..d0b05beb4e63c 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -4,7 +4,6 @@ #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(control_flow_enum)] #![recursion_limit = "256"] #[macro_use] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 11dea400a46ef..78d317096b4f6 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1959,6 +1959,31 @@ pub trait Iterator { /// assert_eq!(it.len(), 2); /// assert_eq!(it.next(), Some(&40)); /// ``` + /// + /// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`] + /// type allows a similar idea: + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// let triangular = (1..30).try_fold(0_i8, |prev, x| { + /// if let Some(next) = prev.checked_add(x) { + /// ControlFlow::Continue(next) + /// } else { + /// ControlFlow::Break(prev) + /// } + /// }); + /// assert_eq!(triangular, ControlFlow::Break(120)); + /// + /// let triangular = (1..30).try_fold(0_u64, |prev, x| { + /// if let Some(next) = prev.checked_add(x) { + /// ControlFlow::Continue(next) + /// } else { + /// ControlFlow::Break(prev) + /// } + /// }); + /// assert_eq!(triangular, ControlFlow::Continue(435)); + /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_fold(&mut self, init: B, mut f: F) -> R @@ -2001,6 +2026,22 @@ pub trait Iterator { /// // It short-circuited, so the remaining items are still in the iterator: /// assert_eq!(it.next(), Some("stale_bread.json")); /// ``` + /// + /// The [`crate::ops::ControlFlow`] type can be used with this method for the + /// situations in which you'd use `break` and `continue` in a normal loop: + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// let r = (2..100).try_for_each(|x| { + /// if 323 % x == 0 { + /// return ControlFlow::Break(x) + /// } + /// + /// ControlFlow::Continue(()) + /// }); + /// assert_eq!(r, ControlFlow::Break(17)); + /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_for_each(&mut self, f: F) -> R diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 9d9398fb56d8a..c26b5c677105b 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -11,7 +11,6 @@ use crate::{convert, ops}; /// /// Early-exiting from [`Iterator::try_for_each`]: /// ``` -/// #![feature(control_flow_enum)] /// use std::ops::ControlFlow; /// /// let r = (2..100).try_for_each(|x| { @@ -26,7 +25,6 @@ use crate::{convert, ops}; /// /// A basic tree traversal: /// ```no_run -/// #![feature(control_flow_enum)] /// use std::ops::ControlFlow; /// /// pub struct TreeNode { @@ -48,13 +46,15 @@ use crate::{convert, ops}; /// } /// } /// ``` -#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] +#[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow { /// Move on to the next phase of the operation as normal. + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[cfg_attr(not(bootstrap), lang = "Continue")] Continue(C), /// Exit the operation without running subsequent phases. + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[cfg_attr(not(bootstrap), lang = "Break")] Break(B), // Yes, the order of the variants doesn't match the type parameters. diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 1d9bc452618e2..0eec52a8701c7 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -55,7 +55,6 @@ use crate::ops::ControlFlow; /// into the return type using [`Try::from_output`]: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(control_flow_enum)] /// # use std::ops::{ControlFlow, Try}; /// fn simple_try_fold_2>( /// iter: impl Iterator, @@ -79,7 +78,6 @@ use crate::ops::ControlFlow; /// recreated from their corresponding residual, so we'll just call it: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(control_flow_enum)] /// # use std::ops::{ControlFlow, Try}; /// pub fn simple_try_fold_3>( /// iter: impl Iterator, @@ -170,7 +168,6 @@ pub trait Try: FromResidual { /// /// ``` /// #![feature(try_trait_v2)] - /// #![feature(control_flow_enum)] /// use std::ops::Try; /// /// assert_eq!( as Try>::from_output(3), Ok(3)); @@ -202,7 +199,6 @@ pub trait Try: FromResidual { /// /// ``` /// #![feature(try_trait_v2)] - /// #![feature(control_flow_enum)] /// use std::ops::{ControlFlow, Try}; /// /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); @@ -329,7 +325,6 @@ pub trait FromResidual::Residual> { /// /// ``` /// #![feature(try_trait_v2)] - /// #![feature(control_flow_enum)] /// use std::ops::{ControlFlow, FromResidual}; /// /// assert_eq!(Result::::from_residual(Err(3_u8)), Err(3)); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 16051b3bc36c7..65fca67b4f290 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -15,7 +15,6 @@ #![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_ptr_offset)] -#![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)]