Skip to content

Compiler should suggest expect/unwrap before the suggestion to remove the last method call #117669

Closed
@3tilley

Description

@3tilley

Code

fn main() {
    let abs: i32 = 3i32.checked_abs();
}

Current output

Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:2:20
  |
2 |     let abs: i32 = 3i32.checked_abs();
  |              ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Option<i32>`
  |              |
  |              expected due to this
  |
  = note: expected type `i32`
             found enum `Option<i32>`
help: try removing the method call
  |
2 -     let abs: i32 = 3i32.checked_abs();
2 +     let abs: i32 = 3i32;
  |

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to previous error

Desired output

Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:2:20
  |
2 |     let abs: i32 = 3i32.checked_abs();
  |              ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Option<i32>`
  |              |
  |              expected due to this
  |
  = note: expected type `i32`
             found enum `Option<i32>`
help: consider using `Option::expect` to unwrap the `Option<i32>` value, panicking if the value is an `Option::None`
   |
2  |     let abs: i32 = 3i32.checked_abs().expect("REASON");
   |                                      +++++++++++++++++

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to previous error

Rationale and extra context

#105872 in Dec '22 introduced a cool new feature to suggest removing the last method call if it would alleviate a type mismatch error. This is particularly using for people wrestling with my_str.to_string() issues.

#116841 in Oct '23 introduced another useful feature to suggest to users that they might consider expecting an Option or Result type in order to solve a type mismatch. Also very cool, and conveniently by the same author @chenyukang.

Unfortunately, in cases where a method T -> Option<T> is called, the previous check takes precedence, and the compiler suggests removing that trailing method to get the code to compile. This isn't generally that useful as the expect suggestion, and I can't think of an example where it's a better one. If you can think of one though, please put it below for me to test!

#116738 surfaced this with Path.parent() but it's more easily demonstrated with ints.

I can see two ways to fix this:

  1. Run the trailing method check first, but ignore Result and Option types
  2. Reorder the checks so the option type is checked first. Note that the method check has to be high in the chain as the motive is to quickly suggest removing a call, before adding a whole load of new ones. This means the expect check has to be one of the first

I am going to work on solving it via method 2, as it feels cleaner that the method check doesn't have to know about the Option and Result check.

If anyone has strong feelings on this, please let me know!

Playground here

Other cases

No response

Anything else?

No response

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions