mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-12 06:53:05 +00:00
Use structured suggestion when requiring Copy
constraint in type param
This commit is contained in:
parent
f453d1127d
commit
02bc412d19
@ -231,12 +231,64 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if let ty::Param(param_ty) = ty.kind {
|
||||
let tcx = self.infcx.tcx;
|
||||
let generics = tcx.generics_of(self.mir_def_id);
|
||||
let def_id = generics.type_param(¶m_ty, tcx).def_id;
|
||||
if let Some(sp) = tcx.hir().span_if_local(def_id) {
|
||||
err.span_label(
|
||||
sp,
|
||||
"consider adding a `Copy` constraint to this type argument",
|
||||
);
|
||||
let param = generics.type_param(¶m_ty, tcx);
|
||||
let generics = tcx.hir().get_generics(self.mir_def_id).unwrap();
|
||||
let msg = "consider adding a `Copy` constraint to this type argument";
|
||||
for param in generics.params.iter().filter(|p| {
|
||||
p.name.ident().as_str() == param.name.as_str()
|
||||
}) {
|
||||
let param_name = param.name.ident().as_str();
|
||||
if param_name.starts_with("impl ") {
|
||||
// `impl Trait` in argument:
|
||||
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
msg,
|
||||
// `impl CurrentTrait + MissingTrait`
|
||||
format!("{} + Copy", param_name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if generics.where_clause.predicates.is_empty() &&
|
||||
param.bounds.is_empty()
|
||||
{
|
||||
// If there are no bounds whatsoever, suggest adding a constraint
|
||||
// to the type parameter:
|
||||
// `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
msg,
|
||||
format!("{}: Copy", param_name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if !generics.where_clause.predicates.is_empty() {
|
||||
// There is a `where` clause, so suggest expanding it:
|
||||
// `fn foo<T>(t: T) where T: Debug {}` →
|
||||
// `fn foo<T>(t: T) where T: Debug, T: Trait {}`
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span().unwrap().shrink_to_hi(),
|
||||
msg,
|
||||
format!(", {}: Copy", param_name),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
// If there is no `where` clause lean towards constraining to the
|
||||
// type parameter:
|
||||
// `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||
// `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
|
||||
let sp = param.span.with_hi(span.hi());
|
||||
let span = tcx.sess.source_map()
|
||||
.span_through_char(sp, ':');
|
||||
if sp != param.span && sp != span {
|
||||
// Only suggest if we have high certainty that the span
|
||||
// covers the colon in `foo<T: Trait>`.
|
||||
err.span_suggestion(span, msg, format!(
|
||||
"{}: Copy +",
|
||||
param_name,
|
||||
), Applicability::MachineApplicable);
|
||||
} else {
|
||||
err.span_label(param.span, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let span = if let Some(local) = place.as_local() {
|
||||
|
@ -2,9 +2,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:7:10
|
||||
|
|
||||
LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs + rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -16,7 +16,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs + rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -27,9 +27,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:13:10
|
||||
|
|
||||
LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs - rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -41,7 +41,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs - rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -52,9 +52,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:19:10
|
||||
|
|
||||
LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs * rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -66,7 +66,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs * rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -77,9 +77,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:25:10
|
||||
|
|
||||
LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs / rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -91,7 +91,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs / rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -102,9 +102,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:31:10
|
||||
|
|
||||
LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs % rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -116,7 +116,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs % rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -127,9 +127,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:37:10
|
||||
|
|
||||
LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs & rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -141,7 +141,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs & rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -152,9 +152,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:43:10
|
||||
|
|
||||
LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs | rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -166,7 +166,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs | rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -177,9 +177,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:49:10
|
||||
|
|
||||
LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs ^ rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -191,7 +191,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs ^ rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -202,9 +202,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:55:10
|
||||
|
|
||||
LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs << rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -216,7 +216,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs << rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -227,9 +227,9 @@ error[E0382]: use of moved value: `lhs`
|
||||
--> $DIR/binop-consume-args.rs:61:10
|
||||
|
|
||||
LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
|
||||
LL | lhs >> rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
@ -241,7 +241,7 @@ error[E0382]: use of moved value: `rhs`
|
||||
LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
|
||||
| - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `B: Copy`
|
||||
LL | lhs >> rhs;
|
||||
| --- value moved here
|
||||
LL | drop(lhs);
|
||||
|
@ -2,9 +2,9 @@ error[E0382]: use of moved value: `x`
|
||||
--> $DIR/binop-move-semantics.rs:8:5
|
||||
|
|
||||
LL | fn double_move<T: Add<Output=()>>(x: T) {
|
||||
| - - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| -- - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
|
||||
LL | x
|
||||
| - value moved here
|
||||
LL | +
|
||||
@ -15,9 +15,9 @@ error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/binop-move-semantics.rs:14:5
|
||||
|
|
||||
LL | fn move_then_borrow<T: Add<Output=()> + Clone>(x: T) {
|
||||
| - - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| -- - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
|
||||
LL | x
|
||||
| - value moved here
|
||||
LL | +
|
||||
|
@ -20,9 +20,9 @@ error[E0382]: use of moved value: `f`
|
||||
--> $DIR/borrowck-unboxed-closures.rs:12:5
|
||||
|
|
||||
LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
|
||||
| - - move occurs because `f` has type `F`, which does not implement the `Copy` trait
|
||||
| -- - move occurs because `f` has type `F`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `F: Copy +`
|
||||
LL | f(1, 2);
|
||||
| - value moved here
|
||||
LL | f(1, 2);
|
||||
|
34
src/test/ui/issues/issue-34721.fixed
Normal file
34
src/test/ui/issues/issue-34721.fixed
Normal file
@ -0,0 +1,34 @@
|
||||
// run-rustfix
|
||||
|
||||
pub trait Foo {
|
||||
fn zero(self) -> Self;
|
||||
}
|
||||
|
||||
impl Foo for u32 {
|
||||
fn zero(self) -> u32 { 0u32 }
|
||||
}
|
||||
|
||||
pub mod bar {
|
||||
pub use Foo;
|
||||
pub fn bar<T: Foo>(x: T) -> T {
|
||||
x.zero()
|
||||
}
|
||||
}
|
||||
|
||||
mod baz {
|
||||
use bar;
|
||||
use Foo;
|
||||
pub fn baz<T: Copy + Foo>(x: T) -> T {
|
||||
if 0 == 1 {
|
||||
bar::bar(x.zero())
|
||||
} else {
|
||||
x.zero()
|
||||
};
|
||||
x.zero()
|
||||
//~^ ERROR use of moved value
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = baz::baz(0u32);
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
// run-rustfix
|
||||
|
||||
pub trait Foo {
|
||||
fn zero(self) -> Self;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/issue-34721.rs:25:9
|
||||
--> $DIR/issue-34721.rs:27:9
|
||||
|
|
||||
LL | pub fn baz<T: Foo>(x: T) -> T {
|
||||
| - - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| -- - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
|
||||
LL | if 0 == 1 {
|
||||
LL | bar::bar(x.zero())
|
||||
| - value moved here
|
||||
|
@ -11,9 +11,9 @@ error[E0382]: borrow of moved value: `f`
|
||||
--> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5
|
||||
|
|
||||
LL | fn conspirator<F>(mut f: F) where F: FnMut(&mut R, bool) {
|
||||
| - ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| ----- - help: consider further restricting type parameter `F`: `, F: Copy`
|
||||
| |
|
||||
| move occurs because `f` has type `F`, which does not implement the `Copy` trait
|
||||
LL | let mut r = R {c: Box::new(f)};
|
||||
| - value moved here
|
||||
LL | f(&mut r, false)
|
||||
|
@ -2,9 +2,9 @@ error[E0382]: use of moved value: `blk`
|
||||
--> $DIR/once-cant-call-twice-on-heap.rs:9:5
|
||||
|
|
||||
LL | fn foo<F:FnOnce()>(blk: F) {
|
||||
| - --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
|
||||
| -- --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `F: Copy +`
|
||||
LL | blk();
|
||||
| --- value moved here
|
||||
LL | blk();
|
||||
|
@ -2,9 +2,9 @@ error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/unop-move-semantics.rs:8:5
|
||||
|
|
||||
LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
|
||||
| - - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| -- - move occurs because `x` has type `T`, which does not implement the `Copy` trait
|
||||
| |
|
||||
| consider adding a `Copy` constraint to this type argument
|
||||
| help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
|
||||
LL | !x;
|
||||
| - value moved here
|
||||
LL |
|
||||
|
Loading…
Reference in New Issue
Block a user