Skip to content

Commit e06cb25

Browse files
ehusstraviscross
authored andcommitted
Rewrite try to be written in terms of the Try trait
This rewrites the section to say that it uses the `Try` trait. I felt it was a bit too awkward to avoid it (since it is unstable). This keeps an explicit list of the types that the `Try` trait is implemented for, and adds the missing types (like `ControlFlow`). The intent is that when `Try` is stabilized that the desuggaring note moves to a normative rule, the `expr.try.restricted-types` rule is removed (and instead direct the user to the standard library documentation). I'm still holding out hope that they change the terminology, since I think the current choice is going to be confusing. This has a hack to allow `feature(try_trait_v2)` by abusing the style checker by adding some spaces. I really wanted to keep this example tested to ensure that it is kept up-to-date. However, I may regret this in the future. Fixes #1927 Edited-by: TC
1 parent 8334b19 commit e06cb25

File tree

1 file changed

+40
-23
lines changed

1 file changed

+40
-23
lines changed

src/expressions/operator-expr.md

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ TryPropagationExpression -> Expression `?`
198198
```
199199

200200
r[expr.try.intro]
201-
The try propagation operator (`?`) unwraps valid values or returns erroneous values, propagating them to the calling function.
201+
The try propagation expression uses the value of the inner expression and the [`Try`] trait to decide whether to produce a value, and if so, what value to produce, or whether to return a value to the caller, and if so, what value to return.
202202

203203
> [!EXAMPLE]
204204
> ```rust
@@ -267,32 +267,48 @@ The try propagation operator (`?`) unwraps valid values or returns erroneous val
267267
> # }
268268
> ```
269269
270+
> [!NOTE]
271+
> The [`Try`] trait is currently unstable, and thus cannot be implemented for user types.
272+
>
273+
> The try propagation expression is currently roughly equivalent to:
274+
>
275+
> ```rust
276+
> # #![ feature(try_trait_v2) ]
277+
> # fn example() -> Result<(), ()> {
278+
> # let expr = Ok(());
279+
> match core::ops::Try::branch(expr) {
280+
> core::ops::ControlFlow::Continue(val) => val,
281+
> core::ops::ControlFlow::Break(residual) =>
282+
> return core::ops::FromResidual::from_residual(residual),
283+
> }
284+
> # Ok(())
285+
> # }
286+
> ```
287+
270288
> [!NOTE]
271289
> The try propagation operator is sometimes called *the question mark operator*, *the `?` operator*, or *the try operator*.
272290
273291
r[expr.try.restricted-types]
274-
It is a unary postfix operator that can only be applied to the types `Result<T, E>` and `Option<T>`.
275-
276-
r[expr.try.behavior-std-result]
277-
When applied to values of the `Result<T, E>` type, it propagates errors.
278-
279-
r[expr.try.effects-err]
280-
If the value is `Err(e)`, then it will return `Err(From::from(e))` from the enclosing function or closure.
281-
282-
r[expr.try.result-ok]
283-
If applied to `Ok(x)`, then it will unwrap the value to evaluate to `x`.
284-
285-
r[expr.try.behavior-std-option]
286-
When applied to values of the `Option<T>` type, it propagates `None`s.
287-
288-
r[expr.try.effects-none]
289-
If the value is `None`, then it will return `None`.
290-
291-
r[expr.try.result-some]
292-
If applied to `Some(x)`, then it will unwrap the value to evaluate to `x`.
293-
294-
r[expr.try.trait]
295-
`?` cannot be overloaded.
292+
The try propagation operator can be applied to expressions with the type of:
293+
294+
- [`Result<T, E>`]
295+
- `Result::Ok(val)` evaluates to `val`.
296+
- `Result::Err(e)` returns `Result::Err(From::from(e))`.
297+
- [`Option<T>`]
298+
- `Option::Some(val)` evaluates to `val`.
299+
- `Option::None` returns `Option::None`.
300+
- [`ControlFlow<B, C>`][core::ops::ControlFlow]
301+
- `ControlFlow::Continue(c)` evaluates to `c`.
302+
- `ControlFlow::Break(b)` returns `ControlFlow::Break(b)`.
303+
- [`Poll<Result<T, E>>`][core::task::Poll]
304+
- `Poll::Ready(Ok(val))` evaluates to `Poll::Ready(val)`.
305+
- `Poll::Ready(Err(e))` returns `Poll::Ready(Err(From::from(e)))`.
306+
- `Poll::Pending` evaluates to `Poll::Pending`.
307+
- [`Poll<Option<Result<T, E>>>`][`core::task::Poll`]
308+
- `Poll::Ready(Some(Ok(val)))` evaluates to `Poll::Ready(Some(val))`.
309+
- `Poll::Ready(Some(Err(e)))` returns `Poll::Ready(Some(Err(From::from(e))))`.
310+
- `Poll::Ready(None)` evaluates to `Poll::Ready(None)`.
311+
- `Poll::Pending` evaluates to `Poll::Pending`.
296312
297313
r[expr.negate]
298314
## Negation operators
@@ -926,6 +942,7 @@ Like assignment expressions, compound assignment expressions always produce [the
926942
> Try not to write code that depends on the evaluation order of operands in compound assignment expressions.
927943
> See [this test] for an example of using this dependency.
928944
945+
[`Try`]: core::ops::Try
929946
[copies or moves]: ../expressions.md#moved-and-copied-types
930947
[dropping]: ../destructors.md
931948
[explicit discriminants]: ../items/enumerations.md#explicit-discriminants

0 commit comments

Comments
 (0)