-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Conversation
r? @nnethercote rustbot has assigned @nnethercote. Use |
find_expr
from Span
to better account for closuresce141f8
to
a8c7820
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the first commit message, "where declared" should be "were declared".
LL | let x = var; | ||
| --- you could clone this value | ||
|
||
error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the compiler is totally inconsistent about "a FnMut
" vs "an FnMut
" :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which one should we use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current split suggests that people say "fun mut" and "eff en mut" equally, so I don't think there's a clear answer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll move towards a FnMut
(in a separate PR) because making every place where we talk about trait names to be specialized based on the language rules of the actual name of the trait would be a headache, whereas moving in the other direction is just a handful of static strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just saw this in compiler/rustc_ast/src/ast.rs
, which agrees with the use of "a":
impl ItemKind {
pub fn article(&self) -> &'static str {
use ItemKind::*;
match self {
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
| Delegation(..) => "a",
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
}
}
I am ambivalent about the middle commit. There are a lot of extra suggestions to implement |
We already suggest making the type param
to
Whether this is the right fix is highly dependent on what the user is trying to accomplish. Sadly we can't provide a good suggestion for every case (which is why it's a note and not a suggestion), but I tend to lean towards "too much information" over "too little information". Too much text can be overwhelming, but not enough text can leave people to fend for themselves with no guidance at all. What do you think? |
a8c7820
to
17a27e8
Compare
Ok, you are way deeper in this stuff than I am so I can live with that explanation. r=me once the commit message typo is fixed and the extra comment added. |
I don't intend to push through my changes without agreement, I can be wrong or miss something! :)
done and done @bors r+ |
Provide more context and suggestions in borrowck errors involving closures Start pointing to where bindings where 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 } => {}, | ++++++++ ``` 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; | + ``` 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 1 | LL ~ let value = bar.clone(); LL ~ let _h = to_fn_once(move || -> isize { value }); | ```
@bors r- |
17a27e8
to
2f29f78
Compare
rebased and fixed @bors r=nnethercote |
…cote Provide more context and suggestions in borrowck errors involving closures Start pointing to where bindings where 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 } => {}, | ++++++++ ``` 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; | + ``` 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 1 | LL ~ let value = bar.clone(); LL ~ let _h = to_fn_once(move || -> isize { value }); | ```
Rollup of 6 pull requests Successful merges: - rust-lang#122500 (delegation: Support renaming, and async, const, extern "ABI" and C-variadic functions) - rust-lang#123316 (Test `#[unix_sigpipe = "inherit"]` with both `SIG_DFL` and `SIG_IGN`) - rust-lang#124136 (Provide more context and suggestions in borrowck errors involving closures) - rust-lang#124280 (Port repr128-dwarf run-make test to rmake) - rust-lang#124282 (windows fill_utf16_buf: explain the expected return value) - rust-lang#124308 (Add diagnostic item for `std::iter::Enumerate`) r? `@ghost` `@rustbot` modify labels: rollup
Needs another rebase. |
Rollup of 5 pull requests Successful merges: - rust-lang#122500 (delegation: Support renaming, and async, const, extern "ABI" and C-variadic functions) - rust-lang#123316 (Test `#[unix_sigpipe = "inherit"]` with both `SIG_DFL` and `SIG_IGN`) - rust-lang#123794 (More DefineOpaqueTypes::Yes) - rust-lang#124282 (windows fill_utf16_buf: explain the expected return value) - rust-lang#124308 (Add diagnostic item for `std::iter::Enumerate`) Failed merges: - rust-lang#124136 (Provide more context and suggestions in borrowck errors involving closures) r? `@ghost` `@rustbot` modify labels: rollup
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 } => {}, | ++++++++ ```
``` 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; | + ```
``` 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 }); | ```
2f29f78
to
ad9a5a5
Compare
@bors r=nnethercote |
☀️ Test successful - checks-actions |
Finished benchmarking commit (cb3752d): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)This benchmark run did not return any relevant results for this metric. CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 672.592s -> 673.228s (0.09%) |
Start pointing to where bindings where declared when they are captured in closures:
Suggest cloning in more cases involving closures:
Mention when type parameter could be Clone
The
help
is new. On ADTs, we also extend the output with span labels:Suggest cloning captured binding in move closure