1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
use crate::ops::ControlFlow;
/// `?` 运算符和 `try {}` 块。
///
/// `try_*` 方法通常涉及实现此 trait 的类型。例如,传递给 [`Iterator::try_fold`] 和 [`Iterator::try_for_each`] 的闭包必须返回这样的类型。
///
/// `Try` 类型通常是那些包含两个或更多类别值的类型,其中一些子集通常通过早期返回处理,因此值得提供一个简洁 (但仍然可见) 的语法来简化它。
///
///
/// 这在 [`Result`] 和 [`Option`] 的错误处理中最常见。
/// 这个 trait 的典型实现是在 [`ControlFlow`] 上。
///
/// # 在泛型代码中使用 `Try`
///
/// `Iterator::try_fold` 在 Rust 1.27 中稳定到调用,但是这个 trait 更新很多。为了说明各种关联类型和方法,让我们实现我们自己的版本。
///
/// 提醒一下,一个可靠的折叠版本看起来像这样:
///
/// ```
/// fn simple_fold<A, T>(
/// iter: impl Iterator<Item = T>,
/// mut accum: A,
/// mut f: impl FnMut(A, T) -> A,
/// ) -> A {
/// for x in iter {
/// accum = f(accum, x);
/// }
/// accum
/// }
/// ```
///
/// 因此,不是 `f` 只返回一个 `A`,我们需要它返回一些在不要短路路径中产生一个 `A` 的其他类型。
/// 方便的是,这也是我们需要从函数返回的类型。
///
/// 让我们为该类型添加一个新的泛型参数 `R`,并将其绑定到我们想要的输出类型:
///
/// ```
/// # #![feature(try_trait_v2)]
/// # use std::ops::Try;
/// fn simple_try_fold_1<A, T, R: Try<Output = A>>(
/// iter: impl Iterator<Item = T>,
/// mut accum: A,
/// mut f: impl FnMut(A, T) -> R,
/// ) -> R {
/// todo!()
/// }
/// ```
///
/// 如果我们遍历整个迭代器,我们需要使用 [`Try::from_output`] 将累加器包装成返回类型:
///
/// ```
/// # #![feature(try_trait_v2)]
/// # use std::ops::{ControlFlow, Try};
/// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
/// iter: impl Iterator<Item = T>,
/// mut accum: A,
/// mut f: impl FnMut(A, T) -> R,
/// ) -> R {
/// for x in iter {
/// let cf = f(accum, x).branch();
/// match cf {
/// ControlFlow::Continue(a) => accum = a,
/// ControlFlow::Break(_) => todo!(),
/// }
/// }
/// R::from_output(accum)
/// }
/// ```
///
/// 我们还需要 [`FromResidual::from_residual`] 将 residual 恢复为原始类型。但因为它是 `Try` 的一个 super trait,所以我们不必在界限内提及它。
/// 所有实现 `Try` 的类型都可以从它们对应的 residual 中重新创建,所以我们将调用它:
///
/// ```
/// # #![feature(try_trait_v2)]
/// # use std::ops::{ControlFlow, Try};
/// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
/// iter: impl Iterator<Item = T>,
/// mut accum: A,
/// mut f: impl FnMut(A, T) -> R,
/// ) -> R {
/// for x in iter {
/// let cf = f(accum, x).branch();
/// match cf {
/// ControlFlow::Continue(a) => accum = a,
/// ControlFlow::Break(r) => return R::from_residual(r),
/// }
/// }
/// R::from_output(accum)
/// }
/// ```
///
/// 但是这个 "调用`branch`,然后在它上面进行 `match`,如果它是 `Break`,则 `return`" 正是在 `?` 操作符内部发生的事情。因此,我们可以使用 `?` 代替手动完成所有这些操作:
///
/// ```
/// # #![feature(try_trait_v2)]
/// # use std::ops::Try;
/// fn simple_try_fold<A, T, R: Try<Output = A>>(
/// iter: impl Iterator<Item = T>,
/// mut accum: A,
/// mut f: impl FnMut(A, T) -> R,
/// ) -> R {
/// for x in iter {
/// accum = f(accum, x)?;
/// }
/// R::from_output(accum)
/// }
/// ```
///
///
///
///
///
///
///
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[rustc_on_unimplemented(
on(
all(from_desugaring = "TryBlock"),
message = "a `try` block must return `Result` or `Option` \
(or another type that implements `{Try}`)",
label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`",
),
on(
all(from_desugaring = "QuestionMark"),
message = "the `?` operator can only be applied to values that implement `{Try}`",
label = "the `?` operator cannot be applied to type `{Self}`"
)
)]
#[doc(alias = "?")]
#[lang = "Try"]
pub trait Try: FromResidual {
/// 当不短路时,`?` 产生的值的类型。
#[unstable(feature = "try_trait_v2", issue = "84277")]
type Output;
/// 短路时作为 `?` 的一部分传递给 [`FromResidual::from_residual`] 的值的类型。
///
/// 这表示 `Self` 类型的可能值,而不是 `Output` 类型所表示的值。
///
/// # 实现者注意
///
/// 这种类型的选择对于相互转化至关重要。
/// 与 `Output` 类型不同,它通常是原始泛型类型,这种类型通常是某种类型的 newtype 到 "color" 类型,以便与其他类型的 residual 区别开来。
///
/// 这就是为什么 `Result<T, E>::Residual` 不是 `E`,而是 `Result<Infallible, E>`。
/// 例如,这样它就不同于 `ControlFlow<E>::Residual`,因此 `ControlFlow` 上的 `?` 不能用于返回 `Result` 的方法中。
///
/// 如果您正在创建实现 `Try<Output = T>` 的泛型 `Foo<T>`,那么通常您可以使用 `Foo<std::convert::Infallible>` 作为它的 `Residual` 类型:该类型将在正确位置有一个 "hole",并将保留 residual 的 "foo-ness",因此其他类型需要选择加入到相互转换中。
///
///
///
///
///
///
///
///
#[unstable(feature = "try_trait_v2", issue = "84277")]
type Residual;
/// 从它的 `Output` 类型构造类型。
///
/// 这应该与 `branch` 方法一致地实现,以便应用 `?` 运算符将返回原始值: `Try::from_output(x).branch() --> ControlFlow::Continue(x)`。
///
///
/// # Examples
///
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::Try;
///
/// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
/// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
/// assert_eq!(
/// <std::ops::ControlFlow<String, _> as Try>::from_output(5),
/// std::ops::ControlFlow::Continue(5),
/// );
///
/// # fn make_question_mark_work() -> Option<()> {
/// assert_eq!(Option::from_output(4)?, 4);
/// # None }
/// # make_question_mark_work();
///
/// // 例如,这用于 `try_fold` 中的累加器:
/// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
/// assert_eq!(r, Some(4));
/// ```
///
#[lang = "from_output"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
fn from_output(output: Self::Output) -> Self;
/// 在 `?` 来决定操作符是应该生成一个值 (因为它返回了 [`ControlFlow::Continue`]),还是将一个值传播回调用者 (因为它返回了 [`ControlFlow::Break`])。
///
///
/// # Examples
///
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::{ControlFlow, Try};
///
/// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
///
/// assert_eq!(Some(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(None::<String>.branch(), ControlFlow::Break(None));
///
/// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3));
/// assert_eq!(
/// ControlFlow::<_, String>::Break(3).branch(),
/// ControlFlow::Break(ControlFlow::Break(3)),
/// );
/// ```
///
///
#[lang = "branch"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}
/// 用于指定哪些残差可以转换为哪些 [`crate::ops::Try`] 类型。
///
/// 每个 `Try` 类型都需要从它自己关联的 `Residual` 类型重新创建,但也可以有额外的 `FromResidual` 实现来支持与其他 `Try` 类型的相互转换。
///
///
#[rustc_on_unimplemented(
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::result::Result<T, E>",
R = "std::option::Option<std::convert::Infallible>"
),
message = "the `?` operator can only be used on `Result`s, not `Option`s, \
in {ItemContext} that returns `Result`",
label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
parent_label = "this function returns a `Result`"
),
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::result::Result<T, E>",
),
// 在 `?` 中 `From` 的 trait 选择代码中有一条特殊的错误消息,因此对于结果中的错误没有显示,因此它可以比 `ControlFlow` 更强烈地表达。
//
//
message = "the `?` operator can only be used on `Result`s \
in {ItemContext} that returns `Result`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
parent_label = "this function returns a `Result`"
),
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::option::Option<T>",
R = "std::result::Result<T, E>",
),
message = "the `?` operator can only be used on `Option`s, not `Result`s, \
in {ItemContext} that returns `Option`",
label = "use `.ok()?` if you want to discard the `{R}` error information",
parent_label = "this function returns an `Option`"
),
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::option::Option<T>",
),
// `Option`-in-`Option` 总是有效,因为只有一种可能的残差,所以这也可以用强烈的措辞表达。
//
message = "the `?` operator can only be used on `Option`s \
in {ItemContext} that returns `Option`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
parent_label = "this function returns an `Option`"
),
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::ops::ControlFlow<B, C>",
R = "std::ops::ControlFlow<B, C>",
),
message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
parent_label = "this function returns a `ControlFlow`",
note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
),
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::ops::ControlFlow<B, C>",
// `R` 不是 `ControlFlow`,因为以前匹配过这种情况
),
message = "the `?` operator can only be used on `ControlFlow`s \
in {ItemContext} that returns `ControlFlow`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
parent_label = "this function returns a `ControlFlow`",
),
on(
all(from_desugaring = "QuestionMark"),
message = "the `?` operator can only be used in {ItemContext} \
that returns `Result` or `Option` \
(or another type that implements `{FromResidual}`)",
label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
parent_label = "this function should return `Result` or `Option` to accept `?`"
),
)]
#[rustc_diagnostic_item = "FromResidual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
pub trait FromResidual<R = <Self as Try>::Residual> {
/// 从兼容的 `Residual` 类型构造类型。
///
/// 这应该与 `branch` 方法一致地实现,以便应用 `?` 运算符将返回等效的残差: `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`。
///
/// (当涉及相互转换时,它不能是*相同的*残差。)
///
/// # Examples
///
/// ```
/// #![feature(try_trait_v2)]
/// use std::ops::{ControlFlow, FromResidual};
///
/// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
/// assert_eq!(Option::<String>::from_residual(None), None);
/// assert_eq!(
/// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)),
/// ControlFlow::Break(5),
/// );
/// ```
///
#[lang = "from_residual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
fn from_residual(residual: R) -> Self;
}
#[unstable(
feature = "yeet_desugar_details",
issue = "none",
reason = "just here to simplify the desugaring; will never be stabilized"
)]
#[inline]
#[track_caller] // 因为 `Result::from_residual` 拥有它
#[lang = "from_yeet"]
pub fn from_yeet<T, Y>(yeeted: Y) -> T
where
T: FromResidual<Yeet<Y>>,
{
FromResidual::from_residual(Yeet(yeeted))
}
/// 允许检索实现 [`Try`] 的规范类型,该类型具有此类型作为它的残差,并允许它保留 `O` 作为它的输出。
///
/// 如果您将 `Try` trait 视为将类型拆分为其 [`Try::Output`] 和 [`Try::Residual`] 组件,则可以将它们重新组合在一起。
///
/// 例如,`Result<T, E>: Try<Output = T, Residual = Result<Infallible, E>>`,在另一个方向上,`<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`。
///
///
///
///
///
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
pub trait Residual<O> {
/// 此元函数的 "return" 类型。
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
type TryType: Try<Output = O, Residual = Self>;
}
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::TryType;
/// 用于通过 `Try` implementation 实现非尝试方法的适配器。
///
/// 概念上与 `Result<T, !>` 相同,但是作为一个明显的 newtype,并且没有 `From` bounds,所以在 trait 求解和控制性检查等方面需要较少的工作。
///
///
/// 目前不打算公开,所以只是 `pub(crate)`。
///
#[repr(transparent)]
pub(crate) struct NeverShortCircuit<T>(pub T);
impl<T> NeverShortCircuit<T> {
/// 包装一元函数以生成将输出包装到 `NeverShortCircuit` 中的函数。
///
/// 这对于根据 `try_` 实现绝对可靠的函数很有用,而不会意外地在闭包中捕获额外的泛型参数。
///
#[inline]
pub fn wrap_mut_1<A>(mut f: impl FnMut(A) -> T) -> impl FnMut(A) -> NeverShortCircuit<T> {
move |a| NeverShortCircuit(f(a))
}
#[inline]
pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
move |a, b| NeverShortCircuit(f(a, b))
}
}
pub(crate) enum NeverShortCircuitResidual {}
impl<T> Try for NeverShortCircuit<T> {
type Output = T;
type Residual = NeverShortCircuitResidual;
#[inline]
fn branch(self) -> ControlFlow<NeverShortCircuitResidual, T> {
ControlFlow::Continue(self.0)
}
#[inline]
fn from_output(x: T) -> Self {
NeverShortCircuit(x)
}
}
impl<T> FromResidual for NeverShortCircuit<T> {
#[inline]
fn from_residual(never: NeverShortCircuitResidual) -> Self {
match never {}
}
}
impl<T> Residual<T> for NeverShortCircuitResidual {
type TryType = NeverShortCircuit<T>;
}
/// 在您的类型上实现 `FromResidual<Yeet<T>>` 以在函数返回您的类型时启用 `do yeet expr` 语法。
///
#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
#[derive(Debug)]
pub struct Yeet<T>(pub T);