Skip to content

Bad/confusing error message with Residuals #90863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
simbleau opened this issue Nov 13, 2021 · 5 comments
Closed

Bad/confusing error message with Residuals #90863

simbleau opened this issue Nov 13, 2021 · 5 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@simbleau
Copy link
Contributor

simbleau commented Nov 13, 2021

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1b1c18cee65bf066a53f2c1a8c3653d0

extern crate anyhow; // 1.0.45
use anyhow::Result;

fn give_result() -> Result<()> {
    Ok(())
}

pub fn main() {
    give_result()?; // <--- Notice the `?`
}

The current output is:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> src/main.rs:9:18
    |
8   | / pub fn main() {
9   | |     give_result()?;
    | |                  ^ cannot use the `?` operator in a function that returns `()`
10  | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Result<Infallible, anyhow::Error>>` is not implemented for `()`
note: required by `from_residual`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

What is wrong?:

  • The indication on which offending function that does not return Result or Option could be better. It could be more explicit on whether main() or get_result() needs to return Result or Option.
  • The helper text help: the trait `FromResidual<Result<Infallible, anyhow::Error>>` is not implemented for `()` note: required by `from_residual`. is help text for the internal compiler which does not need to be passed to developers. It's generally incomprehensible to most who do not know that this trait bound error has nothing to do with their code and would confuse a mass of new Rust programmers.

Ideally the output should look like:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> src/main.rs:9:18
    |
8   | / pub fn main() {
    | |            ^^ `main` does not return `Result` or `Option` to accept `?`
9   | |     give_result()?;
    | |                  ^ cannot use the `?` operator in a function that returns `()`
10  | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
@simbleau simbleau added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 13, 2021
@the8472
Copy link
Member

the8472 commented Nov 13, 2021

There is no clear message saying which function does not return Result or Option.

The ascii-art points to it.

@simbleau
Copy link
Contributor Author

simbleau commented Nov 13, 2021

There is no clear message saying which function does not return Result or Option.

The ascii-art points to it.

Yes, this line does so at the very bottom.

    | |_- this function should return `Result` or `Option` to accept `?`

I was not clear what my intention was with that point.
I meant it would be helpful to say the method's name or give an ascii pointer to that name.

Such as:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> src/main.rs:9:18
    |
8   | / pub fn main() {
    | |            ^^ main does not return `Result` or `Option` to accept `?`
9   | |     give_result()?;
    | |                  ^ cannot use the `?` operator in a function that returns `()`
10  | | }
    |

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

or:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> src/main.rs:9:18
    |
8   | / pub fn main() {
9   | |     give_result()?;
    | |                  ^ cannot use the `?` operator in a function that returns `()`
10  | | }
    | |_- the function `main` should return `Result` or `Option` to accept `?`
    |

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

@kpreid
Copy link
Contributor

kpreid commented Feb 12, 2022

I was just thinking about this frequently-confusing message, and I have an additional idea here. I agree with the above that the span over the whole function item is confusing and marking just the signature or name would be better, but, in addition, this error could have a suggestion to change the function's return type:

-pub fn main() -> T {
+pub fn main() -> Result<T, E> {

where T is whatever the existing return type is, and E is the error type of the Result that is entering the ? operator. (Unfortunately, this would then break the existing value return if any, and an immediate suggestion of Ok might be more confusing than helpful...)

It might also help if it had a dedicated error code instead of E0277, so that the error guide could explain about the use of ? instead of general information about missing trait implementations.

@blueforesticarus
Copy link

blueforesticarus commented Aug 7, 2022

   = help: the following other types implement trait `FromResidual<R>`:
             <Result<T, F> as FromResidual<Result<std::convert::Infallible, E>>>
             <Result<T, F> as FromResidual<Yeet<E>>>
   = note: required because of the requirements on the impl of `From<bytemuck::PodCastError>` for `anyhow::Error`
   = note: required because of the requirements on the impl of `FromResidual<Result<std::convert::Infallible, bytemuck::PodCastError>>` for `Result<(), anyhow::Error>`

I would agree that the FromResidual lines are distracting. It took me a solid minute to realize this wasn't some weird new error message I hadn't seen before and that ^ the trait StdError is not implemented for bytemuck::PodCastError was the whole cause (turns out I had an old version of the library).

Not sure how it could be improved though...

@estebank
Copy link
Contributor

Current output on stable:

error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
 --> src/main.rs:9:18
  |
8 | pub fn main() {
  | ------------- this function should return `Result` or `Option` to accept `?`
9 |     give_result()?;
  |                  ^ cannot use the `?` operator in a function that returns `()`
  |
  = help: the trait `FromResidual<Result<Infallible, anyhow::Error>>` is not implemented for `()`
help: consider adding return type
  |
8 ~ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
9 |     give_result()?;
10+     Ok(())
  |

#137232 will remove the FromResidual note, as it is unnecessary context unless you have that feature enabled. (It does hide the knowledge from nightly users that they could enable the feature, so we might want to have a third case of "on nightly with the feature disabled", but that's a discussion for that PR.)

I believe that the current output pretty much matches the originally requested, so I'll go ahead and close this ticket. Other tickets for other specific cases can be created, of course :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants