about summary refs log tree commit diff
path: root/tests/ui/moves
AgeCommit message (Collapse)AuthorLines
2025-07-25Mention type that could be `Clone` but isn't in more casesEsteban Küber-0/+8
When encountering a moved value of a type that isn't `Clone` because of unmet obligations, but where all the unmet predicates reference crate-local types, mention them and suggest cloning, as we do in other cases already: ``` error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure --> f111.rs:14:25 | 13 | fn do_stuff(foo: Option<Foo>) { | --- captured outer variable 14 | require_fn_trait(|| async { | -- ^^^^^ `foo` is moved here | | | captured by this `Fn` closure 15 | if foo.map_or(false, |f| f.foo()) { | --- | | | variable moved due to use in coroutine | move occurs because `foo` has type `Option<Foo>`, which does not implement the `Copy` trait | note: if `Foo` implemented `Clone`, you could clone the value --> f111.rs:4:1 | 4 | struct Foo; | ^^^^^^^^^^ consider implementing `Clone` for this type ... 15 | if foo.map_or(false, |f| f.foo()) { | --- you could clone this value ```
2025-07-21Generalize logic pointing at binding moved into closureEsteban Küber-2/+4
Account not only for `fn` parameters when moving non-`Copy` values into closure, but also for let bindings. ``` 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); | --- ------ move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait | | | 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 | | | `bar` is moved here | help: consider cloning the value before moving it into the closure | LL ~ let value = bar.clone(); LL ~ let _h = to_fn_once(move || -> isize { value }); | ``` ``` error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9 | LL | let y = vec![format!("World")]; | - ---------------------- move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait | | | captured outer variable LL | call(|| { | -- captured by this `Fn` closure LL | y.into_iter(); | ^ ----------- `y` moved due to this method call | | | `y` is moved here | note: `into_iter` takes ownership of the receiver `self`, which moves `y` --> $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 | <Vec<String> as Clone>::clone(&y).into_iter(); | +++++++++++++++++++++++++++++++ + help: consider cloning the value if the performance cost is acceptable | LL | y.clone().into_iter(); | ++++++++ ```
2025-06-24Suggest cloning `Arc` moved into closureEsteban Küber-1/+117
``` error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-capture-clause-bad.rs:9:20 | LL | let x = "Hello world!".to_string(); | - move occurs because `x` has type `String`, which does not implement the `Copy` trait LL | thread::spawn(move || { | ------- value moved into closure here LL | println!("{}", x); | - variable moved due to use in closure LL | }); LL | println!("{}", x); | ^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value before moving it into the closure | LL ~ let value = x.clone(); LL ~ thread::spawn(move || { LL ~ println!("{}", value); | ```
2025-06-13Unimplement unsized_localsmejrs-73/+26
2025-06-03Use non-2015 edition paths in tests that do not test for their resolutionLukas Wirth-6/+6
This allows for testing these tests on editions other than 2015
2025-04-30compiletest: Make diagnostic kind mandatory on line annotationsVadim Petrochenkov-3/+3
2025-04-09Auto merge of #139555 - petrochenkov:errkind-ann, r=jieyouxubors-24/+24
UI tests: add missing diagnostic kinds where possible The subset of https://github.com/rust-lang/rust/pull/139427 that only adds diagnostic kinds to line annotations, without changing any other things in annotations or compiletest. After this only non-viral `NOTE`s and `HELP`s should be missing. r? `@jieyouxu`
2025-04-08UI tests: add missing diagnostic kinds where possibleVadim Petrochenkov-24/+24
2025-04-07compiletest: Avoid ignoring empty diagnostics in one more placeVadim Petrochenkov-7/+11
This catches some silly notes emitted by rustc, which should ideally be fixed
2025-03-19Fix next solver handling of shallow trait impl checkOli Scherer-2/+39
2025-03-19Demonstrate next-solver missing diagnosticOli Scherer-12/+33
2025-02-14Trim suggestion parts to the subset that is purely additiveMichael Goulet-1/+1
2025-02-14Use underline suggestions for purely 'additive' replacementsMichael Goulet-3/+2
2025-02-10Show diff suggestion format on verbose replacementEsteban Küber-6/+9
``` error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/attempted-access-non-fatal.rs:7:15 | LL | let _ = 2.l; | ^ | help: if intended to be a floating point literal, consider adding a `0` after the period and a `f64` suffix | LL - let _ = 2.l; LL + let _ = 2.0f64; | ```
2025-01-06Remove CallKind::Deref hack from UseSpansMichael Goulet-2/+2
It's not really necessary
2024-12-31Rollup merge of #133486 - dianne:fix-move-error-suggestion, r=estebankTrevor Gross-0/+38
borrowck diagnostics: make `add_move_error_suggestions` use the HIR rather than `SourceMap` This PR aims to fix #132806 by rewriting `add_move_error_suggestions`[^1]. Previously, it manually scanned the source text to find a leading `&`, which isn't always going to produce a correct result (see: that issue). Admittedly, the HIR visitor in this PR introduces a lot of boilerplate, but hopefully the logic at its core isn't too complicated (I go over it in the comments). I also tried a simpler version that didn't use a HIR visitor and suggested adding `ref` always, but the `&ref x` suggestions really didn't look good. As a bonus for the added complexity though, it's now able to produce nice `&`-removing suggestions in more cases. I tried to do this such that it avoids edition-dependent checks and its suggestions can be applied together with those from the match ergonomics 2024 migration lint. I haven't added tests for that since the details of match ergonomics 2024 are still being sorted out, but I can try if desired once that's finalized. [^1]: In brief, it fires on patterns where users try to bind by-value in such a way that moves out of a reference to a non-Copy type (including slice references with non-copy elements). The suggestions are to change the binding's mode to be by-reference, either by removing[^2] an enclosing `&`/`&mut` or adding `ref` to the binding. [^2]: Incidentally, I find the terminology of "consider removing the borrow" a bit confusing for a suggestion to remove a `&` pattern in order to make bindings borrow rather than move. I'm not sure what a good, concise way to explain that would be though, and that should go in a separate PR anyway.
2024-12-24Fix some typosfudancoder-5/+5
Signed-off-by: fudancoder <fudancoder@icloud.com.>
2024-12-07Mention type parameter in more cases and don't suggest ~const bound already ↵Esteban Küber-10/+10
there
2024-12-07Use trait name instead of full constraint in suggestion messageEsteban Küber-5/+5
``` help: consider restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) { | ++++++++++++++ ``` ``` help: consider restricting type parameter `V` with trait `Copy` | LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V { | +++++++++++++++++++ ```
2024-12-07reword trait bound suggestion message to include the boundsEsteban Küber-11/+11
2024-11-25`add_move_error_suggestions`: use a HIR visitor rather than `SourceMap`dianne-0/+38
2024-11-26tests: remove `//@ pretty-expanded` usages许杰友 Jieyou Xu (Joe)-1/+0
Done with ```bash sd '//@ pretty-expanded.*\n' '' tests/ui/**/*.rs ``` and ``` sd '//@pretty-expanded.*\n' '' tests/ui/**/*.rs ```
2024-11-17`suggest_borrow_generic_arg`: instantiate clauses properlydianne-4/+50
Fixes issue 133118. This also modifies `tests/ui/moves/moved-value-on-as-ref-arg.rs` to have more useful bounds on the tests for suggestions to borrow `Borrow` and `BorrowMut` arguments. With its old tautological `T: BorrowMut<T>` bound, this fix would make it suggest a shared borrow for that argument.
2024-11-13Suggest borrowing arguments in generic positions when trait bounds are satisfieddianne-121/+170
This subsumes the suggestions to borrow arguments with `AsRef`/`Borrow` bounds and those to borrow arguments with `Fn` and `FnMut` bounds. It works for other traits implemented on references as well, such as `std::io::Read`, `std::io::Write`, and `core::fmt::Write`. Incidentally, by making the logic for suggesting borrowing closures general, this removes some spurious suggestions to mutably borrow `FnMut` closures in assignments, as well as an unhelpful suggestion to add a `Clone` constraint to an `impl Fn` argument.
2024-11-13Use a common subdiagnostic format for generic borrowsdianne-16/+16
This is setup for unifing the logic for suggestions to borrow arguments in generic positions. As of this commit, it's still special cases for `AsRef`/`Borrow`-like traits and `Fn`-like traits.
2024-11-13Provide borrow-instead-of-move suggestions for calls of fn-like items from ↵dianne-0/+130
other crates This also downgrades its applicability to MaybeIncorrect. Its suggestion can result in ill-typed code when the type parameter it suggests providing a different generic argument for appears elsewhere in the callee's signature or predicates.
2024-07-26Peel off explicit (or implicit) deref before suggesting clone on move error ↵Michael Goulet-9/+0
in borrowck
2024-07-11Rollup merge of #124599 - estebank:issue-41708, r=wesleywiserMatthias Krüger-0/+153
Suggest borrowing on fn argument that is `impl AsRef` When encountering a move conflict, on an expression that is `!Copy` passed as an argument to an `fn` that is `impl AsRef`, suggest borrowing the expression. ``` error[E0382]: use of moved value: `bar` --> f204.rs:14:15 | 12 | let bar = Bar; | --- move occurs because `bar` has type `Bar`, which does not implement the `Copy` trait 13 | foo(bar); | --- value moved here 14 | let baa = bar; | ^^^ value used here after move | help: borrow the value to avoid moving it | 13 | foo(&bar); | + ``` Fix #41708
2024-06-20Fix `...` in multline code-skips in suggestionsEsteban Küber-2/+2
When we have long code skips, we write `...` in the line number gutter. For suggestions, we were "centering" the `...` with the line, but that was consistent with what we do in every other case.
2024-05-09Suggest borrowing on fn argument that is `impl AsRef`Esteban Küber-0/+153
When encountering a move conflict, on an expression that is `!Copy` passed as an argument to an `fn` that is `impl AsRef`, suggest borrowing the expression. ``` error[E0382]: use of moved value: `bar` --> f204.rs:14:15 | 12 | let bar = Bar; | --- move occurs because `bar` has type `Bar`, which does not implement the `Copy` trait 13 | foo(bar); | --- value moved here 14 | let baa = bar; | ^^^ value used here after move | help: borrow the value to avoid moving it | 13 | foo(&bar); | + ``` Fix #41708
2024-04-24Mention when type parameter could be `Clone`Esteban Küber-32/+115
``` 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-15Make array suggestions slightly more accurateMichael Goulet-2/+2
2024-04-15Use /* value */ as a placeholderMichael Goulet-8/+8
2024-04-13Auto merge of #122603 - estebank:clone-o-rama, r=lcnrbors-16/+77
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-12Better account for more cases involving closuresEsteban Küber-3/+10
2024-04-11Mention when the type of the moved value doesn't implement `Clone`Esteban Küber-6/+51
2024-04-11Silence redundant clone suggestionEsteban Küber-5/+20
2024-04-11Suggest `.clone()` in some move errorsEsteban Küber-21/+15
``` 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 `.clone()` when suggesting `<T as Clone>::clone`Esteban Küber-6/+6
2024-04-10Handle more cases of value suggestionsEsteban Küber-2/+2
2024-04-09Tweak value suggestions in `borrowck` and `hir_analysis`Esteban Küber-8/+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-03-17Add `HELP` to testEsteban Küber-6/+21
2024-03-17Point at `continue` and `break` that might be in the wrong placeEsteban Küber-10/+95
Sometimes move errors are because of a misplaced `continue`, but we didn't surface that anywhere. Now when there are more than one set of nested loops we show them out and point at the `continue` and `break` expressions within that might need to go elsewhere. ``` error[E0382]: use of moved value: `foo` --> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18 | LL | for foo in foos { | --- | | | this reinitialization might get skipped | move occurs because `foo` has type `String`, which does not implement the `Copy` trait ... LL | for bar in &bars { | ---------------- inside of this loop ... LL | baz.push(foo); | --- value moved here, in previous iteration of loop ... LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17 | LL | for foo in foos { | --------------- ... LL | for bar in &bars { | ---------------- ... LL | continue; | ^^^^^^^^ this `continue` advances the loop at line 33 help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = baz.push(foo); LL ~ for bar in &bars { LL | ... LL | if foo == *bar { LL ~ value; | help: consider cloning the value if the performance cost is acceptable | LL | baz.push(foo.clone()); | ++++++++ ``` Fix #92531.
2024-03-17Detect when move of `!Copy` value occurs within `loop` and should likely not ↵Esteban Küber-1/+256
be cloned When encountering a move error on a value within a loop of any kind, identify if the moved value belongs to a call expression that should not be cloned and avoid the semantically incorrect suggestion. Also try to suggest moving the call expression outside of the loop instead. ``` error[E0382]: use of moved value: `vec` --> $DIR/recreating-value-in-loop-condition.rs:6:33 | LL | let vec = vec!["one", "two", "three"]; | --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait LL | while let Some(item) = iter(vec).next() { | ----------------------------^^^-------- | | | | | value moved here, in previous iteration of loop | inside of this loop | note: consider changing this parameter type in function `iter` to borrow instead if owning the value isn't necessary --> $DIR/recreating-value-in-loop-condition.rs:1:17 | LL | fn iter<T>(vec: Vec<T>) -> impl Iterator<Item = T> { | ---- ^^^^^^ this parameter takes ownership of the value | | | in this function help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = iter(vec); LL ~ while let Some(item) = value.next() { | ``` We use the presence of a `break` in the loop that would be affected by the moved value as a heuristic for "shouldn't be cloned". Fix #121466.
2024-03-06compiletest: Add a `//@ needs-threads` directiveAlex Crichton-1/+1
This commit is extracted from #122036 and adds a new directive to the `compiletest` test runner, `//@ needs-threads`. This is intended to capture the need that a target must implement threading to execute a specific test, typically one that uses `std::thread`. This is primarily done for WebAssembly targets which currently do not have threads by default. This enables transitioning a lot of `//@ ignore-wasm*`-style ignores into a more self-documenting `//@ needs-threads` directive. Additionally the `wasm32-wasi-preview1-threads` target, for example, does actually have threads, but isn't tested in CI at this time. This change enables running these tests for that target, but not other wasm targets.
2024-02-16[AUTO-GENERATED] Migrate ui tests from `//` to `//@` directives许杰友 Jieyou Xu (Joe)-32/+32
2024-02-07Update testsr0cky-1/+14
2024-01-13Make InferCtxtExt::could_impl_trait less messed upMichael Goulet-2/+12
2023-12-10remove redundant importssurechen-2/+0
detects redundant imports that can be eliminated. for #117772 : In order to facilitate review and modification, split the checking code and removing redundant imports code into two PR.
2023-12-07recurse into refs when comparing tys for diagnosticsjyn-2/+2