Skip to content

Commit acd33e1

Browse files
authored
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.)
2 parents e735247 + 59e3733 commit acd33e1

File tree

8 files changed

+63
-21
lines changed

8 files changed

+63
-21
lines changed

compiler/rustc_data_structures/src/graph/iterate/mod.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,8 @@ where
8787
}
8888

8989
/// Allows searches to terminate early with a value.
90-
#[derive(Clone, Copy, Debug)]
91-
pub enum ControlFlow<T> {
92-
Break(T),
93-
Continue,
94-
}
90+
// FIXME (#75744): remove the alias once the generics are in a better order and `C=()`.
91+
pub type ControlFlow<T> = std::ops::ControlFlow<(), T>;
9592

9693
/// The status of a node in the depth-first search.
9794
///
@@ -260,12 +257,12 @@ where
260257
_node: G::Node,
261258
_prior_status: Option<NodeStatus>,
262259
) -> ControlFlow<Self::BreakVal> {
263-
ControlFlow::Continue
260+
ControlFlow::CONTINUE
264261
}
265262

266263
/// Called after all nodes reachable from this one have been examined.
267264
fn node_settled(&mut self, _node: G::Node) -> ControlFlow<Self::BreakVal> {
268-
ControlFlow::Continue
265+
ControlFlow::CONTINUE
269266
}
270267

271268
/// Behave as if no edges exist from `source` to `target`.
@@ -289,8 +286,8 @@ where
289286
prior_status: Option<NodeStatus>,
290287
) -> ControlFlow<Self::BreakVal> {
291288
match prior_status {
292-
Some(NodeStatus::Visited) => ControlFlow::Break(()),
293-
_ => ControlFlow::Continue,
289+
Some(NodeStatus::Visited) => ControlFlow::BREAK,
290+
_ => ControlFlow::CONTINUE,
294291
}
295292
}
296293
}

compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
1010
#![allow(incomplete_features)]
11+
#![feature(control_flow_enum)]
1112
#![feature(in_band_lifetimes)]
1213
#![feature(unboxed_closures)]
1314
#![feature(generators)]

compiler/rustc_mir_build/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(box_syntax)]
77
#![feature(const_fn)]
88
#![feature(const_panic)]
9+
#![feature(control_flow_enum)]
910
#![feature(crate_visibility_modifier)]
1011
#![feature(bool_to_option)]
1112
#![feature(or_patterns)]

compiler/rustc_mir_build/src/lints.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
117117
// A diverging InlineAsm is treated as non-recursing
118118
TerminatorKind::InlineAsm { destination, .. } => {
119119
if destination.is_some() {
120-
ControlFlow::Continue
120+
ControlFlow::CONTINUE
121121
} else {
122122
ControlFlow::Break(NonRecursive)
123123
}
@@ -131,7 +131,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
131131
| TerminatorKind::FalseEdge { .. }
132132
| TerminatorKind::FalseUnwind { .. }
133133
| TerminatorKind::Goto { .. }
134-
| TerminatorKind::SwitchInt { .. } => ControlFlow::Continue,
134+
| TerminatorKind::SwitchInt { .. } => ControlFlow::CONTINUE,
135135
}
136136
}
137137

@@ -144,7 +144,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
144144
}
145145
}
146146

147-
ControlFlow::Continue
147+
ControlFlow::CONTINUE
148148
}
149149

150150
fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool {

library/core/src/iter/adapters/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ where
12731273
) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ {
12741274
move |(), x| match f(x) {
12751275
Some(x) => ControlFlow::Break(x),
1276-
None => ControlFlow::Continue(()),
1276+
None => ControlFlow::CONTINUE,
12771277
}
12781278
}
12791279

library/core/src/iter/traits/double_ended.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ pub trait DoubleEndedIterator: Iterator {
310310
mut predicate: impl FnMut(&T) -> bool,
311311
) -> impl FnMut((), T) -> ControlFlow<(), T> {
312312
move |(), x| {
313-
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
313+
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
314314
}
315315
}
316316

