Better rustc_on_unimplemented, and UI test fixes

This commit is contained in:
Scott McMurray 2021-04-17 11:56:07 -07:00
parent 47b99485a3
commit 4a7ceea930
38 changed files with 564 additions and 266 deletions

View File

@ -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};

View File

@ -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.

View File

@ -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 `?`

View File

@ -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?;

View File

@ -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

View File

@ -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
};
}

View File

@ -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

View File

@ -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
};
}

View File

@ -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

View File

@ -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

View File

@ -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
};
}

View File

@ -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<(), _> {

View File

@ -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<_>> {

View File

@ -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

View File

@ -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`.

View File

@ -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`.

View File

@ -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

View File

@ -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?;

View File

@ -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`
}

View File

@ -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`.

View File

@ -4,5 +4,5 @@
fn main() {
while try { false } {}
//~^ ERROR the trait bound `bool: Try` is not satisfied
//~^ ERROR a `try` block must
}

View File

@ -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

View File

@ -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 | };

View File

@ -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`.

View File

@ -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();
}

View 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() {}

View 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`.

View File

@ -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)
}

View 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`.

View 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));
}

View File

@ -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

View File

@ -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)
}

View 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`.

View 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();
}

View File

@ -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`

View File

@ -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`.