Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e836a2f
implement continue_ok and break_ok for ControlFlow
jogru0 Apr 24, 2025
b981b84
moved simple test to coretests, introduced more fleshed out doctests …
jogru0 Apr 26, 2025
6dbac3f
add nvptx_target_feature
jedbrown Feb 27, 2025
35a485d
target-feature: enable rust target features implied by target-cpu
jedbrown May 22, 2025
4f1c4e2
don't schedule unnecessary drops when lowering or-patterns
dianne Jul 9, 2025
fee2dfd
base drop order on the first sub-branch
dianne Jul 9, 2025
19ce23c
lower bindings in the order they're written
dianne Jul 10, 2025
ec40ee4
Add documentation for unstable_feature_bound
tiif Jul 30, 2025
712c28e
Remove space
tiif Jul 30, 2025
1eb9b13
Change visibility of Args new function
chotchki Aug 2, 2025
23e6be2
Port #[macro_export] to the new attribute parsing infrastructure
Periodic1911 Jul 12, 2025
f6ce4ac
Anonymize binders in tail call sig
compiler-errors Aug 2, 2025
904e2af
Port `#[coroutine]` to the new attribute system
scrabsha Aug 1, 2025
91e606b
Tweak auto trait errors
estebank Feb 28, 2025
3c6d8a2
Rollup merge of #137831 - estebank:auto-trait-err, r=compiler-errors
tgross35 Aug 6, 2025
a92f396
Rollup merge of #138689 - jedbrown:jed/nvptx-target-feature, r=ZuseZ4
tgross35 Aug 6, 2025
b2c80e2
Rollup merge of #140267 - jogru0:control_flow, r=dtolnay
tgross35 Aug 6, 2025
5c42ae5
Rollup merge of #143764 - dianne:primary-binding-drop-order, r=Nadrie…
tgross35 Aug 6, 2025
daa6ead
Rollup merge of #143857 - Periodic1911:macro-export, r=jdonszelmann
tgross35 Aug 6, 2025
a8a7a3d
Rollup merge of #144676 - tiif:dev_guide_unstable_bound, r=BoxyUwU
tgross35 Aug 6, 2025
7ed6dca
Rollup merge of #144794 - scrabsha:push-noqrrttovmwy, r=jdonszelmann
tgross35 Aug 6, 2025
1c2054b
Rollup merge of #144835 - compiler-errors:tail-call-sig-binder, r=Waf…
tgross35 Aug 6, 2025
4d43539
Rollup merge of #144836 - chotchki:patch-1, r=tgross35
tgross35 Aug 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions library/core/src/ops/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,80 @@ impl<B, C> ControlFlow<B, C> {
}
}

/// Converts the `ControlFlow` into an `Result` which is `Ok` if the
/// `ControlFlow` was `Break` and `Err` if otherwise.
///
/// # Examples
///
/// ```
/// #![feature(control_flow_ok)]
///
/// use std::ops::ControlFlow;
///
/// struct TreeNode<T> {
/// value: T,
/// left: Option<Box<TreeNode<T>>>,
/// right: Option<Box<TreeNode<T>>>,
/// }
///
/// impl<T> TreeNode<T> {
/// fn find<'a>(&'a self, mut predicate: impl FnMut(&T) -> bool) -> Result<&'a T, ()> {
/// let mut f = |t: &'a T| -> ControlFlow<&'a T> {
/// if predicate(t) {
/// ControlFlow::Break(t)
/// } else {
/// ControlFlow::Continue(())
/// }
/// };
///
/// self.traverse_inorder(&mut f).break_ok()
/// }
///
/// fn traverse_inorder<'a, B>(
/// &'a self,
/// f: &mut impl FnMut(&'a T) -> ControlFlow<B>,
/// ) -> ControlFlow<B> {
/// if let Some(left) = &self.left {
/// left.traverse_inorder(f)?;
/// }
/// f(&self.value)?;
/// if let Some(right) = &self.right {
/// right.traverse_inorder(f)?;
/// }
/// ControlFlow::Continue(())
/// }
///
/// fn leaf(value: T) -> Option<Box<TreeNode<T>>> {
/// Some(Box::new(Self {
/// value,
/// left: None,
/// right: None,
/// }))
/// }
/// }
///
/// let node = TreeNode {
/// value: 0,
/// left: TreeNode::leaf(1),
/// right: Some(Box::new(TreeNode {
/// value: -1,
/// left: TreeNode::leaf(5),
/// right: TreeNode::leaf(2),
/// })),
/// };
///
/// let res = node.find(|val: &i32| *val > 3);
/// assert_eq!(res, Ok(&5));
/// ```
#[inline]
#[unstable(feature = "control_flow_ok", issue = "140266")]
pub fn break_ok(self) -> Result<B, C> {
match self {
ControlFlow::Continue(c) => Err(c),
ControlFlow::Break(b) => Ok(b),
}
}

/// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function
/// to the break value in case it exists.
#[inline]
Expand Down Expand Up @@ -218,6 +292,79 @@ impl<B, C> ControlFlow<B, C> {
}
}

/// Converts the `ControlFlow` into an `Result` which is `Ok` if the
/// `ControlFlow` was `Continue` and `Err` if otherwise.
///
/// # Examples
///
/// ```
/// #![feature(control_flow_ok)]
///
/// use std::ops::ControlFlow;
///
/// struct TreeNode<T> {
/// value: T,
/// left: Option<Box<TreeNode<T>>>,
/// right: Option<Box<TreeNode<T>>>,
/// }
///
/// impl<T> TreeNode<T> {
/// fn validate<B>(&self, f: &mut impl FnMut(&T) -> ControlFlow<B>) -> Result<(), B> {
/// self.traverse_inorder(f).continue_ok()
/// }
///
/// fn traverse_inorder<B>(&self, f: &mut impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> {
/// if let Some(left) = &self.left {
/// left.traverse_inorder(f)?;
/// }
/// f(&self.value)?;
/// if let Some(right) = &self.right {
/// right.traverse_inorder(f)?;
/// }
/// ControlFlow::Continue(())
/// }
///
/// fn leaf(value: T) -> Option<Box<TreeNode<T>>> {
/// Some(Box::new(Self {
/// value,
/// left: None,
/// right: None,
/// }))
/// }
/// }
///
/// let node = TreeNode {
/// value: 0,
/// left: TreeNode::leaf(1),
/// right: Some(Box::new(TreeNode {
/// value: -1,
/// left: TreeNode::leaf(5),
/// right: TreeNode::leaf(2),
/// })),
/// };
///
/// let res = node.validate(&mut |val| {
/// if *val < 0 {
/// return ControlFlow::Break("negative value detected");
/// }
///
/// if *val > 4 {
/// return ControlFlow::Break("too big value detected");
/// }
///
/// ControlFlow::Continue(())
/// });
/// assert_eq!(res, Err("too big value detected"));
/// ```
#[inline]
#[unstable(feature = "control_flow_ok", issue = "140266")]
pub fn continue_ok(self) -> Result<C, B> {
match self {
ControlFlow::Continue(c) => Ok(c),
ControlFlow::Break(b) => Err(b),
}
}

/// Maps `ControlFlow<B, C>` to `ControlFlow<B, T>` by applying a function
/// to the continue value in case it exists.
#[inline]
Expand Down
1 change: 1 addition & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#![feature(const_ref_cell)]
#![feature(const_result_trait_fn)]
#![feature(const_trait_impl)]
#![feature(control_flow_ok)]
#![feature(core_float_math)]
#![feature(core_intrinsics)]
#![feature(core_intrinsics_fallbacks)]
Expand Down
12 changes: 12 additions & 0 deletions library/coretests/tests/ops/control_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,15 @@ fn control_flow_discriminants_match_result() {
discriminant_value(&Result::<i32, i32>::Ok(3)),
);
}

#[test]
fn control_flow_break_ok() {
assert_eq!(ControlFlow::<char, i32>::Break('b').break_ok(), Ok('b'));
assert_eq!(ControlFlow::<char, i32>::Continue(3).break_ok(), Err(3));
}

#[test]
fn control_flow_continue_ok() {
assert_eq!(ControlFlow::<char, i32>::Break('b').continue_ok(), Err('b'));
assert_eq!(ControlFlow::<char, i32>::Continue(3).continue_ok(), Ok(3));
}