summary refs log tree commit diff
path: root/compiler/rustc_borrowck/src/diagnostics
AgeCommit message (Collapse)AuthorLines
2024-04-25review comment: rename methodEsteban Küber-2/+2
2024-04-25Check equivalence of indices in more casesEsteban Küber-1/+7
2024-04-25Don't suggest `split_at_mut` when the multiple borrows have the same indexEsteban Küber-2/+6
2024-04-25Mention `split_at_mut` when mixing mutability in indexing opsEsteban Küber-2/+17
Emit suggestion when encountering ```rust let a = &mut foo[0]; let b = &foo[1]; a.use_mut(); ```
2024-04-25Only suggest `split_at_mut` on indexing borrowck errors for std typesEsteban Küber-8/+22
2024-04-25Detect borrow error involving sub-slices and suggest `split_at_mut`Esteban Küber-16/+25
``` error[E0499]: cannot borrow `foo` as mutable more than once at a time --> $DIR/suggest-split-at-mut.rs:13:18 | LL | let a = &mut foo[..2]; | --- first mutable borrow occurs here LL | let b = &mut foo[2..]; | ^^^ second mutable borrow occurs here LL | a[0] = 5; | ---- first borrow later used here | = help: use `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices ``` Address most of #58792. For follow up work, we should emit a structured suggestion for cases where we can identify the exact `let (a, b) = foo.split_at_mut(2);` call that is needed.
2024-04-25Auto merge of #119650 - chenyukang:yukang-fix-118596-ref-mut, r=wesleywiserbors-1/+16
Suggest ref mut for pattern matching assignment Fixes #118596
2024-04-24Suggest cloning captured binding in `move` closureEsteban Küber-8/+136
``` 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 }); | ```
2024-04-24Mention when type parameter could be `Clone`Esteban Küber-8/+51
``` 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; | + ```
2024-04-24Modify `find_expr` from `Span` to better account for closuresEsteban Küber-4/+4
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 } => {}, | ++++++++ ```
2024-04-25Suggest ref mut for pattern matching assignmentyukang-1/+16
2024-04-23Rollup merge of #122598 - Nadrieril:full-derefpats, r=matthewjasperLeón Orell Valerian Liehr-11/+20
deref patterns: lower deref patterns to MIR This lowers deref patterns to MIR. This is a bit tricky because this is the first kind of pattern that requires storing a value in a temporary. Thanks to https://github.com/rust-lang/rust/pull/123324 false edges are no longer a problem. The thing I'm not confident about is the handling of fake borrows. This PR ignores any fake borrows inside a deref pattern. We are guaranteed to at least fake borrow the place of the first pointer value, which could be enough, but I'm not certain.
2024-04-20Add a non-shallow fake borrowNadrieril-11/+20
2024-04-19Stop taking ParamTy/ParamConst/EarlyParamRegion/AliasTy by refMichael Goulet-2/+2
2024-04-17Rename `BindingAnnotation` to `BindingMode`Jules Bertholet-8/+8
2024-04-15Make suggest_deref_closure_return more idiomatic/easier to understandMichael Goulet-73/+64
2024-04-16Rollup merge of #123989 - compiler-errors:type-dependent-def-id, r=oli-obkLeón Orell Valerian Liehr-26/+20
Just use `type_dependent_def_id` to figure out what the method is for an expr The calls to `lookup_method_for_diagnostic` are overkill. r? oli-obk
2024-04-16Rollup merge of #123016 - compiler-errors:no-type-var-origin, r=lcnrLeón Orell Valerian Liehr-5/+4
Remove `TypeVariableOriginKind` and `ConstVariableOriginKind` It's annoying to have to import `TypeVariableOriginKind` just to fill it with `MiscVariable` for almost every use. Every other usage other than `TypeParameterDefinition` wasn't even used -- I can see how it may have been useful once for debugging, but I do quite a lot of typeck debugging and I've never really needed it. So let's just remove it, and keep around the only useful thing which is the `DefId` of the param for `var_for_def`. This is based on #123006, which removed the special use of `TypeVariableOriginKind::OpaqueInference`, which I'm pretty sure I was the one that added. r? lcnr or re-roll to types
2024-04-15Rebase falloutMichael Goulet-5/+4
2024-04-15Just use type_dependent_def_id to figure out what the method is for an exprMichael Goulet-26/+20
2024-04-14Consolidate two copies of ty_kind_suggestionMichael Goulet-63/+2
2024-04-13Auto merge of #122603 - estebank:clone-o-rama, r=lcnrbors-62/+481
Detect borrow checker errors where `.clone()` would be an appropriate user action When a value is moved twice, suggest cloning the earlier move: ``` error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait --> $DIR/union-move.rs:49:18 | LL | move_out(x.f1_nocopy); | ^^^^^^^^^^^ | | | cannot move out of here | move occurs because `x.f1_nocopy` has type `ManuallyDrop<RefCell<i32>>`, which does not implement the `Copy` trait | help: consider cloning the value if the performance cost is acceptable | LL | move_out(x.f1_nocopy.clone()); | ++++++++ ``` When a value is borrowed by an `fn` call, consider if cloning the result of the call would be reasonable, and suggest cloning that, instead of the argument: ``` error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/variance-issue-20533.rs:53:14 | LL | let a = AffineU32(1); | - binding `a` declared here LL | let x = bat(&a); | -- borrow of `a` occurs here LL | drop(a); | ^ move out of `a` occurs here LL | drop(x); | - borrow later used here | help: consider cloning the value if the performance cost is acceptable | LL | let x = bat(&a).clone(); | ++++++++ ``` otherwise, suggest cloning the argument: ``` error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/variance-issue-20533.rs:59:14 | LL | let a = ClonableAffineU32(1); | - binding `a` declared here LL | let x = foo(&a); | -- borrow of `a` occurs here LL | drop(a); | ^ move out of `a` occurs here LL | drop(x); | - borrow later used here | help: consider cloning the value if the performance cost is acceptable | LL - let x = foo(&a); LL + let x = foo(a.clone()); | ``` This suggestion doesn't attempt to square out the types between what's cloned and what the `fn` expects, to allow the user to make a determination on whether to change the `fn` call or `fn` definition themselves. Special case move errors caused by `FnOnce`: ``` error[E0382]: use of moved value: `blk` --> $DIR/once-cant-call-twice-on-heap.rs:8:5 | LL | fn foo<F:FnOnce()>(blk: F) { | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait LL | blk(); | ----- `blk` moved due to this call LL | blk(); | ^^^ value used here after move | note: `FnOnce` closures can only be called once --> $DIR/once-cant-call-twice-on-heap.rs:6:10 | LL | fn foo<F:FnOnce()>(blk: F) { | ^^^^^^^^ `F` is made to be an `FnOnce` closure here LL | blk(); | ----- this value implements `FnOnce`, which causes it to be moved when called ``` Account for redundant `.clone()` calls in resulting suggestions: ``` error[E0507]: cannot move out of dereference of `S` --> $DIR/needs-clone-through-deref.rs:15:18 | LL | for _ in self.clone().into_iter() {} | ^^^^^^^^^^^^ ----------- value moved due to this method call | | | move occurs because value has type `Vec<usize>`, which does not implement the `Copy` trait | note: `into_iter` takes ownership of the receiver `self`, which moves value --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | for _ in <Vec<usize> as Clone>::clone(&self).into_iter() {} | ++++++++++++++++++++++++++++++ ~ ``` We use the presence of `&mut` values in a move error as a proxy for the user caring about side effects, so we don't emit a clone suggestion in that case: ``` error[E0505]: cannot move out of `s` because it is borrowed --> $DIR/borrowck-overloaded-index-move-index.rs:53:7 | LL | let mut s = "hello".to_string(); | ----- binding `s` declared here LL | let rs = &mut s; | ------ borrow of `s` occurs here ... LL | f[s] = 10; | ^ move out of `s` occurs here ... LL | use_mut(rs); | -- borrow later used here ``` We properly account for `foo += foo;` errors where we *don't* suggest `foo.clone() += foo;`, instead suggesting `foo += foo.clone();`. --- Each commit can be reviewed in isolation. There are some "cleanup" commits, but kept them separate in order to show *why* specific changes were being made, and their effect on tests' output. Fix #49693, CC #64167.
2024-04-12review commentsEsteban Küber-8/+36
Added comments and reworded messages
2024-04-12Better account for more cases involving closuresEsteban Küber-14/+36
2024-04-12Fix rebaseEsteban Küber-2/+2
2024-04-12Rollup merge of #123599 - matthiaskrgr:rm, r=cjgillotMatthias Krüger-1/+1
remove some things that do not need to be
2024-04-11Rollup merge of #123523 - estebank:issue-123414, r=BoxyUwUMatthias Krüger-35/+54
Account for trait/impl difference when suggesting changing argument from ref to mut ref Do not ICE when encountering a lifetime error involving an argument with an immutable reference of a method that differs from the trait definition. Fix #123414.
2024-04-11remove some things that do not need to beMatthias Krüger-1/+1
2024-04-11Mention when the type of the moved value doesn't implement `Clone`Esteban Küber-2/+13
2024-04-11Account for move error in the spread operator on struct literalsEsteban Küber-11/+107
We attempt to suggest an appropriate clone for move errors on expressions like `S { ..s }` where a field isn't `Copy`. If we can't suggest, we still don't emit the incorrect suggestion of `S { ..s }.clone()`. ``` error[E0509]: cannot move out of type `S<K>`, which implements the `Drop` trait --> $DIR/borrowck-struct-update-with-dtor.rs:28:19 | LL | let _s2 = S { a: 2, ..s0 }; | ^^^^^^^^^^^^^^^^ | | | cannot move out of here | move occurs because `s0.c` has type `K`, which does not implement the `Copy` trait | help: clone the value from the field instead of using the spread operator syntax | LL | let _s2 = S { a: 2, c: s0.c.clone(), ..s0 }; | +++++++++++++++++ ``` ``` error[E0509]: cannot move out of type `S<()>`, which implements the `Drop` trait --> $DIR/borrowck-struct-update-with-dtor.rs:20:19 | LL | let _s2 = S { a: 2, ..s0 }; | ^^^^^^^^^^^^^^^^ | | | cannot move out of here | move occurs because `s0.b` has type `B`, which does not implement the `Copy` trait | note: `B` doesn't implement `Copy` or `Clone` --> $DIR/borrowck-struct-update-with-dtor.rs:4:1 | LL | struct B; | ^^^^^^^^ help: if `B` implemented `Clone`, you could clone the value from the field instead of using the spread operator syntax | LL | let _s2 = S { a: 2, b: s0.b.clone(), ..s0 }; | +++++++++++++++++ ```
2024-04-11Better account for `FnOnce` in move errorsEsteban Küber-7/+72
``` error[E0382]: use of moved value: `blk` --> $DIR/once-cant-call-twice-on-heap.rs:8:5 | LL | fn foo<F:FnOnce()>(blk: F) { | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait LL | blk(); | ----- `blk` moved due to this call LL | blk(); | ^^^ value used here after move | note: `FnOnce` closures can only be called once --> $DIR/once-cant-call-twice-on-heap.rs:6:10 | LL | fn foo<F:FnOnce()>(blk: F) { | ^^^^^^^^ `F` is made to be an `FnOnce` closure here LL | blk(); | ----- this value implements `FnOnce`, which causes it to be moved when called ```
2024-04-11Account for assign binops in clone suggestionsEsteban Küber-2/+32
Explicitly look for `expr += other_expr;` and avoid suggesting `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
2024-04-11When possible, suggest cloning the result of a call instead of an argumentEsteban Küber-13/+92
``` error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/variance-issue-20533.rs:28:14 | LL | let a = AffineU32(1); | - binding `a` declared here LL | let x = foo(&a); | -- borrow of `a` occurs here LL | drop(a); | ^ move out of `a` occurs here LL | drop(x); | - borrow later used here | help: consider cloning the value if the performance cost is acceptable | LL | let x = foo(&a).clone(); | ++++++++ ```
2024-04-11Do not recomment cloning explicit `&mut` expressionsEsteban Küber-0/+5
2024-04-11Fix accuracy of `T: Clone` check in suggestionEsteban Küber-0/+1
2024-04-11Remove unnecessary argument from `suggest_cloning`Esteban Küber-21/+9
2024-04-11Silence redundant clone suggestionEsteban Küber-0/+5
2024-04-11More move error suggestions to cloneEsteban Küber-0/+4
``` error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure --> $DIR/issue-87456-point-to-closure.rs:10:28 | LL | let val = String::new(); | --- captured outer variable LL | LL | take_mut(|| { | -- captured by this `FnMut` closure LL | LL | let _foo: String = val; | ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait | help: consider borrowing here | LL | let _foo: String = &val; | + help: consider cloning the value if the performance cost is acceptable | LL | let _foo: String = val.clone(); | ++++++++ ```
2024-04-11Suggest `.clone()` in some move errorsEsteban Küber-0/+10
``` error[E0507]: cannot move out of `*x` which is behind a shared reference --> $DIR/borrowck-fn-in-const-a.rs:6:16 | LL | return *x | ^^ move occurs because `*x` has type `String`, which does not implement the `Copy` trait | help: consider cloning the value if the performance cost is acceptable | LL - return *x LL + return x.clone() | ```
2024-04-11Account for unops when suggesting cloningEsteban Küber-19/+24
2024-04-11Suggest `.clone()` when moved while borrowedEsteban Küber-17/+56
2024-04-11Account for `.clone()` when suggesting `<T as Clone>::clone`Esteban Küber-2/+33
2024-04-11Rollup merge of #123704 - estebank:diag-changes, r=compiler-errorsMatthias Krüger-26/+70
Tweak value suggestions in `borrowck` and `hir_analysis` Unify the output of `suggest_assign_value` and `ty_kind_suggestion`. Ideally we'd make these a single function, but doing so would likely require modify the crate dependency tree.
2024-04-10Handle more cases of "values to suggest" given a typeEsteban Küber-3/+16
Add handling for `String`, `Box`, `Option` and `Result`.
2024-04-10Handle more cases of value suggestionsEsteban Küber-18/+51
2024-04-10Use trait solver to answer questions instead of manually writing a trait solverOli Scherer-79/+22
2024-04-09Tweak value suggestions in `borrowck` and `hir_analysis`Esteban Küber-10/+8
Unify the output of `suggest_assign_value` and `ty_kind_suggestion`. Ideally we'd make these a single function, but doing so would likely require modify the crate dependency tree.
2024-04-06Account for trait/impl difference when suggesting changing argument from ref ↵Esteban Küber-35/+54
to mut ref Do not ICE when encountering a lifetime error involving an argument with an immutable reference of a method that differs from the trait definition. Fix #123414.
2024-04-05Provide suggestion to dereference closure tail if appropriateEsteban Küber-4/+210
When encoutnering a case like ```rust //@ run-rustfix use std::collections::HashMap; fn main() { let vs = vec![0, 0, 1, 1, 3, 4, 5, 6, 3, 3, 3]; let mut counts = HashMap::new(); for num in vs { let count = counts.entry(num).or_insert(0); *count += 1; } let _ = counts.iter().max_by_key(|(_, v)| v); ``` produce the following suggestion ``` error: lifetime may not live long enough --> $DIR/return-value-lifetime-error.rs:13:47 | LL | let _ = counts.iter().max_by_key(|(_, v)| v); | ------- ^ returning this value requires that `'1` must outlive `'2` | | | | | return type of closure is &'2 &i32 | has type `&'1 (&i32, &i32)` | help: dereference the return value | LL | let _ = counts.iter().max_by_key(|(_, v)| **v); | ++ ``` Fix #50195.
2024-03-30Stop calling visitors VMichael Goulet-3/+12