Better rustc_on_unimplemented, and UI test fixes
This commit is contained in:
parent
47b99485a3
commit
4a7ceea930
38 changed files with 564 additions and 266 deletions
|
@ -187,7 +187,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
|
|||
pub use self::r#try::Try;
|
||||
|
||||
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
|
||||
pub use self::r#try::Try as TryV1;
|
||||
pub(crate) use self::r#try::Try as TryV1;
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
pub use self::try_trait::FromResidual;
|
||||
|
@ -197,7 +197,7 @@ pub use self::try_trait::FromResidual;
|
|||
pub use self::try_trait::Try;
|
||||
|
||||
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
|
||||
pub use self::try_trait::Try as TryV2;
|
||||
pub(crate) use self::try_trait::Try as TryV2;
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
pub use self::generator::{Generator, GeneratorState};
|
||||
|
|
|
@ -115,6 +115,21 @@ use crate::ops::ControlFlow;
|
|||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(from_method = "from_output", 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_method = "branch", 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 = "?")]
|
||||
#[cfg_attr(not(bootstrap), lang = "Try")]
|
||||
pub trait Try: FromResidual {
|
||||
/// The type of the value produced by `?` when *not* short-circuiting.
|
||||
|
@ -212,6 +227,70 @@ pub trait Try: FromResidual {
|
|||
/// Every `Try` type needs to be recreatable from its own associated
|
||||
/// `Residual` type, but can also have additional `FromResidual` implementations
|
||||
/// to support interconversion with other `Try` types.
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
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}`",
|
||||
enclosing_scope = "this function returns a `Result`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::result::Result<T, E>",
|
||||
),
|
||||
// There's a special error message in the trait selection code for
|
||||
// `From` in `?`, so this is not shown for result-in-result errors,
|
||||
// and thus it can be phrased more strongly than `ControlFlow`'s.
|
||||
message = "the `?` operator can only be used on `Result`s \
|
||||
in {ItemContext} that returns `Result`",
|
||||
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
|
||||
enclosing_scope = "this function returns a `Result`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::option::Option<T>",
|
||||
),
|
||||
// `Option`-in-`Option` always works, as there's only one possible
|
||||
// residual, so this can also be phrased strongly.
|
||||
message = "the `?` operator can only be used on `Option`s \
|
||||
in {ItemContext} that returns `Option`",
|
||||
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
|
||||
enclosing_scope = "this function returns an `Option`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::ops::ControlFlow<B, C>",
|
||||
),
|
||||
message = "the `?` operator can only be used on `ControlFlow<B, _>`s \
|
||||
in {ItemContext} that returns `ControlFlow<B, _>`",
|
||||
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
|
||||
enclosing_scope = "this function returns a `ControlFlow`",
|
||||
note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
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}`",
|
||||
enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
|
||||
),
|
||||
)]
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
pub trait FromResidual<R = <Self as Try>::Residual> {
|
||||
/// Constructs the type from a compatible `Residual` type.
|
||||
|
|
|
@ -42,7 +42,7 @@ async fn bar() -> Result<(), ()> {
|
|||
foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
//~^ NOTE the `?` operator cannot be applied to type `impl Future`
|
||||
//~| HELP the trait `Try` is not implemented for `impl Future`
|
||||
//~| NOTE required by `into_result`
|
||||
//~| NOTE required by `branch`
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
|
@ -65,7 +65,7 @@ async fn baz() -> Result<(), ()> {
|
|||
t?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
//~^ NOTE the `?` operator cannot be applied to type `T`
|
||||
//~| HELP the trait `Try` is not implemented for `T`
|
||||
//~| NOTE required by `into_result`
|
||||
//~| NOTE required by `branch`
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | foo()?;
|
|||
| ^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | foo().await?;
|
||||
|
@ -18,7 +18,7 @@ LL | t?;
|
|||
| ^^ the `?` operator cannot be applied to type `T`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `T`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | t.await?;
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-in-async.rs:8:9
|
||||
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-in-async.rs:8:10
|
||||
|
|
||||
LL | async {
|
||||
| ___________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in an async block that returns `{integer}`
|
||||
| | ^ cannot use the `?` operator in an async block that returns `{integer}`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-in-async.rs:17:9
|
||||
error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-in-async.rs:17:10
|
||||
|
|
||||
LL | let async_closure = async || {
|
||||
| __________________________________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in an async closure that returns `u32`
|
||||
| | ^ cannot use the `?` operator in an async closure that returns `u32`
|
||||
LL | | 22_u32
|
||||
LL | | };
|
||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-in-async.rs:26:5
|
||||
error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-in-async.rs:26:6
|
||||
|
|
||||
LL | async fn an_async_function() -> u32 {
|
||||
| _____________________________________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in an async function that returns `u32`
|
||||
| | ^ cannot use the `?` operator in an async function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ fn make_unit() -> Result<(), Error> {
|
|||
|
||||
fn main() {
|
||||
let fut = async {
|
||||
make_unit()?; //~ ERROR type annotations needed
|
||||
make_unit()?;
|
||||
|
||||
Ok(())
|
||||
Ok(()) //~ ERROR type annotations needed
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,14 +8,13 @@ LL | #![feature(impl_trait_in_bindings)]
|
|||
= note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
|
||||
|
||||
error[E0282]: type annotations needed for `impl Future`
|
||||
--> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20
|
||||
--> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:15:9
|
||||
|
|
||||
LL | let fut = async {
|
||||
| --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified
|
||||
LL | make_unit()?;
|
||||
| ^ cannot infer type of error for `?` operator
|
||||
|
|
||||
= note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
|
||||
| --- consider giving `fut` the explicit type `impl Future`, where the type parameter `E` is specified
|
||||
...
|
||||
LL | Ok(())
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ fn make_unit() -> Result<(), Error> {
|
|||
|
||||
fn main() {
|
||||
let fut = async {
|
||||
make_unit()?; //~ ERROR type annotations needed
|
||||
make_unit()?;
|
||||
|
||||
Ok(())
|
||||
Ok(()) //~ ERROR type annotations needed
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
error[E0282]: type annotations needed
|
||||
--> $DIR/cannot-infer-async.rs:11:20
|
||||
--> $DIR/cannot-infer-async.rs:13:9
|
||||
|
|
||||
LL | let fut = async {
|
||||
| --- consider giving `fut` a type
|
||||
LL | make_unit()?;
|
||||
| ^ cannot infer type of error for `?` operator
|
||||
|
|
||||
= note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
|
||||
...
|
||||
LL | Ok(())
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Result<(), E>`
|
|||
--> $DIR/cannot-infer-closure-circular.rs:7:14
|
||||
|
|
||||
LL | let x = |r| {
|
||||
| ^ consider giving this closure parameter the explicit type `Result<(), E>`, with the type parameters specified
|
||||
| ^ consider giving this closure parameter the explicit type `Result<(), E>`, where the type parameter `E` is specified
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
fn main() {
|
||||
let x = |a: (), b: ()| {
|
||||
Err(a)?; //~ ERROR type annotations needed for the closure
|
||||
Ok(b)
|
||||
Err(a)?;
|
||||
Ok(b) //~ ERROR type annotations needed for the closure
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>`
|
||||
--> $DIR/cannot-infer-closure.rs:3:15
|
||||
--> $DIR/cannot-infer-closure.rs:4:9
|
||||
|
|
||||
LL | Err(a)?;
|
||||
| ^ cannot infer type of error for `?` operator
|
||||
LL | Ok(b)
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
|
||||
= note: `?` implicitly converts the error value into a type implementing `From<()>`
|
||||
help: give this closure an explicit return type without `_` placeholders
|
||||
|
|
||||
LL | let x = |a: (), b: ()| -> Result<(), _> {
|
||||
|
|
|
@ -2,9 +2,8 @@ error[E0282]: type annotations needed for the closure `fn() -> Result<(), Qualif
|
|||
--> $DIR/cannot-infer-partial-try-return.rs:19:9
|
||||
|
|
||||
LL | infallible()?;
|
||||
| ^^^^^^^^^^^^^ cannot infer type of error for `?` operator
|
||||
| ^^^^^^^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: `?` implicitly converts the error value into `QualifiedError<_>` using its implementation of `From<Infallible>`
|
||||
help: give this closure an explicit return type without `_` placeholders
|
||||
|
|
||||
LL | let x = || -> Result<(), QualifiedError<_>> {
|
||||
|
|
|
@ -7,7 +7,8 @@ LL | Err(5)?;
|
|||
| ^ the trait `From<{integer}>` is not implemented for `()`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
error[E0277]: `?` couldn't convert the error to `()`
|
||||
--> $DIR/option-to-result.rs:5:6
|
||||
|
|
||||
LL | fn test_result() -> Result<(),()> {
|
||||
| ------------- expected `()` because of this
|
||||
LL | let a:Option<()> = Some(());
|
||||
LL | a?;
|
||||
| ^ the trait `From<NoneError>` is not implemented for `()`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`
|
||||
|
|
||||
LL | a.ok_or_else(|| /* error value */)?;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `?` couldn't convert the error to `NoneError`
|
||||
--> $DIR/option-to-result.rs:11:6
|
||||
|
|
||||
LL | fn test_option() -> Option<i32>{
|
||||
| ----------- expected `NoneError` because of this
|
||||
LL | let a:Result<i32, i32> = Ok(5);
|
||||
LL | a?;
|
||||
| ^ the trait `From<i32>` is not implemented for `NoneError`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
help: consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`
|
||||
|
|
||||
LL | a.ok()?;
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,11 +1,10 @@
|
|||
error[E0283]: type annotations needed
|
||||
error[E0284]: type annotations needed
|
||||
--> $DIR/question-mark-type-infer.rs:12:21
|
||||
|
|
||||
LL | l.iter().map(f).collect()?
|
||||
| ^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: cannot satisfy `_: Try`
|
||||
= note: required by `into_result`
|
||||
= note: cannot satisfy `<_ as Try>::Residual == _`
|
||||
help: consider specifying the type argument in the method call
|
||||
|
|
||||
LL | l.iter().map(f).collect::<B>()?
|
||||
|
@ -13,4 +12,4 @@ LL | l.iter().map(f).collect::<B>()?
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
|
|
|
@ -502,10 +502,10 @@ LL | if (let 0 = 0)? {}
|
|||
| ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/disallowed-positions.rs:46:8
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/disallowed-positions.rs:46:19
|
||||
|
|
||||
LL | / fn nested_within_if_expr() {
|
||||
LL | | if &let 0 = 0 {}
|
||||
|
@ -513,14 +513,14 @@ LL | |
|
|||
LL | |
|
||||
... |
|
||||
LL | | if (let 0 = 0)? {}
|
||||
| | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | | if let true = let true = true {}
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:56:8
|
||||
|
@ -660,7 +660,7 @@ LL | if let 0 = 0? {}
|
|||
| ^^ the `?` operator cannot be applied to type `{integer}`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:96:11
|
||||
|
@ -690,10 +690,10 @@ LL | while (let 0 = 0)? {}
|
|||
| ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/disallowed-positions.rs:110:11
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/disallowed-positions.rs:110:22
|
||||
|
|
||||
LL | / fn nested_within_while_expr() {
|
||||
LL | | while &let 0 = 0 {}
|
||||
|
@ -701,14 +701,14 @@ LL | |
|
|||
LL | |
|
||||
... |
|
||||
LL | | while (let 0 = 0)? {}
|
||||
| | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | | while let true = let true = true {}
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:120:11
|
||||
|
@ -848,7 +848,7 @@ LL | while let 0 = 0? {}
|
|||
| ^^ the `?` operator cannot be applied to type `{integer}`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0614]: type `bool` cannot be dereferenced
|
||||
--> $DIR/disallowed-positions.rs:173:5
|
||||
|
@ -869,10 +869,10 @@ LL | (let 0 = 0)?;
|
|||
| ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/disallowed-positions.rs:183:5
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/disallowed-positions.rs:183:16
|
||||
|
|
||||
LL | / fn outside_if_and_while_expr() {
|
||||
LL | | &let 0 = 0;
|
||||
|
@ -880,14 +880,14 @@ LL | |
|
|||
LL | | !let 0 = 0;
|
||||
... |
|
||||
LL | | (let 0 = 0)?;
|
||||
| | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:198:10
|
||||
|
@ -916,7 +916,7 @@ LL | let 0 = 0?;
|
|||
| ^^ the `?` operator cannot be applied to type `{integer}`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error: aborting due to 104 previous errors; 2 warnings emitted
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | SadGirl {}.call()?;
|
|||
| ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | SadGirl {}.call().await?;
|
||||
|
|
|
@ -15,8 +15,7 @@ pub fn main() {
|
|||
let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
|
||||
|
||||
let res: () = try { };
|
||||
//~^ ERROR the trait bound `(): Try` is not satisfied
|
||||
//~| ERROR the trait bound `(): Try` is not satisfied
|
||||
//~^ ERROR a `try` block must return `Result` or `Option`
|
||||
|
||||
let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied
|
||||
let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option`
|
||||
}
|
||||
|
|
|
@ -7,43 +7,40 @@ LL | Err("")?;
|
|||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= help: the following implementations were found:
|
||||
<TryFromSliceError as From<Infallible>>
|
||||
= note: required by `from`
|
||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Ok == &str`
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
|
||||
--> $DIR/try-block-bad-type.rs:12:9
|
||||
|
|
||||
LL | ""
|
||||
| ^^ expected `i32`, found `&str`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Ok == ()`
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == ()`
|
||||
--> $DIR/try-block-bad-type.rs:15:39
|
||||
|
|
||||
LL | let res: Result<i32, i32> = try { };
|
||||
| ^ expected `i32`, found `()`
|
||||
|
||||
error[E0277]: the trait bound `(): Try` is not satisfied
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-bad-type.rs:17:25
|
||||
|
|
||||
LL | let res: () = try { };
|
||||
| ^ the trait `Try` is not implemented for `()`
|
||||
| ^ could not wrap the final value of the block as `()` doesn't implement `Try`
|
||||
|
|
||||
= note: required by `from_ok`
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_output`
|
||||
|
||||
error[E0277]: the trait bound `(): Try` is not satisfied
|
||||
--> $DIR/try-block-bad-type.rs:17:25
|
||||
|
|
||||
LL | let res: () = try { };
|
||||
| ^ the trait `Try` is not implemented for `()`
|
||||
|
||||
error[E0277]: the trait bound `i32: Try` is not satisfied
|
||||
--> $DIR/try-block-bad-type.rs:21:26
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-bad-type.rs:20:26
|
||||
|
|
||||
LL | let res: i32 = try { 5 };
|
||||
| ^ the trait `Try` is not implemented for `i32`
|
||||
| ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
|
||||
|
|
||||
= note: required by `from_ok`
|
||||
= help: the trait `Try` is not implemented for `i32`
|
||||
= note: required by `from_output`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
fn main() {
|
||||
while try { false } {}
|
||||
//~^ ERROR the trait bound `bool: Try` is not satisfied
|
||||
//~^ ERROR a `try` block must
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
error[E0277]: the trait bound `bool: Try` is not satisfied
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-in-while.rs:6:17
|
||||
|
|
||||
LL | while try { false } {}
|
||||
| ^^^^^ the trait `Try` is not implemented for `bool`
|
||||
| ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try`
|
||||
|
|
||||
= note: required by `from_ok`
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `from_output`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0271]: type mismatch resolving `<Option<f32> as Try>::Ok == {integer}`
|
||||
error[E0271]: type mismatch resolving `<Option<f32> as Try>::Output == {integer}`
|
||||
--> $DIR/try-block-type-error.rs:10:9
|
||||
|
|
||||
LL | 42
|
||||
|
@ -7,7 +7,7 @@ LL | 42
|
|||
| expected `f32`, found integer
|
||||
| help: use a float literal: `42.0`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Option<i32> as Try>::Ok == ()`
|
||||
error[E0271]: type mismatch resolving `<Option<i32> as Try>::Output == ()`
|
||||
--> $DIR/try-block-type-error.rs:16:5
|
||||
|
|
||||
LL | };
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
error[E0277]: `?` couldn't convert the error to `()`
|
||||
--> $DIR/try-on-option.rs:7:6
|
||||
|
|
||||
LL | fn foo() -> Result<u32, ()> {
|
||||
| --------------- expected `()` because of this
|
||||
LL | let x: Option<u32> = None;
|
||||
LL | x?;
|
||||
| ^ the trait `From<NoneError>` is not implemented for `()`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`
|
||||
|
|
||||
LL | x.ok_or_else(|| /* error value */)?;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option.rs:13:5
|
||||
|
|
||||
LL | / fn bar() -> u32 {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,63 +0,0 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(try_trait)]
|
||||
|
||||
use std::ops::Try;
|
||||
|
||||
enum MyResult<T, U> {
|
||||
Awesome(T),
|
||||
Terrible(U)
|
||||
}
|
||||
|
||||
impl<U, V> Try for MyResult<U, V> {
|
||||
type Ok = U;
|
||||
type Error = V;
|
||||
|
||||
fn from_ok(u: U) -> MyResult<U, V> {
|
||||
MyResult::Awesome(u)
|
||||
}
|
||||
|
||||
fn from_error(e: V) -> MyResult<U, V> {
|
||||
MyResult::Terrible(e)
|
||||
}
|
||||
|
||||
fn into_result(self) -> Result<U, V> {
|
||||
match self {
|
||||
MyResult::Awesome(u) => Ok(u),
|
||||
MyResult::Terrible(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn f(x: i32) -> Result<i32, String> {
|
||||
if x == 0 {
|
||||
Ok(42)
|
||||
} else {
|
||||
let y = g(x)?;
|
||||
Ok(y)
|
||||
}
|
||||
}
|
||||
|
||||
fn g(x: i32) -> MyResult<i32, String> {
|
||||
let _y = f(x - 1)?;
|
||||
MyResult::Terrible("Hello".to_owned())
|
||||
}
|
||||
|
||||
fn h() -> MyResult<i32, String> {
|
||||
let a: Result<i32, &'static str> = Err("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn i() -> MyResult<i32, String> {
|
||||
let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert!(f(0) == Ok(42));
|
||||
assert!(f(10) == Err("Hello".to_owned()));
|
||||
let _ = h();
|
||||
let _ = i();
|
||||
}
|
48
src/test/ui/try-trait/bad-interconversion.rs
Normal file
48
src/test/ui/try-trait/bad-interconversion.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
#![feature(control_flow_enum)]
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
fn result_to_result() -> Result<u64, u8> {
|
||||
Ok(Err(123_i32)?)
|
||||
//~^ ERROR `?` couldn't convert the error to `u8`
|
||||
}
|
||||
|
||||
fn option_to_result() -> Result<u64, String> {
|
||||
Some(3)?;
|
||||
//~^ ERROR the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
Ok(10)
|
||||
}
|
||||
|
||||
fn control_flow_to_result() -> Result<u64, String> {
|
||||
Ok(ControlFlow::Break(123)?)
|
||||
//~^ ERROR the `?` operator can only be used on `Result`s in a function that returns `Result`
|
||||
}
|
||||
|
||||
fn result_to_option() -> Option<u16> {
|
||||
Some(Err("hello")?)
|
||||
//~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
}
|
||||
|
||||
fn control_flow_to_option() -> Option<u64> {
|
||||
Some(ControlFlow::Break(123)?)
|
||||
//~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
}
|
||||
|
||||
fn result_to_control_flow() -> ControlFlow<String> {
|
||||
ControlFlow::Continue(Err("hello")?)
|
||||
//~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
}
|
||||
|
||||
fn option_to_control_flow() -> ControlFlow<u64> {
|
||||
Some(3)?;
|
||||
//~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
ControlFlow::Break(10)
|
||||
}
|
||||
|
||||
fn control_flow_to_control_flow() -> ControlFlow<i64> {
|
||||
ControlFlow::Break(4_u8)?;
|
||||
//~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn main() {}
|
115
src/test/ui/try-trait/bad-interconversion.stderr
Normal file
115
src/test/ui/try-trait/bad-interconversion.stderr
Normal file
|
@ -0,0 +1,115 @@
|
|||
error[E0277]: `?` couldn't convert the error to `u8`
|
||||
--> $DIR/bad-interconversion.rs:6:20
|
||||
|
|
||||
LL | fn result_to_result() -> Result<u64, u8> {
|
||||
| --------------- expected `u8` because of this
|
||||
LL | Ok(Err(123_i32)?)
|
||||
| ^ the trait `From<i32>` is not implemented for `u8`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= help: the following implementations were found:
|
||||
<u8 as From<NonZeroU8>>
|
||||
<u8 as From<bool>>
|
||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
--> $DIR/bad-interconversion.rs:11:12
|
||||
|
|
||||
LL | / fn option_to_result() -> Result<u64, String> {
|
||||
LL | | Some(3)?;
|
||||
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
|
||||
LL | |
|
||||
LL | | Ok(10)
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
|
||||
--> $DIR/bad-interconversion.rs:17:31
|
||||
|
|
||||
LL | / fn control_flow_to_result() -> Result<u64, String> {
|
||||
LL | | Ok(ControlFlow::Break(123)?)
|
||||
| | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
--> $DIR/bad-interconversion.rs:22:22
|
||||
|
|
||||
LL | / fn result_to_option() -> Option<u16> {
|
||||
LL | | Some(Err("hello")?)
|
||||
| | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `Option<u16>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns an `Option`
|
||||
|
|
||||
= help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
--> $DIR/bad-interconversion.rs:27:33
|
||||
|
|
||||
LL | / fn control_flow_to_option() -> Option<u64> {
|
||||
LL | | Some(ControlFlow::Break(123)?)
|
||||
| | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns an `Option`
|
||||
|
|
||||
= help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
--> $DIR/bad-interconversion.rs:32:39
|
||||
|
|
||||
LL | / fn result_to_control_flow() -> ControlFlow<String> {
|
||||
LL | | ControlFlow::Continue(Err("hello")?)
|
||||
| | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns a `ControlFlow`
|
||||
|
|
||||
= help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
|
||||
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
--> $DIR/bad-interconversion.rs:37:12
|
||||
|
|
||||
LL | / fn option_to_control_flow() -> ControlFlow<u64> {
|
||||
LL | | Some(3)?;
|
||||
| | ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
|
||||
LL | |
|
||||
LL | | ControlFlow::Break(10)
|
||||
LL | | }
|
||||
| |_- this function returns a `ControlFlow`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
|
||||
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
--> $DIR/bad-interconversion.rs:43:29
|
||||
|
|
||||
LL | / fn control_flow_to_control_flow() -> ControlFlow<i64> {
|
||||
LL | | ControlFlow::Break(4_u8)?;
|
||||
| | ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
|
||||
LL | |
|
||||
LL | | ControlFlow::Continue(())
|
||||
LL | | }
|
||||
| |_- this function returns a `ControlFlow`
|
||||
|
|
||||
= help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
|
||||
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -2,12 +2,12 @@ fn main(){ }
|
|||
|
||||
fn test_result() -> Result<(),()> {
|
||||
let a:Option<()> = Some(());
|
||||
a?;//~ ERROR `?` couldn't convert the error
|
||||
a?;//~ ERROR the `?` operator can only be used
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_option() -> Option<i32>{
|
||||
let a:Result<i32, i32> = Ok(5);
|
||||
a?;//~ ERROR `?` couldn't convert the error
|
||||
a?;//~ ERROR the `?` operator can only be used
|
||||
Some(5)
|
||||
}
|
31
src/test/ui/try-trait/option-to-result.stderr
Normal file
31
src/test/ui/try-trait/option-to-result.stderr
Normal file
|
@ -0,0 +1,31 @@
|
|||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
--> $DIR/option-to-result.rs:5:6
|
||||
|
|
||||
LL | / fn test_result() -> Result<(),()> {
|
||||
LL | | let a:Option<()> = Some(());
|
||||
LL | | a?;
|
||||
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
|
||||
LL | | Ok(())
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
--> $DIR/option-to-result.rs:11:6
|
||||
|
|
||||
LL | / fn test_option() -> Option<i32>{
|
||||
LL | | let a:Result<i32, i32> = Ok(5);
|
||||
LL | | a?;
|
||||
| | ^ this `?` produces `Result<Infallible, i32>`, which is incompatible with `Option<i32>`
|
||||
LL | | Some(5)
|
||||
LL | | }
|
||||
| |_- this function returns an `Option`
|
||||
|
|
||||
= help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
24
src/test/ui/try-trait/try-as-monad.rs
Normal file
24
src/test/ui/try-trait/try-as-monad.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::Try;
|
||||
|
||||
fn monad_unit<T: Try>(x: <T as Try>::Output) -> T {
|
||||
T::from_output(x)
|
||||
}
|
||||
|
||||
fn monad_bind<T1: Try<Residual = R>, T2: Try<Residual = R>, R>(
|
||||
mx: T1,
|
||||
f: impl FnOnce(<T1 as Try>::Output) -> T2)
|
||||
-> T2 {
|
||||
let x = mx?;
|
||||
f(x)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mx: Option<i32> = monad_unit(1);
|
||||
let my = monad_bind(mx, |x| Some(x + 1));
|
||||
let mz = monad_bind(my, |x| Some(-x));
|
||||
assert_eq!(mz, Some(-2));
|
||||
}
|
|
@ -1,57 +1,57 @@
|
|||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:7:5
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:7:6
|
||||
|
|
||||
LL | / fn a_function() -> u32 {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a function that returns `u32`
|
||||
| | ^ cannot use the `?` operator in a function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:14:9
|
||||
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:14:10
|
||||
|
|
||||
LL | let a_closure = || {
|
||||
| _____________________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a closure that returns `{integer}`
|
||||
| | ^ cannot use the `?` operator in a closure that returns `{integer}`
|
||||
LL | | 22
|
||||
LL | | };
|
||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:26:13
|
||||
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:26:14
|
||||
|
|
||||
LL | / fn a_method() {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a method that returns `()`
|
||||
| | ^ cannot use the `?` operator in a method that returns `()`
|
||||
LL | | }
|
||||
| |_________- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:39:13
|
||||
error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:39:14
|
||||
|
|
||||
LL | / fn a_trait_method() {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a trait method that returns `()`
|
||||
| | ^ cannot use the `?` operator in a trait method that returns `()`
|
||||
LL | | }
|
||||
| |_________- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
|
@ -4,7 +4,7 @@ fn main() {}
|
|||
|
||||
fn foo() -> Result<u32, ()> {
|
||||
let x: Option<u32> = None;
|
||||
x?; //~ ERROR `?` couldn't convert the error
|
||||
x?; //~ ERROR the `?` operator
|
||||
Ok(22)
|
||||
}
|
||||
|
31
src/test/ui/try-trait/try-on-option.stderr
Normal file
31
src/test/ui/try-trait/try-on-option.stderr
Normal file
|
@ -0,0 +1,31 @@
|
|||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
--> $DIR/try-on-option.rs:7:6
|
||||
|
|
||||
LL | / fn foo() -> Result<u32, ()> {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
|
||||
LL | | Ok(22)
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option.rs:13:6
|
||||
|
|
||||
LL | / fn bar() -> u32 {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^ cannot use the `?` operator in a function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
91
src/test/ui/try-trait/try-operator-custom.rs
Normal file
91
src/test/ui/try-trait/try-operator-custom.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::{ControlFlow, FromResidual, Try};
|
||||
|
||||
enum MyResult<T, U> {
|
||||
Awesome(T),
|
||||
Terrible(U)
|
||||
}
|
||||
|
||||
enum Never {}
|
||||
|
||||
impl<U, V> Try for MyResult<U, V> {
|
||||
type Output = U;
|
||||
type Residual = MyResult<Never, V>;
|
||||
|
||||
fn from_output(u: U) -> MyResult<U, V> {
|
||||
MyResult::Awesome(u)
|
||||
}
|
||||
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
match self {
|
||||
MyResult::Awesome(u) => ControlFlow::Continue(u),
|
||||
MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, V, W> FromResidual<MyResult<Never, V>> for MyResult<U, W> where V: Into<W> {
|
||||
fn from_residual(x: MyResult<Never, V>) -> Self {
|
||||
match x {
|
||||
MyResult::Awesome(u) => match u {},
|
||||
MyResult::Terrible(e) => MyResult::Terrible(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ResultResidual<E> = Result<std::convert::Infallible, E>;
|
||||
|
||||
impl<U, V, W> FromResidual<ResultResidual<V>> for MyResult<U, W> where V: Into<W> {
|
||||
fn from_residual(x: ResultResidual<V>) -> Self {
|
||||
match x {
|
||||
Ok(v) => match v {}
|
||||
Err(e) => MyResult::Terrible(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, V, W> FromResidual<MyResult<Never, V>> for Result<U, W> where V: Into<W> {
|
||||
fn from_residual(x: MyResult<Never, V>) -> Self {
|
||||
match x {
|
||||
MyResult::Awesome(u) => match u {},
|
||||
MyResult::Terrible(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn f(x: i32) -> Result<i32, String> {
|
||||
if x == 0 {
|
||||
Ok(42)
|
||||
} else {
|
||||
let y = g(x)?;
|
||||
Ok(y)
|
||||
}
|
||||
}
|
||||
|
||||
fn g(x: i32) -> MyResult<i32, String> {
|
||||
let _y = f(x - 1)?;
|
||||
MyResult::Terrible("Hello".to_owned())
|
||||
}
|
||||
|
||||
fn h() -> MyResult<i32, String> {
|
||||
let a: Result<i32, &'static str> = Err("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn i() -> MyResult<i32, String> {
|
||||
let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert!(f(0) == Ok(42));
|
||||
assert!(f(10) == Err("Hello".to_owned()));
|
||||
let _ = h();
|
||||
let _ = i();
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(try_trait)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::Try;
|
||||
|
||||
|
@ -7,14 +7,13 @@ fn main() {
|
|||
std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
|
||||
|
||||
// a non-`Try` type on a non-`Try` fn
|
||||
()?; //~ ERROR the `?` operator can only
|
||||
()?; //~ ERROR the `?` operator can only be applied to
|
||||
//~^ ERROR the `?` operator can only be used in a function that
|
||||
|
||||
// an unrelated use of `Try`
|
||||
try_trait_generic::<()>(); //~ ERROR the trait bound
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn try_trait_generic<T: Try>() -> T {
|
||||
// and a non-`Try` object on a `Try` fn.
|
||||
()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
|
|
@ -1,18 +1,18 @@
|
|||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-operator-on-main.rs:7:5
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-operator-on-main.rs:7:31
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | | // error for a `Try` type on a non-`Try` fn
|
||||
LL | | std::fs::File::open("foo")?;
|
||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
LL | |
|
||||
... |
|
||||
LL | | try_trait_generic::<()>();
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $DIR/try-operator-on-main.rs:10:5
|
||||
|
@ -21,10 +21,28 @@ LL | ()?;
|
|||
| ^^^ the `?` operator cannot be applied to type `()`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-operator-on-main.rs:10:7
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | | // error for a `Try` type on a non-`Try` fn
|
||||
LL | | std::fs::File::open("foo")?;
|
||||
LL | |
|
||||
LL | | // a non-`Try` type on a non-`Try` fn
|
||||
LL | | ()?;
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | | try_trait_generic::<()>();
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the trait bound `(): Try` is not satisfied
|
||||
--> $DIR/try-operator-on-main.rs:13:25
|
||||
--> $DIR/try-operator-on-main.rs:14:25
|
||||
|
|
||||
LL | try_trait_generic::<()>();
|
||||
| ^^ the trait `Try` is not implemented for `()`
|
||||
|
@ -33,14 +51,14 @@ LL | fn try_trait_generic<T: Try>() -> T {
|
|||
| --- required by this bound in `try_trait_generic`
|
||||
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $DIR/try-operator-on-main.rs:20:5
|
||||
--> $DIR/try-operator-on-main.rs:19:5
|
||||
|
|
||||
LL | ()?;
|
||||
| ^^^ the `?` operator cannot be applied to type `()`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in a new issue