/// (b) it gives a way to separate this case from the remaining cases
/// for diagnostics.
pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
+ /// Span of the pattern in which this variable was bound.
+ pub pat_span: Span,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
impl_stable_hash_for!(struct self::VarBindingForm<'tcx> {
binding_mode,
opt_ty_info,
- opt_match_place
+ opt_match_place,
+ pat_span
});
mod binding_form_impl {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
+ pat_span: _,
}))) => true,
// FIXME: might be able to thread the distinction between
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
+ pat_span: _,
}))) => true,
Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
ty::BindByReference(..) => {
let let_span = self.tcx.hir.span(node_id);
let suggestion = suggest_ref_mut(self.tcx, let_span);
- if let Some((let_span, replace_str)) = suggestion {
+ if let Some(replace_str) = suggestion {
db.span_suggestion(
let_span,
"use a mutable reference instead",
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rustc::hir;
+use core::unicode::property::Pattern_White_Space;
use rustc::mir::*;
use rustc::ty;
use rustc_errors::DiagnosticBuilder;
// let (&x, &y) = (&String::new(), &String::new());
#[derive(Debug)]
enum GroupedMoveError<'tcx> {
- // Match place can't be moved from
+ // Place expression can't be moved from,
// e.g. match x[0] { s => (), } where x: &[String]
- MovesFromMatchPlace {
+ MovesFromPlace {
original_path: Place<'tcx>,
span: Span,
move_from: Place<'tcx>,
kind: IllegalMoveOriginKind<'tcx>,
binds_to: Vec<Local>,
},
- // Part of a pattern can't be moved from,
+ // Part of a value expression can't be moved from,
// e.g. match &String::new() { &x => (), }
- MovesFromPattern {
+ MovesFromValue {
original_path: Place<'tcx>,
span: Span,
move_from: MovePathIndex,
binds_to: Vec<Local>,
},
// Everything that isn't from pattern matching.
+ // FIXME(ashtneoi): I think this is only for moves into temporaries, as
+ // when returning a value. Clarification needed.
OtherIllegalMove {
original_path: Place<'tcx>,
span: Span,
opt_match_place: Some((ref opt_match_place, match_span)),
binding_mode: _,
opt_ty_info: _,
+ pat_span: _,
}))) = local_decl.is_user_variable
{
self.append_binding_error(
// Error with the match place
LookupResult::Parent(_) => {
for ge in &mut *grouped_errors {
- if let GroupedMoveError::MovesFromMatchPlace { span, binds_to, .. } = ge {
+ if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge {
if match_span == *span {
debug!("appending local({:?}) to list", bind_to);
if !binds_to.is_empty() {
} else {
(vec![bind_to], match_span)
};
- grouped_errors.push(GroupedMoveError::MovesFromMatchPlace {
+ grouped_errors.push(GroupedMoveError::MovesFromPlace {
span,
move_from: match_place.clone(),
original_path,
_ => unreachable!("Probably not unreachable..."),
};
for ge in &mut *grouped_errors {
- if let GroupedMoveError::MovesFromPattern {
+ if let GroupedMoveError::MovesFromValue {
span,
move_from: other_mpi,
binds_to,
}
}
debug!("found a new move error location");
- grouped_errors.push(GroupedMoveError::MovesFromPattern {
+ grouped_errors.push(GroupedMoveError::MovesFromValue {
span: match_span,
move_from: mpi,
original_path,
let (mut err, err_span) = {
let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind) =
match error {
- GroupedMoveError::MovesFromMatchPlace {
+ GroupedMoveError::MovesFromPlace {
span,
ref original_path,
ref kind,
..
} |
- GroupedMoveError::MovesFromPattern { span, ref original_path, ref kind, .. } |
+ GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } |
GroupedMoveError::OtherIllegalMove { span, ref original_path, ref kind } => {
(span, original_path, kind)
},
err: &mut DiagnosticBuilder<'a>,
span: Span,
) {
+ let snippet = self.tcx.sess.codemap().span_to_snippet(span).unwrap();
match error {
- GroupedMoveError::MovesFromMatchPlace {
+ GroupedMoveError::MovesFromPlace {
mut binds_to,
move_from,
..
} => {
- // Ok to suggest a borrow, since the target can't be moved from
- // anyway.
- if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
- match move_from {
- Place::Projection(ref proj)
- if self.suitable_to_remove_deref(proj, &snippet) =>
- {
+ let mut suggest_change_head_expr = false;
+ match move_from {
+ Place::Projection(box PlaceProjection {
+ elem: ProjectionElem::Deref,
+ ..
+ }) => {
+ // This is false for (e.g.) index expressions `a[b]`,
+ // which roughly desugar to `*Index::index(&a, b)` or
+ // `*IndexMut::index_mut(&mut a, b)`.
+ if snippet.starts_with('*') {
err.span_suggestion(
span,
"consider removing this dereference operator",
(&snippet[1..]).to_owned(),
);
- }
- _ => {
- err.span_suggestion(
- span,
- "consider using a reference instead",
- format!("&{}", snippet),
- );
+ suggest_change_head_expr = true;
}
}
-
- binds_to.sort();
- binds_to.dedup();
- for local in binds_to {
- let bind_to = &self.mir.local_decls[local];
- let binding_span = bind_to.source_info.span;
- err.span_label(
- binding_span,
- format!(
- "move occurs because {} has type `{}`, \
- which does not implement the `Copy` trait",
- bind_to.name.unwrap(),
- bind_to.ty
- ),
+ _ => {
+ err.span_suggestion(
+ span,
+ "consider using a reference instead",
+ format!("&{}", snippet),
);
+ suggest_change_head_expr = true;
}
}
+ binds_to.sort();
+ binds_to.dedup();
+ if !suggest_change_head_expr {
+ self.add_move_error_suggestions(err, &binds_to);
+ }
+ self.add_move_error_labels(err, &binds_to);
}
- GroupedMoveError::MovesFromPattern { mut binds_to, .. } => {
- // Suggest ref, since there might be a move in
- // another match arm
+ GroupedMoveError::MovesFromValue { mut binds_to, .. } => {
binds_to.sort();
binds_to.dedup();
- let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
- for (j, local) in binds_to.into_iter().enumerate() {
- let bind_to = &self.mir.local_decls[local];
- let binding_span = bind_to.source_info.span;
+ self.add_move_error_suggestions(err, &binds_to);
+ self.add_move_error_labels(err, &binds_to);
+ }
+ // No binding. Nothing to suggest.
+ GroupedMoveError::OtherIllegalMove { .. } => (),
+ }
+ }
- // Suggest ref mut when the user has already written mut.
- let ref_kind = match bind_to.mutability {
- Mutability::Not => "ref",
- Mutability::Mut => "ref mut",
- };
- if j == 0 {
- err.span_label(binding_span, format!("data moved here"));
+ fn add_move_error_suggestions(
+ &self,
+ err: &mut DiagnosticBuilder<'a>,
+ binds_to: &[Local],
+ ) {
+ for local in binds_to {
+ let bind_to = &self.mir.local_decls[*local];
+ if let Some(
+ ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ pat_span,
+ ..
+ }))
+ ) = bind_to.is_user_variable {
+ let pat_snippet = self
+ .tcx.sess.codemap()
+ .span_to_snippet(pat_span)
+ .unwrap();
+ if pat_snippet.starts_with('&') {
+ let pat_snippet = &pat_snippet[1..];
+ let suggestion;
+ if pat_snippet.starts_with("mut")
+ && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
+ {
+ suggestion = pat_snippet["mut".len()..].trim_left();
} else {
- err.span_label(binding_span, format!("... and here"));
- }
- match bind_to.name {
- Some(name) => {
- multipart_suggestion.push((binding_span,
- format!("{} {}", ref_kind, name)));
- }
- None => {
- err.span_label(
- span,
- format!("Local {:?} is not suitable for ref", bind_to),
- );
- }
+ suggestion = pat_snippet;
}
+ err.span_suggestion(
+ pat_span,
+ "consider removing this borrow operator",
+ suggestion.to_owned(),
+ );
}
- err.multipart_suggestion("to prevent move, use ref or ref mut",
- multipart_suggestion);
}
- // Nothing to suggest.
- GroupedMoveError::OtherIllegalMove { .. } => (),
}
}
- fn suitable_to_remove_deref(&self, proj: &PlaceProjection<'tcx>, snippet: &str) -> bool {
- let is_shared_ref = |ty: ty::Ty| match ty.sty {
- ty::TypeVariants::TyRef(.., hir::Mutability::MutImmutable) => true,
- _ => false,
- };
+ fn add_move_error_labels(
+ &self,
+ err: &mut DiagnosticBuilder<'a>,
+ binds_to: &[Local],
+ ) {
+ for (j, local) in binds_to.into_iter().enumerate() {
+ let bind_to = &self.mir.local_decls[*local];
+ let binding_span = bind_to.source_info.span;
- proj.elem == ProjectionElem::Deref && snippet.starts_with('*') && match proj.base {
- Place::Local(local) => {
- let local_decl = &self.mir.local_decls[local];
- // If this is a temporary, then this could be from an
- // overloaded * operator.
- local_decl.is_user_variable.is_some() && is_shared_ref(local_decl.ty)
+ if j == 0 {
+ err.span_label(binding_span, format!("data moved here"));
+ } else {
+ err.span_label(binding_span, format!("... and here"));
}
- Place::Promoted(_) => true,
- Place::Static(ref st) => is_shared_ref(st.ty),
- Place::Projection(ref proj) => match proj.elem {
- ProjectionElem::Field(_, ty) => is_shared_ref(ty),
- _ => false,
- },
+
+ err.span_note(
+ binding_span,
+ &format!(
+ "move occurs because {} has type `{}`, \
+ which does not implement the `Copy` trait",
+ bind_to.name.unwrap(),
+ bind_to.ty
+ ),
+ );
}
}
}
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByReference(_),
..
- })) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
+ })) => {
+ let pattern_span = local_decl.source_info.span;
+ suggest_ref_mut(self.tcx, pattern_span)
+ .map(|replacement| (pattern_span, replacement))
+ }
//
ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(),
let visibility_scope = visibility_scope.unwrap();
this.declare_binding(source_info, visibility_scope, mutability, name, mode,
num_patterns, var, ty, has_guard,
- opt_match_place.map(|(x, y)| (x.cloned(), y)));
+ opt_match_place.map(|(x, y)| (x.cloned(), y)),
+ patterns[0].span);
});
visibility_scope
}
var_id: NodeId,
var_ty: Ty<'tcx>,
has_guard: ArmHasGuard,
- opt_match_place: Option<(Option<Place<'tcx>>, Span)>)
+ opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
+ pat_span: Span)
{
debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
visibility_scope={:?}, source_info={:?})",
// Instead, just abandon providing diagnostic info.
opt_ty_info: None,
opt_match_place,
+ pat_span,
}))),
};
let for_arm_body = self.local_decls.push(local.clone());
binding_mode,
opt_ty_info,
opt_match_place: Some((Some(place.clone()), span)),
+ pat_span: span,
})))
};
self.var_indices.insert(var, LocalsForNode::One(local));
#![feature(try_trait)]
#![feature(unicode_internals)]
#![feature(step_trait)]
+#![feature(slice_concat_ext)]
#![recursion_limit="256"]
/// If possible, suggest replacing `ref` with `ref mut`.
pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>(
tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>,
- pattern_span: Span,
-) -> Option<(Span, String)> {
- let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap();
+ binding_span: Span,
+) -> Option<(String)> {
+ let hi_src = tcx.sess.codemap().span_to_snippet(binding_span).unwrap();
if hi_src.starts_with("ref")
&& hi_src["ref".len()..].starts_with(Pattern_White_Space)
{
let replacement = format!("ref mut{}", &hi_src["ref".len()..]);
- Some((pattern_span, replacement))
+ Some(replacement)
} else {
None
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+enum Either {
+ One(X),
+ Two(X),
+}
+
+struct X(Y);
+
+struct Y;
+
+pub fn main() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let r = &e;
+ let rm = &mut Either::One(X(Y));
+
+ let x = X(Y);
+ let mut xm = X(Y);
+
+ let s = &x;
+ let sm = &mut X(Y);
+
+ // --------
+
+ let X(_t) = *s;
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION s
+ if let Either::One(_t) = *r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION r
+ while let Either::One(_t) = *r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION r
+ match *r {
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION r
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match *r {
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION r
+ // (invalid but acceptable)
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ }
+
+ let X(_t) = *sm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION sm
+ if let Either::One(_t) = *rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION rm
+ while let Either::One(_t) = *rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION rm
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION rm
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION rm
+ // (invalid but acceptable)
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ }
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing this dereference operator
+ //~| SUGGESTION rm
+ // (invalid but acceptable)
+ Either::One(_t) => (),
+ Either::Two(ref mut _t) => (),
+ }
+
+ // --------
+
+ let &X(_t) = s;
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION X(_t)
+ if let &Either::One(_t) = r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ while let &Either::One(_t) = r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t)
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ | &Either::Two(_t) => (),
+ // TODO: would really like a suggestion here too
+ }
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &Either::Two(ref _t) => (),
+ }
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+ fn f1(&X(_t): &X) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION X(_t)
+
+ let &mut X(_t) = sm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION X(_t)
+ if let &mut Either::One(_t) = rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ while let &mut Either::One(_t) = rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::Two(_t)
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref _t) => (),
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref mut _t) => (),
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+ fn f2(&mut X(_t): &mut X) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION X(_t)
+
+ // --------
+
+ let &X(_t) = &x;
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION X(_t)
+ if let &Either::One(_t) = &e { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ while let &Either::One(_t) = &e { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t)
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ | &Either::Two(_t) => (),
+ // TODO: would really like a suggestion here too
+ }
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &Either::Two(ref _t) => (),
+ }
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+
+ let &mut X(_t) = &mut xm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION X(_t)
+ if let &mut Either::One(_t) = &mut em { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ while let &mut Either::One(_t) = &mut em { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t)
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ | &mut Either::Two(_t) => (),
+ // TODO: would really like a suggestion here too
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref _t) => (),
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref mut _t) => (),
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing this borrow operator
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+}
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:37:17
+ |
+LL | let X(_t) = *s;
+ | -- ^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing this dereference operator: `s`
+ | data moved here
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:37:11
+ |
+LL | let X(_t) = *s;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:41:30
+ |
+LL | if let Either::One(_t) = *r { }
+ | -- ^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing this dereference operator: `r`
+ | data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:41:24
+ |
+LL | if let Either::One(_t) = *r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:45:33
+ |
+LL | while let Either::One(_t) = *r { }
+ | -- ^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing this dereference operator: `r`
+ | data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:45:27
+ |
+LL | while let Either::One(_t) = *r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:49:11
+ |
+LL | match *r {
+ | ^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing this dereference operator: `r`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:53:21
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:56:11
+ |
+LL | match *r {
+ | ^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing this dereference operator: `r`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:61:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:65:17
+ |
+LL | let X(_t) = *sm;
+ | -- ^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing this dereference operator: `sm`
+ | data moved here
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:65:11
+ |
+LL | let X(_t) = *sm;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:69:30
+ |
+LL | if let Either::One(_t) = *rm { }
+ | -- ^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing this dereference operator: `rm`
+ | data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:69:24
+ |
+LL | if let Either::One(_t) = *rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:73:33
+ |
+LL | while let Either::One(_t) = *rm { }
+ | -- ^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing this dereference operator: `rm`
+ | data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:73:27
+ |
+LL | while let Either::One(_t) = *rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:77:11
+ |
+LL | match *rm {
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing this dereference operator: `rm`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:81:21
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:84:11
+ |
+LL | match *rm {
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing this dereference operator: `rm`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:89:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:92:11
+ |
+LL | match *rm {
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing this dereference operator: `rm`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:97:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:103:18
+ |
+LL | let &X(_t) = s;
+ | ------ ^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `X(_t)`
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:103:12
+ |
+LL | let &X(_t) = s;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:107:31
+ |
+LL | if let &Either::One(_t) = r { }
+ | ---------------- ^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:107:25
+ |
+LL | if let &Either::One(_t) = r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:111:34
+ |
+LL | while let &Either::One(_t) = r { }
+ | ---------------- ^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:111:28
+ |
+LL | while let &Either::One(_t) = r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:115:11
+ |
+LL | match r {
+ | ^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t)
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:117:22
+ |
+LL | &Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:123:11
+ |
+LL | match r {
+ | ^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:125:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:130:11
+ |
+LL | match r {
+ | ^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:132:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:142:22
+ |
+LL | let &mut X(_t) = sm;
+ | ---------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `X(_t)`
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:142:16
+ |
+LL | let &mut X(_t) = sm;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:146:35
+ |
+LL | if let &mut Either::One(_t) = rm { }
+ | -------------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:146:29
+ |
+LL | if let &mut Either::One(_t) = rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:150:38
+ |
+LL | while let &mut Either::One(_t) = rm { }
+ | -------------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:150:32
+ |
+LL | while let &mut Either::One(_t) = rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:154:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | -- data moved here
+...
+LL | &mut Either::Two(_t) => (),
+ | -- ... and here
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:156:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:159:26
+ |
+LL | &mut Either::Two(_t) => (),
+ | ^^
+help: consider removing this borrow operator
+ |
+LL | Either::One(_t) => (),
+ | ^^^^^^^^^^^^^^^
+help: consider removing this borrow operator
+ |
+LL | Either::Two(_t) => (),
+ | ^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:163:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:165:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:170:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:172:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:177:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:179:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:191:18
+ |
+LL | let &X(_t) = &x;
+ | ------ ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `X(_t)`
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:191:12
+ |
+LL | let &X(_t) = &x;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:195:31
+ |
+LL | if let &Either::One(_t) = &e { }
+ | ---------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:195:25
+ |
+LL | if let &Either::One(_t) = &e { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:199:34
+ |
+LL | while let &Either::One(_t) = &e { }
+ | ---------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:199:28
+ |
+LL | while let &Either::One(_t) = &e { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:203:11
+ |
+LL | match &e {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t)
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:205:22
+ |
+LL | &Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:211:11
+ |
+LL | match &e {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:213:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:218:11
+ |
+LL | match &e {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:220:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:226:22
+ |
+LL | let &mut X(_t) = &mut xm;
+ | ---------- ^^^^^^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `X(_t)`
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:226:16
+ |
+LL | let &mut X(_t) = &mut xm;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:230:35
+ |
+LL | if let &mut Either::One(_t) = &mut em { }
+ | -------------------- ^^^^^^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:230:29
+ |
+LL | if let &mut Either::One(_t) = &mut em { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:234:38
+ |
+LL | while let &mut Either::One(_t) = &mut em { }
+ | -------------------- ^^^^^^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:234:32
+ |
+LL | while let &mut Either::One(_t) = &mut em { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:238:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t)
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:240:26
+ |
+LL | &mut Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:246:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:248:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:253:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:255:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:260:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing this borrow operator: `Either::One(_t)`
+ |
+note: move occurs because _t has type `X`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:262:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:137:11
+ |
+LL | fn f1(&X(_t): &X) { }
+ | ^^^--^
+ | | |
+ | | data moved here
+ | cannot move out of borrowed content
+ | help: consider removing this borrow operator: `X(_t)`
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:137:14
+ |
+LL | fn f1(&X(_t): &X) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/dont-suggest-ref.rs:184:11
+ |
+LL | fn f2(&mut X(_t): &mut X) { }
+ | ^^^^^^^--^
+ | | |
+ | | data moved here
+ | cannot move out of borrowed content
+ | help: consider removing this borrow operator: `X(_t)`
+ |
+note: move occurs because _t has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/dont-suggest-ref.rs:184:18
+ |
+LL | fn f2(&mut X(_t): &mut X) { }
+ | ^^
+
+error: aborting due to 39 previous errors
+
+For more information about this error, try `rustc --explain E0507`.