Rollup merge of #76318 - scottmcm:one-control-flow, r=ecstatic-morse
Use ops::ControlFlow in rustc_data_structures::graph::iterate Since I only know about this because you mentioned it, r? @ecstatic-morse If we're not supposed to use new `core` things in compiler for a while then feel free to close, but it felt reasonable to merge the two types since they're the same, and it might be convenient for people to use `?` in their traversal code. (This doesn't do the type parameter swap; NoraCodes has signed up to do that one.)
This commit is contained in:
commit
acd33e1d14
8 changed files with 63 additions and 21 deletions
|
@ -87,11 +87,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows searches to terminate early with a value.
|
/// Allows searches to terminate early with a value.
|
||||||
#[derive(Clone, Copy, Debug)]
|
// FIXME (#75744): remove the alias once the generics are in a better order and `C=()`.
|
||||||
pub enum ControlFlow<T> {
|
pub type ControlFlow<T> = std::ops::ControlFlow<(), T>;
|
||||||
Break(T),
|
|
||||||
Continue,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The status of a node in the depth-first search.
|
/// The status of a node in the depth-first search.
|
||||||
///
|
///
|
||||||
|
@ -260,12 +257,12 @@ where
|
||||||
_node: G::Node,
|
_node: G::Node,
|
||||||
_prior_status: Option<NodeStatus>,
|
_prior_status: Option<NodeStatus>,
|
||||||
) -> ControlFlow<Self::BreakVal> {
|
) -> ControlFlow<Self::BreakVal> {
|
||||||
ControlFlow::Continue
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called after all nodes reachable from this one have been examined.
|
/// Called after all nodes reachable from this one have been examined.
|
||||||
fn node_settled(&mut self, _node: G::Node) -> ControlFlow<Self::BreakVal> {
|
fn node_settled(&mut self, _node: G::Node) -> ControlFlow<Self::BreakVal> {
|
||||||
ControlFlow::Continue
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Behave as if no edges exist from `source` to `target`.
|
/// Behave as if no edges exist from `source` to `target`.
|
||||||
|
@ -289,8 +286,8 @@ where
|
||||||
prior_status: Option<NodeStatus>,
|
prior_status: Option<NodeStatus>,
|
||||||
) -> ControlFlow<Self::BreakVal> {
|
) -> ControlFlow<Self::BreakVal> {
|
||||||
match prior_status {
|
match prior_status {
|
||||||
Some(NodeStatus::Visited) => ControlFlow::Break(()),
|
Some(NodeStatus::Visited) => ControlFlow::BREAK,
|
||||||
_ => ControlFlow::Continue,
|
_ => ControlFlow::CONTINUE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(generators)]
|
#![feature(generators)]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(const_panic)]
|
#![feature(const_panic)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
|
|
|
@ -117,7 +117,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
|
||||||
// A diverging InlineAsm is treated as non-recursing
|
// A diverging InlineAsm is treated as non-recursing
|
||||||
TerminatorKind::InlineAsm { destination, .. } => {
|
TerminatorKind::InlineAsm { destination, .. } => {
|
||||||
if destination.is_some() {
|
if destination.is_some() {
|
||||||
ControlFlow::Continue
|
ControlFlow::CONTINUE
|
||||||
} else {
|
} else {
|
||||||
ControlFlow::Break(NonRecursive)
|
ControlFlow::Break(NonRecursive)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
|
||||||
| TerminatorKind::FalseEdge { .. }
|
| TerminatorKind::FalseEdge { .. }
|
||||||
| TerminatorKind::FalseUnwind { .. }
|
| TerminatorKind::FalseUnwind { .. }
|
||||||
| TerminatorKind::Goto { .. }
|
| TerminatorKind::Goto { .. }
|
||||||
| TerminatorKind::SwitchInt { .. } => ControlFlow::Continue,
|
| TerminatorKind::SwitchInt { .. } => ControlFlow::CONTINUE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlFlow::Continue
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool {
|
fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool {
|
||||||
|
|
|
@ -1273,7 +1273,7 @@ where
|
||||||
) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ {
|
) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ {
|
||||||
move |(), x| match f(x) {
|
move |(), x| match f(x) {
|
||||||
Some(x) => ControlFlow::Break(x),
|
Some(x) => ControlFlow::Break(x),
|
||||||
None => ControlFlow::Continue(()),
|
None => ControlFlow::CONTINUE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,7 +310,7 @@ pub trait DoubleEndedIterator: Iterator {
|
||||||
mut predicate: impl FnMut(&T) -> bool,
|
mut predicate: impl FnMut(&T) -> bool,
|
||||||
) -> impl FnMut((), T) -> ControlFlow<(), T> {
|
) -> impl FnMut((), T) -> ControlFlow<(), T> {
|
||||||
move |(), x| {
|
move |(), x| {
|
||||||
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
|
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2076,10 +2076,10 @@ pub trait Iterator {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
|
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
|
||||||
move |(), x| {
|
move |(), x| {
|
||||||
if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
|
if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.try_fold((), check(f)) == ControlFlow::Continue(())
|
self.try_fold((), check(f)) == ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests if any element of the iterator matches a predicate.
|
/// Tests if any element of the iterator matches a predicate.
|
||||||
|
@ -2129,11 +2129,11 @@ pub trait Iterator {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
|
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
|
||||||
move |(), x| {
|
move |(), x| {
|
||||||
if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
|
if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.try_fold((), check(f)) == ControlFlow::Break(())
|
self.try_fold((), check(f)) == ControlFlow::BREAK
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Searches for an element of an iterator that satisfies a predicate.
|
/// Searches for an element of an iterator that satisfies a predicate.
|
||||||
|
@ -2191,7 +2191,7 @@ pub trait Iterator {
|
||||||
mut predicate: impl FnMut(&T) -> bool,
|
mut predicate: impl FnMut(&T) -> bool,
|
||||||
) -> impl FnMut((), T) -> ControlFlow<(), T> {
|
) -> impl FnMut((), T) -> ControlFlow<(), T> {
|
||||||
move |(), x| {
|
move |(), x| {
|
||||||
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
|
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2226,7 +2226,7 @@ pub trait Iterator {
|
||||||
) -> impl FnMut((), T) -> ControlFlow<(), B> {
|
) -> impl FnMut((), T) -> ControlFlow<(), B> {
|
||||||
move |(), x| match f(x) {
|
move |(), x| match f(x) {
|
||||||
Some(x) => ControlFlow::Break(x),
|
Some(x) => ControlFlow::Break(x),
|
||||||
None => ControlFlow::Continue(()),
|
None => ControlFlow::CONTINUE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2268,7 +2268,7 @@ pub trait Iterator {
|
||||||
R: Try<Ok = bool>,
|
R: Try<Ok = bool>,
|
||||||
{
|
{
|
||||||
move |(), x| match f(&x).into_result() {
|
move |(), x| match f(&x).into_result() {
|
||||||
Ok(false) => ControlFlow::Continue(()),
|
Ok(false) => ControlFlow::CONTINUE,
|
||||||
Ok(true) => ControlFlow::Break(Ok(x)),
|
Ok(true) => ControlFlow::Break(Ok(x)),
|
||||||
Err(x) => ControlFlow::Break(Err(x)),
|
Err(x) => ControlFlow::Break(Err(x)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,3 +65,46 @@ impl<R: Try> ControlFlow<R::Ok, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<B> ControlFlow<(), B> {
|
||||||
|
/// It's frequently the case that there's no value needed with `Continue`,
|
||||||
|
/// so this provides a way to avoid typing `(())`, if you prefer it.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(control_flow_enum)]
|
||||||
|
/// use std::ops::ControlFlow;
|
||||||
|
///
|
||||||
|
/// let mut partial_sum = 0;
|
||||||
|
/// let last_used = (1..10).chain(20..25).try_for_each(|x| {
|
||||||
|
/// partial_sum += x;
|
||||||
|
/// if partial_sum > 100 { ControlFlow::Break(x) }
|
||||||
|
/// else { ControlFlow::CONTINUE }
|
||||||
|
/// });
|
||||||
|
/// assert_eq!(last_used.break_value(), Some(22));
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||||
|
pub const CONTINUE: Self = ControlFlow::Continue(());
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C> ControlFlow<C, ()> {
|
||||||
|
/// APIs like `try_for_each` don't need values with `Break`,
|
||||||
|
/// so this provides a way to avoid typing `(())`, if you prefer it.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(control_flow_enum)]
|
||||||
|
/// use std::ops::ControlFlow;
|
||||||
|
///
|
||||||
|
/// let mut partial_sum = 0;
|
||||||
|
/// (1..10).chain(20..25).try_for_each(|x| {
|
||||||
|
/// if partial_sum > 100 { ControlFlow::BREAK }
|
||||||
|
/// else { partial_sum += x; ControlFlow::CONTINUE }
|
||||||
|
/// });
|
||||||
|
/// assert_eq!(partial_sum, 108);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||||
|
pub const BREAK: Self = ControlFlow::Break(());
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue