Skip to content
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

Provide more context and suggestions in borrowck errors involving closures #124136

Merged
merged 3 commits into from
Apr 25, 2024

Commits on Apr 24, 2024

  1. Modify find_expr from Span to better account for closures

    Start pointing to where bindings were declared when they are captured in closures:
    
    ```
    error[E0597]: `x` does not live long enough
      --> $DIR/suggest-return-closure.rs:23:9
       |
    LL |     let x = String::new();
       |         - binding `x` declared here
    ...
    LL |     |c| {
       |     --- value captured here
    LL |         x.push(c);
       |         ^ borrowed value does not live long enough
    ...
    LL | }
       | -- borrow later used here
       | |
       | `x` dropped here while still borrowed
    ```
    
    Suggest cloning in more cases involving closures:
    
    ```
    error[E0507]: cannot move out of `foo` in pattern guard
      --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19
       |
    LL |             if { (|| { let mut bar = foo; bar.take() })(); false } => {},
       |                   ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
       |                   |
       |                   `foo` is moved here
       |
       = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
    help: consider cloning the value if the performance cost is acceptable
       |
    LL |             if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
       |                                         ++++++++
    ```
    estebank committed Apr 24, 2024
    Configuration menu
    Copy the full SHA
    4aba2c5 View commit details
    Browse the repository at this point in the history
  2. Mention when type parameter could be Clone

    ```
    error[E0382]: use of moved value: `t`
      --> $DIR/use_of_moved_value_copy_suggestions.rs:7:9
       |
    LL | fn duplicate_t<T>(t: T) -> (T, T) {
       |                   - move occurs because `t` has type `T`, which does not implement the `Copy` trait
    ...
    LL |     (t, t)
       |      -  ^ value used here after move
       |      |
       |      value moved here
       |
    help: if `T` implemented `Clone`, you could clone the value
      --> $DIR/use_of_moved_value_copy_suggestions.rs:4:16
       |
    LL | fn duplicate_t<T>(t: T) -> (T, T) {
       |                ^ consider constraining this type parameter with `Clone`
    ...
    LL |     (t, t)
       |      - you could clone this value
    help: consider restricting type parameter `T`
       |
    LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) {
       |                 ++++++
    ```
    
    The `help` is new. On ADTs, we also extend the output with span labels:
    
    ```
    error[E0507]: cannot move out of static item `FOO`
      --> $DIR/issue-17718-static-move.rs:6:14
       |
    LL |     let _a = FOO;
       |              ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
       |
    note: if `Foo` implemented `Clone`, you could clone the value
      --> $DIR/issue-17718-static-move.rs:1:1
       |
    LL | struct Foo;
       | ^^^^^^^^^^ consider implementing `Clone` for this type
    ...
    LL |     let _a = FOO;
       |              --- you could clone this value
    help: consider borrowing here
       |
    LL |     let _a = &FOO;
       |              +
    ```
    estebank committed Apr 24, 2024
    Configuration menu
    Copy the full SHA
    d68f2a6 View commit details
    Browse the repository at this point in the history
  3. Suggest cloning captured binding in move closure

    ```
    error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
      --> $DIR/borrowck-move-by-capture.rs:9:29
       |
    LL |     let bar: Box<_> = Box::new(3);
       |         --- captured outer variable
    LL |     let _g = to_fn_mut(|| {
       |                        -- captured by this `FnMut` closure
    LL |         let _h = to_fn_once(move || -> isize { *bar });
       |                             ^^^^^^^^^^^^^^^^   ----
       |                             |                  |
       |                             |                  variable moved due to use in closure
       |                             |                  move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
       |                             `bar` is moved here
       |
    help: clone the value before moving it into the closure
       |
    LL ~         let value = bar.clone();
    LL ~         let _h = to_fn_once(move || -> isize { value });
       |
    ```
    estebank committed Apr 24, 2024
    Configuration menu
    Copy the full SHA
    ad9a5a5 View commit details
    Browse the repository at this point in the history