Skip to content

Commit a8ee3a1

Browse files
committed
Actually implement the feature in the compiler
Including all the bootstrapping tweaks in the library.
1 parent 1f91ef6 commit a8ee3a1

File tree

6 files changed

+98
-5
lines changed

6 files changed

+98
-5
lines changed

core/src/iter/adapters/peekable.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
2-
use crate::ops::TryWhereOutputEquals;
2+
use crate::ops::{ControlFlow, TryWhereOutputEquals};
33

44
/// An iterator with a `peek()` that returns an optional reference to the next
55
/// element.
@@ -130,12 +130,35 @@ where
130130
}
131131

132132
#[inline]
133+
#[cfg(not(bootstrap))]
133134
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
134135
where
135136
Self: Sized,
136137
F: FnMut(B, Self::Item) -> R,
137138
R: TryWhereOutputEquals<B>,
138139
{
140+
match self.peeked.take() {
141+
Some(None) => try { init },
142+
Some(Some(v)) => match self.iter.try_rfold(init, &mut f).branch() {
143+
ControlFlow::Continue(acc) => f(acc, v),
144+
ControlFlow::Break(r) => {
145+
self.peeked = Some(Some(v));
146+
R::from_residual(r)
147+
}
148+
},
149+
None => self.iter.try_rfold(init, f),
150+
}
151+
}
152+
153+
#[inline]
154+
#[cfg(bootstrap)]
155+
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
156+
where
157+
Self: Sized,
158+
F: FnMut(B, Self::Item) -> R,
159+
R: TryWhereOutputEquals<B>,
160+
{
161+
let _use_the_import: ControlFlow<()>;
139162
match self.peeked.take() {
140163
Some(None) => try { init },
141164
Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {

core/src/iter/traits/iterator.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,6 +2412,36 @@ pub trait Iterator {
24122412
/// ```
24132413
#[inline]
24142414
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
2415+
#[cfg(not(bootstrap))]
2416+
fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E>
2417+
where
2418+
Self: Sized,
2419+
F: FnMut(&Self::Item) -> R,
2420+
R: TryWhereOutputEquals<bool>,
2421+
// FIXME: This is a weird bound; the API should change
2422+
R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
2423+
{
2424+
#[inline]
2425+
fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
2426+
where
2427+
F: FnMut(&T) -> R,
2428+
R: TryWhereOutputEquals<bool>,
2429+
R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
2430+
{
2431+
move |(), x| match f(&x).branch() {
2432+
ControlFlow::Continue(false) => ControlFlow::CONTINUE,
2433+
ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)),
2434+
ControlFlow::Break(Err(x)) => ControlFlow::Break(Err(x)),
2435+
}
2436+
}
2437+
2438+
self.try_fold((), check(f)).break_value().transpose()
2439+
}
2440+
2441+
/// We're bootstrapping.
2442+
#[inline]
2443+
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
2444+
#[cfg(bootstrap)]
24152445
fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error>
24162446
where
24172447
Self: Sized,

core/src/ops/control_flow.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ use crate::{convert, ops};
5252
#[derive(Debug, Clone, Copy, PartialEq)]
5353
pub enum ControlFlow<B, C = ()> {
5454
/// Move on to the next phase of the operation as normal.
55+
#[cfg_attr(not(bootstrap), lang = "Continue")]
5556
Continue(C),
5657
/// Exit the operation without running subsequent phases.
58+
#[cfg_attr(not(bootstrap), lang = "Break")]
5759
Break(B),
5860
// Yes, the order of the variants doesn't match the type parameters.
5961
// They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
@@ -181,6 +183,7 @@ impl<B, C> ControlFlow<B, C> {
181183
}
182184
}
183185

186+
#[cfg(bootstrap)]
184187
impl<R: ops::TryV1> ControlFlow<R, R::Ok> {
185188
/// Create a `ControlFlow` from any type implementing `Try`.
186189
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
@@ -203,6 +206,29 @@ impl<R: ops::TryV1> ControlFlow<R, R::Ok> {
203206
}
204207
}
205208

209+
#[cfg(not(bootstrap))]
210+
impl<R: ops::TryV2> ControlFlow<R, R::Output> {
211+
/// Create a `ControlFlow` from any type implementing `Try`.
212+
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
213+
#[inline]
214+
pub fn from_try(r: R) -> Self {
215+
match R::branch(r) {
216+
ControlFlow::Continue(v) => ControlFlow::Continue(v),
217+
ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)),
218+
}
219+
}
220+
221+
/// Convert a `ControlFlow` into any type implementing `Try`;
222+
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
223+
#[inline]
224+
pub fn into_try(self) -> R {
225+
match self {
226+
ControlFlow::Continue(v) => R::from_output(v),
227+
ControlFlow::Break(v) => v,
228+
}
229+
}
230+
}
231+
206232
impl<B> ControlFlow<B, ()> {
207233
/// It's frequently the case that there's no value needed with `Continue`,
208234
/// so this provides a way to avoid typing `(())`, if you prefer it.

core/src/ops/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
183183
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
184184

185185
#[unstable(feature = "try_trait", issue = "42327")]
186+
#[cfg(bootstrap)]
186187
pub use self::r#try::Try;
187188

188189
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
@@ -191,6 +192,10 @@ pub use self::r#try::Try as TryV1;
191192
#[unstable(feature = "try_trait_v2", issue = "84277")]
192193
pub use self::try_trait::FromResidual;
193194

195+
#[unstable(feature = "try_trait_v2", issue = "84277")]
196+
#[cfg(not(bootstrap))]
197+
pub use self::try_trait::Try;
198+
194199
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
195200
pub use self::try_trait::Try as TryV2;
196201

@@ -220,4 +225,9 @@ pub use self::control_flow::ControlFlow;
220225
/// foo::<Option<i32>, i32>();
221226
/// ```
222227
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
228+
#[cfg(not(bootstrap))]
229+
pub trait TryWhereOutputEquals<T> = TryV2<Output = T>;
230+
231+
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
232+
#[cfg(bootstrap)]
223233
pub trait TryWhereOutputEquals<T> = TryV1<Ok = T>;

core/src/ops/try.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
)
2626
)]
2727
#[doc(alias = "?")]
28-
#[lang = "try"]
28+
#[cfg_attr(bootstrap, lang = "try")]
2929
pub trait Try {
3030
/// The type of this value when viewed as successful.
3131
#[unstable(feature = "try_trait", issue = "42327")]
@@ -43,19 +43,19 @@ pub trait Try {
4343
/// in the return type of the enclosing scope (which must itself implement
4444
/// `Try`). Specifically, the value `X::from_error(From::from(e))`
4545
/// is returned, where `X` is the return type of the enclosing function.
46-
#[lang = "into_result"]
46+
#[cfg_attr(bootstrap, lang = "into_result")]
4747
#[unstable(feature = "try_trait", issue = "42327")]
4848
fn into_result(self) -> Result<Self::Ok, Self::Error>;
4949

5050
/// Wrap an error value to construct the composite result. For example,
5151
/// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
52-
#[lang = "from_error"]
52+
#[cfg_attr(bootstrap, lang = "from_error")]
5353
#[unstable(feature = "try_trait", issue = "42327")]
5454
fn from_error(v: Self::Error) -> Self;
5555

5656
/// Wrap an OK value to construct the composite result. For example,
5757
/// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
58-
#[lang = "from_ok"]
58+
#[cfg_attr(bootstrap, lang = "from_ok")]
5959
#[unstable(feature = "try_trait", issue = "42327")]
6060
fn from_ok(v: Self::Ok) -> Self;
6161
}

core/src/ops/try_trait.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ use crate::ops::ControlFlow;
119119
/// }
120120
/// ```
121121
#[unstable(feature = "try_trait_v2", issue = "84277")]
122+
#[cfg_attr(not(bootstrap), lang = "Try")]
122123
pub trait Try: FromResidual {
123124
/// The type of the value produced by `?` when *not* short-circuiting.
124125
#[unstable(feature = "try_trait_v2", issue = "84277")]
@@ -178,6 +179,7 @@ pub trait Try: FromResidual {
178179
/// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
179180
/// assert_eq!(r, Some(4));
180181
/// ```
182+
#[cfg_attr(not(bootstrap), lang = "from_output")]
181183
#[unstable(feature = "try_trait_v2", issue = "84277")]
182184
fn from_output(output: Self::Output) -> Self;
183185

@@ -206,6 +208,7 @@ pub trait Try: FromResidual {
206208
/// ControlFlow::Break(ControlFlow::Break(3)),
207209
/// );
208210
/// ```
211+
#[cfg_attr(not(bootstrap), lang = "branch")]
209212
#[unstable(feature = "try_trait_v2", issue = "84277")]
210213
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
211214
}
@@ -238,6 +241,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
238241
/// ControlFlow::Break(5),
239242
/// );
240243
/// ```
244+
#[cfg_attr(not(bootstrap), lang = "from_residual")]
241245
#[unstable(feature = "try_trait_v2", issue = "84277")]
242246
fn from_residual(residual: R) -> Self;
243247
}

0 commit comments

Comments
 (0)