Wait, so what do you want to behaviour to be when using ?
?
Try blocks act as a closure; they return an Option
/Result
:
let x: Option<usize> = try {
Some(3)?
};
x
is still an Option
, and the ?
operator just broke out of the try
block instead of the most local function.
Additionally, if you want this to work:
fn foo() { // -> () implicitly
None?;
println!("Hello, World");
}
And print Hello, World
, then what would be needed is to implement From<NoneError> for ()
.
The behaviour of ?
on a type is dictated by std::ops::Try
, which when used on an Option
, its Err
type is NoneError
.
As stated in the docs:
The error type that results from applying the try operator ( ?
) to a None
value. If you wish to allow x?
(where x
is an Option<T>
) to be converted into your error type, you can implement impl From<NoneError>
for YourErrorType
. In that case, x?
within a function that returns Result<_, YourErrorType>
will translate a None
value into an Err
result.
Hence, if you want to be able to use ?
on a None
variant to return early out of a ()
returning function, std
would have to add an implementation for From<NoneError> for ()
.
Unfortunately, that might cause even more ambiguity errors:
fn foo() -> Option<()> {
(|| None?)()
}
Works fine, however lets introduce a mock Unit
type to replace ()
upon which we can implement our own traits:
#![feature(try_trait)]
use std::option::NoneError;
struct Unit;
impl From<NoneError> for Unit {
fn from(x: NoneError) -> Self {
Unit
}
}
fn foo() -> Unit {
(|| None?)()?;
Unit
}
However, even this produces an error:
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:14:5
|
13 | / fn foo() -> Unit {
14 | | (|| None?)()?;
| | ^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `Unit`
15 | |
16 | | Unit
17 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `Unit`
= note: required by `std::ops::Try::from_error`
Which points out that the function's return type must also implement Try
.