Skip to content

Diagnostics: compiler should hint about .as_ref() when trying to go from &Option<> to Option<&>. #53809

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
vi opened this issue Aug 30, 2018 · 2 comments
Labels
A-borrow-checker Area: The borrow checker A-diagnostics Area: Messages for errors, warnings, and lints

Comments

@vi
Copy link
Contributor

vi commented Aug 30, 2018

fn main() {
    let a = Some(vec![1,2,3,4]);
    let b : &Option<Vec<u8>> = &a;
    let c : Option<&[u8]>;
    // c = b; // expected enum `std::option::Option`, found reference
    // c = *b; // expected &[u8], found struct `std::vec::Vec`
    // c = (*b).map(|x|x.as_slice()); // cannot move `b` out of borrowed content
    // c = b.map(|x|x.as_slice()); // cannot move `b` out of borrowed content and `x` does not live long enough
    
    // Ask IRC here
    
    c = b.as_ref().map(|x|x.as_slice());

    let _ = c;
}

Compiler message should hint Option::as_ref, to shift user attention from object inside Option to the Option itself.

@estebank
Copy link
Contributor

estebank commented Aug 30, 2018

Similar issue to #43861, which was fixed with a targeted hack in #51100.

The first two cases could probably be handled by extending that code, the last two are lifetime errors so they would need to touch a different part of the compiler.

For future reference, the four cases produce the following output:

error[E0308]: mismatched types
 --> src/main.rs:6:9
  |
6 |     c = b;
  |         ^ expected enum `std::option::Option`, found reference
  |
  = note: expected type `std::option::Option<&[u8]>`
             found type `&std::option::Option<std::vec::Vec<u8>>`
error[E0308]: mismatched types
 --> src/main.rs:7:9
  |
7 |     c = *b;
  |         ^^ expected &[u8], found struct `std::vec::Vec`
  |
  = note: expected type `std::option::Option<&[u8]>`
             found type `std::option::Option<std::vec::Vec<u8>>`
error[E0597]: `x` does not live long enough
 --> src/main.rs:8:21
  |
8 |     c = (*b).map(|x|x.as_slice());
  |                     ^          - `x` dropped here while still borrowed
  |                     |
  |                     borrowed value does not live long enough

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:8:9
  |
8 |     c = (*b).map(|x|x.as_slice());
  |         ^^^^ cannot move out of borrowed content
error[E0597]: `x` does not live long enough
 --> src/main.rs:9:18
  |
9 |     c = b.map(|x|x.as_slice());
  |                  ^          - `x` dropped here while still borrowed
  |                  |
  |                  borrowed value does not live long enough

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:9:9
  |
9 |     c = b.map(|x|x.as_slice());
  |         ^ cannot move out of borrowed content

@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions A-borrow-checker Area: The borrow checker and removed A-lifetimes Area: Lifetimes / regions labels Aug 30, 2018
@estebank
Copy link
Contributor

Current output for 3 and 4:

error[E0515]: cannot return value referencing function parameter `x`
 --> src/main.rs:7:21
  |
7 |     c = (*b).map(|x|x.as_slice()); // cannot move `b` out of borrowed content
  |                     -^^^^^^^^^^^
  |                     |
  |                     returns a value referencing data owned by the current function
  |                     `x` is borrowed here

error[E0507]: cannot move out of `*b` which is behind a shared reference
 --> src/main.rs:7:9
  |
7 |     c = (*b).map(|x|x.as_slice()); // cannot move `b` out of borrowed content
  |         ^^^^
  |         |
  |         move occurs because `*b` has type `std::option::Option<std::vec::Vec<u8>>`, which does not implement the `Copy` trait
  |         help: consider borrowing the `Option`'s content: `(*b).as_ref()`
error[E0515]: cannot return value referencing function parameter `x`
 --> src/main.rs:8:18
  |
8 |     c = b.map(|x|x.as_slice()); // cannot move `b` out of borrowed content and `x` does not live long enough
  |                  -^^^^^^^^^^^
  |                  |
  |                  returns a value referencing data owned by the current function
  |                  `x` is borrowed here

error[E0507]: cannot move out of `*b` which is behind a shared reference
 --> src/main.rs:8:9
  |
8 |     c = b.map(|x|x.as_slice()); // cannot move `b` out of borrowed content and `x` does not live long enough
  |         ^
  |         |
  |         move occurs because `*b` has type `std::option::Option<std::vec::Vec<u8>>`, which does not implement the `Copy` trait
  |         help: consider borrowing the `Option`'s content: `b.as_ref()`

Note the suggestions are accurate and fix the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker A-diagnostics Area: Messages for errors, warnings, and lints
Projects
None yet
Development

No branches or pull requests

2 participants