From 65a0a8b38663751870264fb73815c5586f324b47 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 23 May 2021 10:21:25 -0700 Subject: [PATCH 1/2] Stabilize ops::ControlFlow (just the type) --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 - compiler/rustc_traits/src/lib.rs | 1 - library/core/src/iter/traits/iterator.rs | 41 ++++++++++++++++++++++++ library/core/src/ops/control_flow.rs | 6 ++-- library/core/src/ops/try_trait.rs | 5 --- library/core/tests/lib.rs | 1 - 8 files changed, 45 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 56f97054f9624..7e1761ea868cf 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -332,7 +332,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 300d2c01cb5d0..b1dd942719820 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 14ee083eceebe..8b682d068c071 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -414,7 +414,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 777e4bc2c8920..922133fa6994f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1993,6 +1993,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 @@ -2035,6 +2060,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 dbb51540bd475..4a7da1c3cac99 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.54.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.54.0")] #[cfg_attr(not(bootstrap), lang = "Continue")] Continue(C), /// Exit the operation without running subsequent phases. + #[stable(feature = "control_flow_enum_type", since = "1.54.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 87044ed2fcee1..8628db13ed5fb 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)); @@ -304,7 +300,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 db12d79c00c30..4cc2765dc7d95 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)] From 590d4526e91d77cc514deb58c3d87e30b3f74db6 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 14 Jun 2021 10:37:05 -0700 Subject: [PATCH 2/2] Master is 1.55 now :( --- library/core/src/ops/control_flow.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 4a7da1c3cac99..ff1e968a8d113 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -46,15 +46,15 @@ use crate::{convert, ops}; /// } /// } /// ``` -#[stable(feature = "control_flow_enum_type", since = "1.54.0")] +#[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.54.0")] + #[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.54.0")] + #[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.