Skip to content
Permalink
Browse files

Use structured suggestion when requiring `Copy` constraint in type param

  • Loading branch information
estebank committed Nov 20, 2019
1 parent f453d11 commit 02bc412d192549977a9244174cd871b394ce4960
@@ -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(&param_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(&param_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);
@@ -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

0 comments on commit 02bc412

Please sign in to comment.
You can’t perform that action at this time.