library/core/src/iter/traits/iterator.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -2076,10 +2076,10 @@ pub trait Iterator {
20762076
#[inline]
20772077
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
20782078
move |(), x| {
2079-
if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
2079+
if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
20802080
}
20812081
}
2082-
self.try_fold((), check(f)) == ControlFlow::Continue(())
2082+
self.try_fold((), check(f)) == ControlFlow::CONTINUE
20832083
}
20842084

20852085
/// Tests if any element of the iterator matches a predicate.
@@ -2129,11 +2129,11 @@ pub trait Iterator {
21292129
#[inline]
21302130
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
21312131
move |(), x| {
2132-
if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
2132+
if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
21332133
}
21342134
}
21352135

2136-
self.try_fold((), check(f)) == ControlFlow::Break(())
2136+
self.try_fold((), check(f)) == ControlFlow::BREAK
21372137
}
21382138

21392139
/// Searches for an element of an iterator that satisfies a predicate.
@@ -2191,7 +2191,7 @@ pub trait Iterator {
21912191
mut predicate: impl FnMut(&T) -> bool,
21922192
) -> impl FnMut((), T) -> ControlFlow<(), T> {
21932193
move |(), x| {
2194-
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
2194+
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
21952195
}
21962196
}
21972197

@@ -2226,7 +2226,7 @@ pub trait Iterator {
22262226
) -> impl FnMut((), T) -> ControlFlow<(), B> {
22272227
move |(), x| match f(x) {
22282228
Some(x) => ControlFlow::Break(x),
2229-
None => ControlFlow::Continue(()),
2229+
None => ControlFlow::CONTINUE,
22302230
}
22312231
}
22322232

@@ -2268,7 +2268,7 @@ pub trait Iterator {
22682268
R: Try<Ok = bool>,
22692269
{
22702270
move |(), x| match f(&x).into_result() {
2271-
Ok(false) => ControlFlow::Continue(()),
2271+
Ok(false) => ControlFlow::CONTINUE,
22722272
Ok(true) => ControlFlow::Break(Ok(x)),
22732273
Err(x) => ControlFlow::Break(Err(x)),
22742274
}

library/core/src/ops/control_flow.rs

+43
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,46 @@ impl<R: Try> ControlFlow<R::Ok, R> {
6565
}
6666
}
6767
}
68+
69+
impl<B> ControlFlow<(), B> {
70+
/// It's frequently the case that there's no value needed with `Continue`,
71+
/// so this provides a way to avoid typing `(())`, if you prefer it.
72+
///
73+
/// # Examples
74+
///
75+
/// ```
76+
/// #![feature(control_flow_enum)]
77+
/// use std::ops::ControlFlow;
78+
///
79+
/// let mut partial_sum = 0;
80+
/// let last_used = (1..10).chain(20..25).try_for_each(|x| {
81+
/// partial_sum += x;
82+
/// if partial_sum > 100 { ControlFlow::Break(x) }
83+
/// else { ControlFlow::CONTINUE }
84+
/// });
85+
/// assert_eq!(last_used.break_value(), Some(22));
86+
/// ```
87+
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
88+
pub const CONTINUE: Self = ControlFlow::Continue(());
89+
}
90+
91+
impl<C> ControlFlow<C, ()> {
92+
/// APIs like `try_for_each` don't need values with `Break`,
93+
/// so this provides a way to avoid typing `(())`, if you prefer it.
94+
///
95+
/// # Examples
96+
///
97+
/// ```
98+
/// #![feature(control_flow_enum)]
99+
/// use std::ops::ControlFlow;
100+
///
101+
/// let mut partial_sum = 0;
102+
/// (1..10).chain(20..25).try_for_each(|x| {
103+
/// if partial_sum > 100 { ControlFlow::BREAK }
104+
/// else { partial_sum += x; ControlFlow::CONTINUE }
105+
/// });
106+
/// assert_eq!(partial_sum, 108);
107+
/// ```
108+
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
109+
pub const BREAK: Self = ControlFlow::Break(());
110+
}

0 commit comments

Comments
 (0)