Auto merge of #66567 - estebank:suggest-copy, r=Centril

Use structured suggestion when requiring `Copy` constraint in type param
This commit is contained in:
bors 2019-11-29 00:23:23 +00:00
commit 861e96f2e9
13 changed files with 187 additions and 121 deletions

View File

@ -39,6 +39,7 @@ use syntax::ast;
use syntax::symbol::{sym, kw};
use syntax_pos::{DUMMY_SP, Span, ExpnKind, MultiSpan};
use rustc::hir::def_id::LOCAL_CRATE;
use syntax_pos::source_map::SourceMap;
use rustc_error_codes::*;
@ -1091,7 +1092,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
fn suggest_restricting_param_bound(
&self,
err: &mut DiagnosticBuilder<'_>,
mut err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::PolyTraitRef<'_>,
body_id: hir::HirId,
) {
@ -1102,7 +1103,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => return,
};
let mut suggest_restriction = |generics: &hir::Generics, msg| {
let suggest_restriction = |
generics: &hir::Generics,
msg,
err: &mut DiagnosticBuilder<'_>,
| {
let span = generics.where_clause.span_for_predicates_or_empty_place();
if !span.from_expansion() && span.desugaring_kind().is_none() {
err.span_suggestion(
@ -1132,7 +1137,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
kind: hir::TraitItemKind::Method(..), ..
}) if param_ty && self_ty == self.tcx.types.self_param => {
// Restricting `Self` for a single method.
suggest_restriction(&generics, "`Self`");
suggest_restriction(&generics, "`Self`", err);
return;
}
@ -1154,7 +1159,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
kind: hir::ItemKind::Impl(_, _, _, generics, ..), ..
}) if projection.is_some() => {
// Missing associated type bound.
suggest_restriction(&generics, "the associated type");
suggest_restriction(&generics, "the associated type", err);
return;
}
@ -1183,68 +1188,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
if param_ty => {
// Missing generic type parameter bound.
let restrict_msg = "consider further restricting this bound";
let param_name = self_ty.to_string();
for param in generics.params.iter().filter(|p| {
p.name.ident().as_str() == param_name
}) {
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,
restrict_msg,
// `impl CurrentTrait + MissingTrait`
format!("{} + {}", param.name.ident(), trait_ref),
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,
"consider restricting this bound",
format!("{}", trait_ref.to_predicate()),
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(),
&format!(
"consider further restricting type parameter `{}`",
param_name,
),
format!(", {}", trait_ref.to_predicate()),
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 = self.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, restrict_msg, format!(
"{} + ",
trait_ref.to_predicate(),
), Applicability::MachineApplicable);
} else {
err.span_label(param.span, &format!(
"consider adding a `where {}` bound",
trait_ref.to_predicate(),
));
}
}
let constraint = trait_ref.to_string();
if suggest_constraining_type_param(
generics,
&mut err,
&param_name,
&constraint,
self.tcx.sess.source_map(),
*span,
) {
return;
}
}
@ -2546,3 +2499,76 @@ impl ArgKind {
}
}
}
/// Suggest restricting a type param with a new bound.
pub fn suggest_constraining_type_param(
generics: &hir::Generics,
err: &mut DiagnosticBuilder<'_>,
param_name: &str,
constraint: &str,
source_map: &SourceMap,
span: Span,
) -> bool {
let restrict_msg = "consider further restricting this bound";
if let Some(param) = generics.params.iter().filter(|p| {
p.name.ident().as_str() == param_name
}).next() {
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,
restrict_msg,
// `impl CurrentTrait + MissingTrait`
format!("{} + {}", param_name, constraint),
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,
"consider restricting this bound",
format!("{}: {}", param_name, constraint),
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(),
&format!("consider further restricting type parameter `{}`", param_name),
format!(", {}: {}", param_name, constraint),
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 = 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,
restrict_msg,
format!("{}: {} + ", param_name, constraint),
Applicability::MachineApplicable,
);
} else {
err.span_label(
param.span,
&format!("consider adding a `where {}: {}` bound", param_name, constraint),
);
}
}
return true;
}
false
}

View File

@ -7,6 +7,7 @@ use rustc::mir::{
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, Ty};
use rustc::traits::error_reporting::suggest_constraining_type_param;
use rustc_data_structures::fx::FxHashSet;
use rustc_index::vec::Idx;
use rustc_errors::{Applicability, DiagnosticBuilder};
@ -231,13 +232,16 @@ 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();
suggest_constraining_type_param(
generics,
&mut err,
&param.name.as_str(),
"Copy",
tcx.sess.source_map(),
span,
);
}
let span = if let Some(local) = place.as_local() {
let decl = &self.body.local_decls[local];

View File

@ -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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `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 further restricting this bound: `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 restricting this bound: `B: Copy`
LL | lhs >> rhs;
| --- value moved here
LL | drop(lhs);

View File

@ -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 further restricting this bound: `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 further restricting this bound: `T: Copy +`
LL | x
| - value moved here
LL | +

View File

@ -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 further restricting this bound: `F: Copy +`
LL | f(1, 2);
| - value moved here
LL | f(1, 2);

View File

@ -7,7 +7,7 @@ LL | where B : for<'ccx> Bar<'ccx>
| ------------------- required by this bound in `want_bar_for_any_ccx`
...
LL | where B : Qux
| - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>`
| - help: consider further restricting type parameter `B`: `, B: for<'ccx> Bar<'ccx>`
...
LL | want_bar_for_any_ccx(b);
| ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`

View File

@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
--> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
|
LL | where F : Foo<'x>
| - help: consider further restricting type parameter `F`: `, for<'tcx> F: Foo<'tcx>`
| - help: consider further restricting type parameter `F`: `, F: for<'tcx> Foo<'tcx>`
...
LL | want_foo_for_any_tcx(f);
| ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
@ -16,7 +16,7 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
--> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
|
LL | where B : Bar<'x>
| - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>`
| - help: consider further restricting type parameter `B`: `, B: for<'ccx> Bar<'ccx>`
...
LL | want_bar_for_any_ccx(b);
| ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`

View 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);
}

View File

@ -1,3 +1,5 @@
// run-rustfix
pub trait Foo {
fn zero(self) -> Self;
}

View File

@ -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 further restricting this bound: `T: Copy +`
LL | if 0 == 1 {
LL | bar::bar(x.zero())
| - value moved here

View File

@ -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)

View File

@ -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 further restricting this bound: `F: Copy +`
LL | blk();
| --- value moved here
LL | blk();

View File

@ -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 further restricting this bound: `T: Copy +`
LL | !x;
| - value moved here
LL |