Skip to content

Commit 7a7890a

Browse files
committed
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
1 parent 0bfd8e1 commit 7a7890a

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

src/expressions/operator-expr.md

Lines changed: 39 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 [`core::ops::Try`] trait to evaluate the subexpression to either a value, or to return a value.
202202

203203
> [!EXAMPLE]
204204
> The following examples illustrate some basic uses of the try propagation expression.
@@ -269,32 +269,48 @@ The try propagation operator (`?`) unwraps valid values or returns erroneous val
269269
> # }
270270
> ```
271271
272+
> [!NOTE]
273+
> The [`core::ops::Try`] trait is currently unstable, and thus cannot be implemented for user types without using the nightly release channel.
274+
>
275+
> The try propagation expression is currently equivalent to:
276+
>
277+
> ```rust
278+
> # #![ feature(try_trait_v2) ]
279+
> # fn example() -> Result<(), ()> {
280+
> # let expr = Ok(());
281+
> match core::ops::Try::branch(expr) {
282+
> core::ops::ControlFlow::Continue(val) => val,
283+
> core::ops::ControlFlow::Break(residual) =>
284+
> return core::ops::FromResidual::from_residual(residual),
285+
> }
286+
> # Ok(())
287+
> # }
288+
> ```
289+
272290
> [!NOTE]
273291
> The try propagation operator is sometimes called *the question mark operator*, *the `?` operator*, or *the try operator*.
274292
275293
r[expr.try.restricted-types]
276-
It is a unary postfix operator that can only be applied to the types `Result<T, E>` and `Option<T>`.
277-
278-
r[expr.try.behavior-std-result]
279-
When applied to values of the `Result<T, E>` type, it propagates errors.
280-
281-
r[expr.try.effects-err]
282-
If the value is `Err(e)`, then it will return `Err(From::from(e))` from the enclosing function or closure.
283-
284-
r[expr.try.result-ok]
285-
If applied to `Ok(x)`, then it will unwrap the value to evaluate to `x`.
286-
287-
r[expr.try.behavior-std-option]
288-
When applied to values of the `Option<T>` type, it propagates `None`s.
289-
290-
r[expr.try.effects-none]
291-
If the value is `None`, then it will return `None`.
292-
293-
r[expr.try.result-some]
294-
If applied to `Some(x)`, then it will unwrap the value to evaluate to `x`.
295-
296-
r[expr.try.trait]
297-
`?` cannot be overloaded.
294+
The try propagation operator can be applied to expressions with the type of:
295+
296+
- [`Result<T, E>`]
297+
- `Result::Ok(val)` evaluates to the value of `val`
298+
- `Result::Err(e)` returns the value of `Result::Err(From::from(e))`
299+
- [`Option<T>`]
300+
- `Option::Some(val)` evaluates to the value of `val`
301+
- `Option::None` returns the value `Option::None`
302+
- [`ControlFlow<B, C>`][core::ops::ControlFlow]
303+
- `ControlFlow::Continue(c)` evaluates to value of `c`
304+
- `ControlFlow::Break(b)` returns the value `ControlFlow::Break(b)`
305+
- [`Poll<Result<T, E>>`][core::task::Poll]
306+
- `Poll::Ready(Ok(val))` evaluates to the value `Poll::Ready(val)`
307+
- `Poll::Ready(Err(e))` returns the value `Poll::Ready(Err(From::from(e)))`
308+
- `Poll::Pending` evaluates to the value `Poll::Pending`
309+
- [`Poll<Option<Result<T, E>>>`][`core::task::Poll`]
310+
- `Poll::Ready(Some(Ok(val)))` evaluates to the value `Poll::Ready(Some(val))`
311+
- `Poll::Ready(Some(Err(e)))` returns the value `Poll::Ready(Some(Err(From::from(e))))`
312+
- `Poll::Ready(None)` evaluates to the value `Poll::Ready(None)`
313+
- `Poll::Pending` evaluates to the value `Poll::Pending`
298314
299315
r[expr.negate]
300316
## Negation operators

0 commit comments

Comments
 (0)