]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #53147 - ashtneoi:dont-suggest-ref, r=estebank
authorbors <bors@rust-lang.org>
Thu, 16 Aug 2018 08:45:32 +0000 (08:45 +0000)
committerbors <bors@rust-lang.org>
Thu, 16 Aug 2018 08:45:32 +0000 (08:45 +0000)
For move errors, suggest match ergonomics instead of `ref`

Partially fixes issue #52423. Also makes errors and suggestions more consistent between move-from-place and move-from-value errors.

Limitations:
- Only the first pattern in a match arm can have a "consider removing this borrow operator" suggestion.
- Suggestions don't always compile as-is (see the TODOs in the test for details).

Sorry for the really long test. I wanted to make sure I handled every case I could think of, and it turned out there were a lot of them.

Questions:
- Is there any particular applicability I should set on those suggestions?
- Are the notes about the `Copy` trait excessive?

49 files changed:
src/librustc/mir/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/util/mod.rs
src/test/ui/E0508-fail.ast.nll.stderr [new file with mode: 0644]
src/test/ui/E0508-fail.mir.stderr
src/test/ui/E0508.nll.stderr [new file with mode: 0644]
src/test/ui/access-mode-in-closures.nll.stderr
src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr
src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr
src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr
src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.nll.stderr
src/test/ui/borrowck/borrowck-move-in-irrefut-pat.mir.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.nll.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.nll.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
src/test/ui/borrowck/issue-51415.nll.stderr
src/test/ui/by-move-pattern-binding.nll.stderr
src/test/ui/check-static-values-constraints.nll.stderr
src/test/ui/codemap_tests/overlapping_spans.nll.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.nll.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.nll.stderr
src/test/ui/error-codes/E0509.nll.stderr [new file with mode: 0644]
src/test/ui/issues/issue-12567.nll.stderr
src/test/ui/issues/issue-17718-static-move.nll.stderr [new file with mode: 0644]
src/test/ui/issues/issue-20801.nll.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.nll.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.nll.stderr
src/test/ui/moves/move-out-of-slice-1.nll.stderr
src/test/ui/moves/moves-based-on-type-block-bad.nll.stderr
src/test/ui/nll/cannot-move-block-spans.nll.stderr
src/test/ui/nll/move-errors.stderr
src/test/ui/std-uncopyable-atomics.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/simple.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/simple.stderr [new file with mode: 0644]
src/tools/compiletest/src/json.rs

index dae5709ba114a3721f86bdb41ee2fcb9ae1594e7..8ceff303774b596a265af6a1dfac05a09589914c 100644 (file)
@@ -429,8 +429,8 @@ pub enum BorrowKind {
 
     /// Data must be immutable but not aliasable.  This kind of borrow
     /// cannot currently be expressed by the user and is used only in
-    /// implicit closure bindings. It is needed when you the closure
-    /// is borrowing or mutating a mutable referent, e.g.:
+    /// implicit closure bindings. It is needed when the closure is
+    /// borrowing or mutating a mutable referent, e.g.:
     ///
     ///    let x: &mut isize = ...;
     ///    let y = || *x += 5;
@@ -443,7 +443,7 @@ pub enum BorrowKind {
     ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
     ///
-    /// This is then illegal because you cannot mutate a `&mut` found
+    /// This is then illegal because you cannot mutate an `&mut` found
     /// in an aliasable location. To solve, you'd have to translate with
     /// an `&mut` borrow:
     ///
@@ -523,6 +523,8 @@ pub struct VarBindingForm<'tcx> {
     /// (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)]
@@ -540,7 +542,8 @@ pub enum BindingForm<'tcx> {
 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 {
@@ -673,7 +676,7 @@ pub struct LocalDecl<'tcx> {
     /// ROOT SCOPE
     ///  │{ argument x: &str }
     ///  │
-    ///  │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes
+    ///  │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes
     ///  │ │                        // in practice because I'm lazy.
     ///  │ │
     ///  │ │← x.source_info.scope
@@ -710,6 +713,7 @@ pub fn can_be_made_mutable(&self) -> bool {
                 binding_mode: ty::BindingMode::BindByValue(_),
                 opt_ty_info: _,
                 opt_match_place: _,
+                pat_span: _,
             }))) => true,
 
             // FIXME: might be able to thread the distinction between
@@ -729,6 +733,7 @@ pub fn is_nonref_binding(&self) -> bool {
                 binding_mode: ty::BindingMode::BindByValue(_),
                 opt_ty_info: _,
                 opt_match_place: _,
+                pat_span: _,
             }))) => true,
 
             Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
@@ -906,7 +911,7 @@ pub enum TerminatorKind<'tcx> {
 
     /// Drop the Place and assign the new value over it. This ensures
     /// that the assignment to `P` occurs *even if* the destructor for
-    /// place unwinds. Its semantics are best explained by by the
+    /// place unwinds. Its semantics are best explained by the
     /// elaboration:
     ///
     /// ```
index 098149c36ce435f74f6d253a14914552650c6fcd..5b08400eb112d05ddc56fe37aca367d0eb61391c 100644 (file)
@@ -1235,7 +1235,7 @@ fn note_immutability_blame(&self,
                     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",
index d3524e841b223d93d3b927a149ce006a84d5efdb..56ca4db098f87217f9534118238e08b1f3956a38 100644 (file)
@@ -8,7 +8,7 @@
 // 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,
@@ -119,6 +119,7 @@ fn append_to_grouped_errors(
                         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(
@@ -155,7 +156,7 @@ fn append_binding_error(
         statement_span: Span,
     ) {
         debug!(
-            "append_to_grouped_errors(match_place={:?}, match_span={:?})",
+            "append_binding_error(match_place={:?}, match_span={:?})",
             match_place, match_span
         );
 
@@ -166,7 +167,7 @@ fn 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() {
@@ -184,7 +185,7 @@ fn append_binding_error(
                 } else {
                     (vec![bind_to], match_span)
                 };
-                grouped_errors.push(GroupedMoveError::MovesFromMatchPlace {
+                grouped_errors.push(GroupedMoveError::MovesFromPlace {
                     span,
                     move_from: match_place.clone(),
                     original_path,
@@ -200,7 +201,7 @@ fn append_binding_error(
                     _ => 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,
@@ -215,7 +216,7 @@ fn append_binding_error(
                     }
                 }
                 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,
@@ -230,13 +231,13 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
         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)
                     },
@@ -331,111 +332,140 @@ fn add_move_hints(
         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) =>
-                        {
-                            err.span_suggestion(
-                                span,
-                                "consider removing this dereference operator",
-                                (&snippet[1..]).to_owned(),
-                            );
-                        }
-                        _ => {
-                            err.span_suggestion(
-                                span,
-                                "consider using a reference instead",
-                                format!("&{}", snippet),
-                            );
-                        }
-                    }
-
-                    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
-                            ),
-                        );
-                    }
+                let try_remove_deref = match move_from {
+                    Place::Projection(box PlaceProjection {
+                        elem: ProjectionElem::Deref,
+                        ..
+                    }) => true,
+                    _ => false,
+                };
+                if try_remove_deref && snippet.starts_with('*') {
+                    // The snippet doesn't start with `*` in (e.g.) index
+                    // expressions `a[b]`, which roughly desugar to
+                    // `*Index::index(&a, b)` or
+                    // `*IndexMut::index_mut(&mut a, b)`.
+                    err.span_suggestion(
+                        span,
+                        "consider removing the `*`",
+                        snippet[1..].to_owned(),
+                    );
+                } else {
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                    );
                 }
+
+                binds_to.sort();
+                binds_to.dedup();
+                self.add_move_error_details(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_details(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],
+    ) {
+        let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+        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..].trim_left();
+                    let suggestion;
+                    let to_remove;
+                    if pat_snippet.starts_with("mut")
+                        && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
+                    {
+                        suggestion = pat_snippet["mut".len()..].trim_left();
+                        to_remove = "&mut";
                     } 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;
+                        to_remove = "&";
                     }
+                    suggestions.push((
+                        pat_span,
+                        to_remove,
+                        suggestion.to_owned(),
+                    ));
                 }
-                err.multipart_suggestion("to prevent move, use ref or ref mut",
-                                         multipart_suggestion);
             }
-            // Nothing to suggest.
-            GroupedMoveError::OtherIllegalMove { .. } => (),
+        }
+        suggestions.sort_unstable_by_key(|&(span, _, _)| span);
+        suggestions.dedup_by_key(|&mut (span, _, _)| span);
+        for (span, to_remove, suggestion) in suggestions {
+            err.span_suggestion(
+                span,
+                &format!("consider removing the `{}`", to_remove),
+                suggestion
+            );
         }
     }
 
-    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_details(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        binds_to: &[Local],
+    ) {
+        let mut noncopy_var_spans = Vec::new();
+        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,
-            },
+
+            if binds_to.len() == 1 {
+                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
+                    ),
+                );
+            } else {
+                noncopy_var_spans.push(binding_span);
+            }
+        }
+
+        if binds_to.len() > 1 {
+            err.span_note(
+                noncopy_var_spans,
+                "move occurs because these variables have types that \
+                    don't implement the `Copy` trait",
+            );
         }
     }
 }
index 283cccd51174a1bbe81e32f8c8def62fb5f3805f..f11135fc026f53acd940600a43d226a733416c30 100644 (file)
@@ -329,7 +329,11 @@ pub(super) fn report_mutability_error(
                     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!(),
index 6b6ec749bcbe6efd1124d6f529264564a4aab661..b317bb7cff0e3c9a6e0b720f0dd0b2a63e1123f9 100644 (file)
@@ -321,9 +321,10 @@ pub fn place_into_pattern(&mut self,
         block.unit()
     }
 
-    /// Declares the bindings of the given pattern and returns the visibility scope
-    /// for the bindings in this patterns, if such a scope had to be created.
-    /// NOTE: Declaring the bindings should always be done in their drop scope.
+    /// Declares the bindings of the given patterns and returns the visibility
+    /// scope for the bindings in these patterns, if such a scope had to be
+    /// created. NOTE: Declaring the bindings should always be done in their
+    /// drop scope.
     pub fn declare_bindings(&mut self,
                             mut visibility_scope: Option<SourceScope>,
                             scope_span: Span,
@@ -356,7 +357,8 @@ pub fn declare_bindings(&mut self,
             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
     }
@@ -1181,7 +1183,8 @@ fn declare_binding(&mut self,
                        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={:?})",
@@ -1207,6 +1210,7 @@ fn declare_binding(&mut self,
                 // 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());
index 054bd69c361b92115eb6c60dd32e67ec3cccbcd4..c0c431804d8c1ea52fcf1716084e06c761586e55 100644 (file)
@@ -763,6 +763,7 @@ fn args_and_body(&mut self,
                                     binding_mode,
                                     opt_ty_info,
                                     opt_match_place: Some((Some(place.clone()), span)),
+                                    pat_span: span,
                                 })))
                             };
                         self.var_indices.insert(var, LocalsForNode::One(local));
index 42682c34407cab08c713731ac8fc89d4dadbc097..bda80ff562c75ede8ef6cbacc79b5982d36de066 100644 (file)
@@ -35,6 +35,7 @@
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 #![feature(step_trait)]
+#![feature(slice_concat_ext)]
 
 #![recursion_limit="256"]
 
index 78e9dd23e83ae718387a9fa5bd1e47e2a50028e3..fe6fefe89fd66b59cab4e0e5b4887eb165fbc1ce 100644 (file)
 /// 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
     }
diff --git a/src/test/ui/E0508-fail.ast.nll.stderr b/src/test/ui/E0508-fail.ast.nll.stderr
new file mode 100644 (file)
index 0000000..fda6c24
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508-fail.rs:18:18
+   |
+LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
index faf7411af317b15b2f8faf13cb99ff2a052cd173..fda6c24dc8710a8e5d97bf5bf119d843e95cb793 100644 (file)
@@ -5,7 +5,7 @@ LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
    |                  ^^^^^^^^
    |                  |
    |                  cannot move out of here
-   |                  help: consider using a reference instead: `&array[0]`
+   |                  help: consider borrowing here: `&array[0]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/E0508.nll.stderr b/src/test/ui/E0508.nll.stderr
new file mode 100644 (file)
index 0000000..025ff87
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:15:18
+   |
+LL |     let _value = array[0];  //~ ERROR [E0508]
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
index 2aa8f1c3813090291fbca72df73f78ee8f2f8785..b9de60f43f703f72c82096ffa92e995bea3c211d 100644 (file)
@@ -2,10 +2,16 @@ error[E0507]: cannot move out of borrowed content
   --> $DIR/access-mode-in-closures.rs:19:15
    |
 LL |         match *s { sty(v) => v } //~ ERROR cannot move out
-   |               ^^       - move occurs because v has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+   |               ^^       - data moved here
    |               |
    |               cannot move out of borrowed content
-   |               help: consider removing this dereference operator: `s`
+   |               help: consider removing the `*`: `s`
+   |
+note: move occurs because `v` has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+  --> $DIR/access-mode-in-closures.rs:19:24
+   |
+LL |         match *s { sty(v) => v } //~ ERROR cannot move out
+   |                        ^
 
 error: aborting due to previous error
 
index f9e517def14060e049e7d8629c1058e35691cc4b..25eb69ad9377dfe21b260a35ad50463847956d75 100644 (file)
@@ -2,28 +2,46 @@ error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
    |
 LL |     for &a in x.iter() {    //~ ERROR cannot move out
-   |          -    ^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref a`
+   |         --    ^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:10
+   |
+LL |     for &a in x.iter() {    //~ ERROR cannot move out
+   |          ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:28:15
    |
 LL |     for &a in &f.a {  //~ ERROR cannot move out
-   |          -    ^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref a`
+   |         --    ^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:28:10
+   |
+LL |     for &a in &f.a {  //~ ERROR cannot move out
+   |          ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:32:15
    |
 LL |     for &a in x.iter() {    //~ ERROR cannot move out
-   |          -    ^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref a`
+   |         --    ^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:32:10
+   |
+LL |     for &a in x.iter() {    //~ ERROR cannot move out
+   |          ^
 
 error: aborting due to 3 previous errors
 
index 55c6a40d281bc0c55dc1c9d02b52de582e9c3364..cdbfab8bd054a1903c2d53ce953bc577d7f9faeb 100644 (file)
@@ -5,7 +5,7 @@ LL |         let _b = *y; //~ ERROR cannot move out
    |                  ^^
    |                  |
    |                  cannot move out of borrowed content
-   |                  help: consider removing this dereference operator: `y`
+   |                  help: consider removing the `*`: `y`
 
 error: aborting due to previous error
 
index 1b913471924b799a19fbcefa11978ce2bef67d0a..2df520a936c9d4a9975563d5eb6221917fda2853 100644 (file)
@@ -5,14 +5,24 @@ LL |     match *f {             //~ ERROR cannot move out of
    |           ^^
    |           |
    |           cannot move out of borrowed content
-   |           help: consider removing this dereference operator: `f`
+   |           help: consider removing the `*`: `f`
 LL |                            //~| cannot move out
 LL |         Foo::Foo1(num1,
-   |                   ---- move occurs because num1 has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+   |                   ---- data moved here
 LL |                   num2) => (),
-   |                   ---- move occurs because num2 has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+   |                   ---- ...and here
 LL |         Foo::Foo2(num) => (),
-   |                   --- move occurs because num has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+   |                   --- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:23:19
+   |
+LL |         Foo::Foo1(num1,
+   |                   ^^^^
+LL |                   num2) => (),
+   |                   ^^^^
+LL |         Foo::Foo2(num) => (),
+   |                   ^^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-error-with-note.rs:39:11
@@ -23,12 +33,15 @@ LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
 LL |             f: _s,
    |                -- data moved here
 LL |             g: _t
-   |                -- ... and here
-help: to prevent move, use ref or ref mut
+   |                -- ...and here
    |
-LL |             f: ref _s,
-LL |             g: ref _t
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:42:16
    |
+LL |             f: _s,
+   |                ^^
+LL |             g: _t
+   |                ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-error-with-note.rs:57:11
@@ -37,10 +50,16 @@ LL |     match a.a {           //~ ERROR cannot move out of
    |           ^^^
    |           |
    |           cannot move out of borrowed content
-   |           help: consider using a reference instead: `&a.a`
+   |           help: consider borrowing here: `&a.a`
 LL |                           //~| cannot move out
 LL |         n => {
-   |         - move occurs because n has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+   |         - data moved here
+   |
+note: move occurs because `n` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:59:9
+   |
+LL |         n => {
+   |         ^
 
 error: aborting due to 3 previous errors
 
index 4f692bfc55e427cb92ed903d240d51e4269da96c..f823a6f08d789485e47546b7e9fa34f4ec5f1f34 100644 (file)
@@ -5,7 +5,7 @@ LL |     let y = *x; //~ ERROR cannot move out of dereference of raw pointer
    |             ^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&*x`
+   |             help: consider removing the `*`: `x`
 
 error: aborting due to previous error
 
index f670936dbac17b7a4bee7dac9c2e38d198641daa..49c2ec0dcf4e7c996e77b3f918f482664288f74f 100644 (file)
@@ -5,8 +5,14 @@ LL | fn arg_item(&_x: &String) {}
    |             ^--
    |             ||
    |             |data moved here
-   |             |help: to prevent move, use ref or ref mut: `ref _x`
    |             cannot move out of borrowed content
+   |             help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:16:14
+   |
+LL | fn arg_item(&_x: &String) {}
+   |              ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:21:11
@@ -15,17 +21,29 @@ LL |     with(|&_x| ())
    |           ^--
    |           ||
    |           |data moved here
-   |           |help: to prevent move, use ref or ref mut: `ref _x`
    |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:21:12
+   |
+LL |     with(|&_x| ())
+   |            ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:27:15
    |
 LL |     let &_x = &"hi".to_string();
-   |          --   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref _x`
+   |         ---   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:27:10
+   |
+LL |     let &_x = &"hi".to_string();
+   |          ^^
 
 error: aborting due to 3 previous errors
 
index f670936dbac17b7a4bee7dac9c2e38d198641daa..49c2ec0dcf4e7c996e77b3f918f482664288f74f 100644 (file)
@@ -5,8 +5,14 @@ LL | fn arg_item(&_x: &String) {}
    |             ^--
    |             ||
    |             |data moved here
-   |             |help: to prevent move, use ref or ref mut: `ref _x`
    |             cannot move out of borrowed content
+   |             help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:16:14
+   |
+LL | fn arg_item(&_x: &String) {}
+   |              ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:21:11
@@ -15,17 +21,29 @@ LL |     with(|&_x| ())
    |           ^--
    |           ||
    |           |data moved here
-   |           |help: to prevent move, use ref or ref mut: `ref _x`
    |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:21:12
+   |
+LL |     with(|&_x| ())
+   |            ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:27:15
    |
 LL |     let &_x = &"hi".to_string();
-   |          --   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref _x`
+   |         ---   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:27:10
+   |
+LL |     let &_x = &"hi".to_string();
+   |          ^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr
new file mode 100644 (file)
index 0000000..b9c47e6
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-out-of-overloaded-deref.rs:14:14
+   |
+LL |     let _x = *Rc::new("hi".to_string());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              cannot move out of borrowed content
+   |              help: consider removing the `*`: `Rc::new("hi".to_string())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index 15c7011d71671c90b0852f028ce47060a1102c0d..34f9f035188b8d4276c21c2f5afc674365cb5f29 100644 (file)
@@ -5,10 +5,13 @@ LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         //[mir]~^ ERROR [E0509]
 LL |         S {f:_s} => {}
-   |              --
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:22:14
+   |
+LL |         S {f:_s} => {}
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:20
@@ -17,7 +20,12 @@ LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:14
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:19
@@ -26,8 +34,13 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
    |                   |    |
    |                   |    data moved here
-   |                   |    help: to prevent move, use ref or ref mut: `ref _s`
    |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:24
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                        ^^
 
 error: aborting due to 3 previous errors
 
index 15c7011d71671c90b0852f028ce47060a1102c0d..34f9f035188b8d4276c21c2f5afc674365cb5f29 100644 (file)
@@ -5,10 +5,13 @@ LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         //[mir]~^ ERROR [E0509]
 LL |         S {f:_s} => {}
-   |              --
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:22:14
+   |
+LL |         S {f:_s} => {}
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:20
@@ -17,7 +20,12 @@ LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:14
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:19
@@ -26,8 +34,13 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
    |                   |    |
    |                   |    data moved here
-   |                   |    help: to prevent move, use ref or ref mut: `ref _s`
    |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:24
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                        ^^
 
 error: aborting due to 3 previous errors
 
index c69ae8755a957dcdebeff4e25172412f6f622cf1..278c33c71e24549f00090137180e5a32f9df8d7d 100644 (file)
@@ -4,10 +4,13 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
 LL |     match S("foo".to_string()) {
    |           ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         S(_s) => {}
-   |           --
-   |           |
-   |           data moved here
-   |           help: to prevent move, use ref or ref mut: `ref _s`
+   |           -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:11
+   |
+LL |         S(_s) => {}
+   |           ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:24:17
@@ -16,7 +19,12 @@ LL |     let S(_s) = S("foo".to_string());
    |           --    ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
-   |           help: to prevent move, use ref or ref mut: `ref _s`
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:24:11
+   |
+LL |     let S(_s) = S("foo".to_string());
+   |           ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:28:19
@@ -25,8 +33,13 @@ LL | fn move_in_fn_arg(S(_s): S) {
    |                   ^^--^
    |                   | |
    |                   | data moved here
-   |                   | help: to prevent move, use ref or ref mut: `ref _s`
    |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:28:21
+   |
+LL | fn move_in_fn_arg(S(_s): S) {
+   |                     ^^
 
 error: aborting due to 3 previous errors
 
index 95a7894d532546e1f8dd942b7c11e536c906eb22..f3430ba4e06c9038310a8f087594447e8b89dbce 100644 (file)
@@ -7,14 +7,23 @@ LL |                 &[Foo { string: a },
    |                                 - data moved here
 ...
 LL |                   Foo { string: b }] => {
-   |                                 - ... and here
-help: to prevent move, use ref or ref mut
+   |                                 - ...and here
    |
-LL |                 &[Foo { string: ref a },
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:30:33
+   |
+LL |                 &[Foo { string: a },
+   |                                 ^
+...
+LL |                   Foo { string: b }] => {
+   |                                 ^
+help: consider removing the `&`
+   |
+LL |                 [Foo { string: a },
 LL |                 //~^ ERROR cannot move out of type `[Foo]`
 LL |                 //~| cannot move out
 LL |                 //~| to prevent move
-LL |                   Foo { string: ref b }] => {
+LL |                   Foo { string: b }] => {
    |
 
 error: aborting due to previous error
index 4a72d7f33026652970b485baf7aa76e090aaba8b..92e10c258c269efbd9cca6855d1dcd0e351bf573 100644 (file)
@@ -5,7 +5,7 @@ LL |     let bad = v[0];
    |               ^^^^
    |               |
    |               cannot move out of borrowed content
-   |               help: consider using a reference instead: `&v[0]`
+   |               help: consider borrowing here: `&v[0]`
 
 error: aborting due to previous error
 
index 2779132590e2c00b57e1b06f1a9d372b2af166fd..d5b17119d85f52abeb645cf07b1f5b8c24f2ec8e 100644 (file)
@@ -28,10 +28,21 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
 LL |     match vec {
    |           ^^^ cannot move out of here
 LL |         &mut [_a, //~ ERROR cannot move out
-   |               --
-   |               |
-   |               data moved here
-   |               help: to prevent move, use ref or ref mut: `ref _a`
+   |               -- data moved here
+   |
+note: move occurs because `_a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:44:15
+   |
+LL |         &mut [_a, //~ ERROR cannot move out
+   |               ^^
+help: consider removing the `&mut`
+   |
+LL |         [_a, //~ ERROR cannot move out
+LL |             //~| cannot move out
+LL |             //~| to prevent move
+LL |             ..
+LL |         ] => {
+   |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:57:13
@@ -40,7 +51,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&vec[0]`
+   |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:64:11
@@ -49,10 +60,19 @@ LL |     match vec {
    |           ^^^ cannot move out of here
 ...
 LL |          _b] => {}
-   |          --
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref _b`
+   |          -- data moved here
+   |
+note: move occurs because `_b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:67:10
+   |
+LL |          _b] => {}
+   |          ^^
+help: consider removing the `&mut`
+   |
+LL |         [ //~ ERROR cannot move out
+LL |         //~^ cannot move out
+LL |          _b] => {}
+   |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:70:13
@@ -61,7 +81,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&vec[0]`
+   |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:77:11
@@ -69,14 +89,18 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
 LL |     match vec {
    |           ^^^ cannot move out of here
 LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
-   |               --  --  -- ... and here
-   |               |   |
-   |               |   ... and here
-   |               data moved here
-help: to prevent move, use ref or ref mut
-   |
-LL |         &mut [ref _a, ref _b, ref _c] => {}  //~ ERROR cannot move out
-   |               ^^^^^^  ^^^^^^  ^^^^^^
+   |         -----------------
+   |         |     |   |   |
+   |         |     |   |   ...and here
+   |         |     |   ...and here
+   |         |     data moved here
+   |         help: consider removing the `&mut`: `[_a, _b, _c]`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:78:15
+   |
+LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+   |               ^^  ^^  ^^
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:82:13
@@ -85,7 +109,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&vec[0]`
+   |             help: consider borrowing here: `&vec[0]`
 
 error: aborting due to 8 previous errors
 
index 20713c3392e8e9c23e0f2cfe66337beee321ede3..d4340938eebc14880e7b4409021344c26f733c86 100644 (file)
@@ -5,8 +5,13 @@ LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
    |                                          ^^^^^-^
    |                                          |    |
    |                                          |    data moved here
-   |                                          |    help: to prevent move, use ref or ref mut: `ref s`
    |                                          cannot move out of borrowed content
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/issue-51415.rs:16:47
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                               ^
 
 error: aborting due to previous error
 
index 4ba9b3aeb5d5da423591f7b3554db573cdaad917..491b5b5bd74abef53a40f7b6d0e963f9c0683bd5 100644 (file)
@@ -5,10 +5,16 @@ LL |     match &s.x {
    |           ^^^^ cannot move out of borrowed content
 LL |         &E::Foo => {}
 LL |         &E::Bar(identifier) => f(identifier.clone())  //~ ERROR cannot move
-   |                 ----------
-   |                 |
-   |                 data moved here
-   |                 help: to prevent move, use ref or ref mut: `ref identifier`
+   |         -------------------
+   |         |       |
+   |         |       data moved here
+   |         help: consider removing the `&`: `E::Bar(identifier)`
+   |
+note: move occurs because `identifier` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/by-move-pattern-binding.rs:26:17
+   |
+LL |         &E::Bar(identifier) => f(identifier.clone())  //~ ERROR cannot move
+   |                 ^^^^^^^^^^
 
 error: aborting due to previous error
 
index b265ec8bddac689c663c9d8b1d35e527f397e2c6..5522e22fb1fa28089a33a6c8851a39b7b52cf70a 100644 (file)
@@ -56,7 +56,7 @@ LL |     let y = { static x: Box<isize> = box 3; x };
    |                                             ^
    |                                             |
    |                                             cannot move out of static item
-   |                                             help: consider using a reference instead: `&x`
+   |                                             help: consider borrowing here: `&x`
 
 error[E0010]: allocations are not allowed in statics
   --> $DIR/check-static-values-constraints.rs:120:38
index a1fbcf1430db93b2b4a40c3077ee87db39a4cce9..e334472f9d6e1b26cba8b06eb20fe2ccdd999cfe 100644 (file)
@@ -4,10 +4,13 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         S {f:_s} => {} //~ ERROR cannot move out
-   |              --
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/overlapping_spans.rs:21:14
+   |
+LL |         S {f:_s} => {} //~ ERROR cannot move out
+   |              ^^
 
 error: aborting due to previous error
 
index a8be048d7df6c25c5e0e2c8551704e01d546f7a4..8e0599370287fb886ef239e8b593c5088c94d7dd 100644 (file)
@@ -5,7 +5,12 @@ LL |     let X { x: y } = x; //~ ERROR cannot move out of type
    |                -     ^ cannot move out of here
    |                |
    |                data moved here
-   |                help: to prevent move, use ref or ref mut: `ref y`
+   |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:22:16
+   |
+LL |     let X { x: y } = x; //~ ERROR cannot move out of type
+   |                ^
 
 error: aborting due to previous error
 
index 9f0d2d5f0e1891e42d588a51db7c0b663dd22428..dd1a3ef2a2b9835c1403c0796b7475cb4b7de57d 100644 (file)
@@ -4,10 +4,13 @@ error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
 LL |     match x {
    |           ^ cannot move out of here
 LL |         X { x: y } => println!("contents: {}", y)
-   |                -
-   |                |
-   |                data moved here
-   |                help: to prevent move, use ref or ref mut: `ref y`
+   |                - data moved here
+   |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:25:16
+   |
+LL |         X { x: y } => println!("contents: {}", y)
+   |                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0509.nll.stderr b/src/test/ui/error-codes/E0509.nll.stderr
new file mode 100644 (file)
index 0000000..723b083
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait
+  --> $DIR/E0509.rs:26:23
+   |
+LL |     let fancy_field = drop_struct.fancy; //~ ERROR E0509
+   |                       ^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       cannot move out of here
+   |                       help: consider borrowing here: `&drop_struct.fancy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
index 29bda252b9115f180495870e819928142669be9c..72d21d47d86fa765985da974e0b8b2664837d7fa 100644 (file)
@@ -8,15 +8,16 @@ LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
    |                 -- data moved here
 ...
 LL |         (&[hd1, ..], &[hd2, ..])
-   |                        --- ... and here
-help: to prevent move, use ref or ref mut
+   |                        --- ...and here
    |
-LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-LL |             => println!("one empty"),
-LL |         //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         (&[hd1, ..], &[ref hd2, ..])
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-12567.rs:16:17
    |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 ^^
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |                        ^^^
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
   --> $DIR/issue-12567.rs:14:11
@@ -28,15 +29,16 @@ LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
    |                 -- data moved here
 ...
 LL |         (&[hd1, ..], &[hd2, ..])
-   |            --- ... and here
-help: to prevent move, use ref or ref mut
+   |            --- ...and here
    |
-LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-LL |             => println!("one empty"),
-LL |         //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         (&[ref hd1, ..], &[hd2, ..])
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-12567.rs:16:17
    |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 ^^
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |            ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-17718-static-move.nll.stderr b/src/test/ui/issues/issue-17718-static-move.nll.stderr
new file mode 100644 (file)
index 0000000..f8da3c3
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/issue-17718-static-move.rs:16:14
+   |
+LL |     let _a = FOO; //~ ERROR: cannot move out of static item
+   |              ^^^
+   |              |
+   |              cannot move out of static item
+   |              help: consider borrowing here: `&FOO`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index fc94cc423c53138d3c35bcbbdfef22648835772e..3a6784eed67dd35d3adaaadb90b1bcd59d38ebc7 100644 (file)
@@ -5,7 +5,7 @@ LL |     let a = unsafe { *mut_ref() };
    |                      ^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*mut_ref()`
+   |                      help: consider removing the `*`: `mut_ref()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:39:22
@@ -14,7 +14,7 @@ LL |     let b = unsafe { *imm_ref() };
    |                      ^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*imm_ref()`
+   |                      help: consider removing the `*`: `imm_ref()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:42:22
@@ -23,7 +23,7 @@ LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*mut_ptr()`
+   |                      help: consider removing the `*`: `mut_ptr()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:45:22
@@ -32,7 +32,7 @@ LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*const_ptr()`
+   |                      help: consider removing the `*`: `const_ptr()`
 
 error: aborting due to 4 previous errors
 
index 162e43abc0ac47a0e915200ff2df12e647227194..9020d3778c3730820347651be4554a9b7d9c1f0b 100644 (file)
@@ -5,7 +5,7 @@ LL |     let e = f.v[0]; //~ ERROR cannot move out of indexed content
    |             ^^^^^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&f.v[0]`
+   |             help: consider borrowing here: `&f.v[0]`
 
 error: aborting due to previous error
 
index cd75be24589dfbf443bd00671ba8dc3e43056891..a80e9a5fe091f70343247033078fb2881a09d61d 100644 (file)
@@ -5,9 +5,15 @@ LL |     let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
    |          -  -    ^^^^
    |          |  |    |
    |          |  |    cannot move out of borrowed content
-   |          |  |    help: consider using a reference instead: `&x[0]`
-   |          |  move occurs because b has type `std::string::String`, which does not implement the `Copy` trait
-   |          move occurs because a has type `std::string::String`, which does not implement the `Copy` trait
+   |          |  |    help: consider borrowing here: `&x[0]`
+   |          |  ...and here
+   |          data moved here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-40402-2.rs:15:10
+   |
+LL |     let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
+   |          ^  ^
 
 error: aborting due to previous error
 
index b061b6a7963859daed322b322498da6a7c3dd45c..aa62b457ecdf378cef6c96e4a6256aa36293a886 100644 (file)
@@ -4,10 +4,13 @@ error[E0508]: cannot move out of type `[A]`, a non-copy slice
 LL |     match a {
    |           ^ cannot move out of here
 LL |         box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
-   |              -
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref a`
+   |              - data moved here
+   |
+note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
+  --> $DIR/move-out-of-slice-1.rs:18:14
+   |
+LL |         box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
+   |              ^
 
 error: aborting due to previous error
 
index 94f2074b45d4c0a444f38b6606876e5eefdb3097..1f22ab148185296bbf3ca71abe0a75ca06630a3d 100644 (file)
@@ -5,10 +5,16 @@ LL |             match hellothere.x { //~ ERROR cannot move out
    |                   ^^^^^^^^^^^^
    |                   |
    |                   cannot move out of borrowed content
-   |                   help: consider using a reference instead: `&hellothere.x`
+   |                   help: consider borrowing here: `&hellothere.x`
 ...
 LL |                 box E::Bar(x) => println!("{}", x.to_string()),
-   |                            - move occurs because x has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+   |                            - data moved here
+   |
+note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/moves-based-on-type-block-bad.rs:37:28
+   |
+LL |                 box E::Bar(x) => println!("{}", x.to_string()),
+   |                            ^
 
 error: aborting due to previous error
 
index 814e11b6f0682f5feccb0a49fce9885b48d65dbd..6a4c8f2e8d81570161b7d251523acb9c6483235f 100644 (file)
@@ -5,7 +5,7 @@ LL |     let x = { *r }; //~ ERROR
    |               ^^
    |               |
    |               cannot move out of borrowed content
-   |               help: consider removing this dereference operator: `r`
+   |               help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:16:22
@@ -14,7 +14,7 @@ LL |     let y = unsafe { *r }; //~ ERROR
    |                      ^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider removing this dereference operator: `r`
+   |                      help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:17:26
@@ -23,7 +23,7 @@ LL |     let z = loop { break *r; }; //~ ERROR
    |                          ^^
    |                          |
    |                          cannot move out of borrowed content
-   |                          help: consider removing this dereference operator: `r`
+   |                          help: consider removing the `*`: `r`
 
 error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:21:15
@@ -32,7 +32,7 @@ LL |     let x = { arr[0] }; //~ ERROR
    |               ^^^^^^
    |               |
    |               cannot move out of here
-   |               help: consider using a reference instead: `&arr[0]`
+   |               help: consider borrowing here: `&arr[0]`
 
 error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:22:22
@@ -41,7 +41,7 @@ LL |     let y = unsafe { arr[0] }; //~ ERROR
    |                      ^^^^^^
    |                      |
    |                      cannot move out of here
-   |                      help: consider using a reference instead: `&arr[0]`
+   |                      help: consider borrowing here: `&arr[0]`
 
 error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:23:26
@@ -50,7 +50,7 @@ LL |     let z = loop { break arr[0]; }; //~ ERROR
    |                          ^^^^^^
    |                          |
    |                          cannot move out of here
-   |                          help: consider using a reference instead: `&arr[0]`
+   |                          help: consider borrowing here: `&arr[0]`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:27:38
@@ -59,7 +59,7 @@ LL |     let x = { let mut u = 0; u += 1; *r }; //~ ERROR
    |                                      ^^
    |                                      |
    |                                      cannot move out of borrowed content
-   |                                      help: consider removing this dereference operator: `r`
+   |                                      help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:28:45
@@ -68,7 +68,7 @@ LL |     let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR
    |                                             ^^
    |                                             |
    |                                             cannot move out of borrowed content
-   |                                             help: consider removing this dereference operator: `r`
+   |                                             help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:29:49
@@ -77,7 +77,7 @@ LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR
    |                                                 ^^
    |                                                 |
    |                                                 cannot move out of borrowed content
-   |                                                 help: consider removing this dereference operator: `r`
+   |                                                 help: consider removing the `*`: `r`
 
 error: aborting due to 9 previous errors
 
index 53d60d3f6d649a4b4ec0b3d9efbc1dc8c14f4ba7..592768363096cae2d0d60a37ee35a0eefb81d24b 100644 (file)
@@ -5,7 +5,7 @@ LL |     let b = *a;
    |             ^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider removing this dereference operator: `a`
+   |             help: consider removing the `*`: `a`
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:25:13
@@ -14,7 +14,7 @@ LL |     let b = a[0];
    |             ^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&a[0]`
+   |             help: consider borrowing here: `&a[0]`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:32:13
@@ -23,7 +23,7 @@ LL |     let s = **r;
    |             ^^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&**r`
+   |             help: consider removing the `*`: `*r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:40:13
@@ -32,7 +32,7 @@ LL |     let s = *r;
    |             ^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&*r`
+   |             help: consider removing the `*`: `r`
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:45:13
@@ -41,7 +41,7 @@ LL |     let a = [A("".to_string())][0];
    |             ^^^^^^^^^^^^^^^^^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&[A("".to_string())][0]`
+   |             help: consider borrowing here: `&[A("".to_string())][0]`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:51:16
@@ -50,8 +50,14 @@ LL |     let A(s) = *a;
    |           -    ^^
    |           |    |
    |           |    cannot move out of borrowed content
-   |           |    help: consider removing this dereference operator: `a`
-   |           move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+   |           |    help: consider removing the `*`: `a`
+   |           data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:51:11
+   |
+LL |     let A(s) = *a;
+   |           ^
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:57:19
@@ -60,7 +66,12 @@ LL |     let C(D(s)) = c;
    |             -     ^ cannot move out of here
    |             |
    |             data moved here
-   |             help: to prevent move, use ref or ref mut: `ref s`
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:57:13
+   |
+LL |     let C(D(s)) = c;
+   |             ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:64:9
@@ -75,12 +86,20 @@ LL |     match x[0] {
    |           ^^^^
    |           |
    |           cannot move out of here
-   |           help: consider using a reference instead: `&x[0]`
+   |           help: consider borrowing here: `&x[0]`
 LL |     //~^ ERROR
 LL |         B::U(d) => (),
-   |              - move occurs because d has type `D`, which does not implement the `Copy` trait
+   |              - data moved here
 LL |         B::V(s) => (),
-   |              - move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+   |              - ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/move-errors.rs:89:14
+   |
+LL |         B::U(d) => (),
+   |              ^
+LL |         B::V(s) => (),
+   |              ^
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:96:11
@@ -89,10 +108,13 @@ LL |     match x {
    |           ^ cannot move out of here
 ...
 LL |         B::U(D(s)) => (),
-   |                -
-   |                |
-   |                data moved here
-   |                help: to prevent move, use ref or ref mut: `ref s`
+   |                - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:99:16
+   |
+LL |         B::U(D(s)) => (),
+   |                ^
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:105:11
@@ -101,10 +123,13 @@ LL |     match x {
    |           ^ cannot move out of here
 ...
 LL |         (D(s), &t) => (),
-   |            -
-   |            |
-   |            data moved here
-   |            help: to prevent move, use ref or ref mut: `ref s`
+   |            - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:108:12
+   |
+LL |         (D(s), &t) => (),
+   |            ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:105:11
@@ -113,10 +138,13 @@ LL |     match x {
    |           ^ cannot move out of borrowed content
 ...
 LL |         (D(s), &t) => (),
-   |                 -
-   |                 |
-   |                 data moved here
-   |                 help: to prevent move, use ref or ref mut: `ref t`
+   |                 - data moved here
+   |
+note: move occurs because `t` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:108:17
+   |
+LL |         (D(s), &t) => (),
+   |                 ^
 
 error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:115:11
@@ -125,13 +153,15 @@ LL |     match x {
    |           ^ cannot move out of here
 LL |     //~^ ERROR
 LL |         F(s, mut t) => (),
-   |           -  ----- ... and here
+   |           -  ----- ...and here
    |           |
    |           data moved here
-help: to prevent move, use ref or ref mut
    |
-LL |         F(ref s, ref mut t) => (),
-   |           ^^^^^  ^^^^^^^^^
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/move-errors.rs:117:11
+   |
+LL |         F(s, mut t) => (),
+   |           ^  ^^^^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:123:11
@@ -140,10 +170,16 @@ LL |     match *x {
    |           ^^
    |           |
    |           cannot move out of borrowed content
-   |           help: consider removing this dereference operator: `x`
+   |           help: consider removing the `*`: `x`
 LL |     //~^ ERROR
 LL |         Ok(s) | Err(s) => (),
-   |            - move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+   |            - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:125:12
+   |
+LL |         Ok(s) | Err(s) => (),
+   |            ^
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/std-uncopyable-atomics.nll.stderr b/src/test/ui/std-uncopyable-atomics.nll.stderr
new file mode 100644 (file)
index 0000000..e6b612f
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:19:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:21:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:23:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:25:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
new file mode 100644 (file)
index 0000000..dc0186e
--- /dev/null
@@ -0,0 +1,162 @@
+// 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)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+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 ve = vec![Either::One(X(Y))];
+
+    let vr = &ve;
+    let vrm = &mut vec![Either::One(X(Y))];
+
+    let vx = vec![X(Y)];
+
+    let vs = &vx;
+    let vsm = &mut vec![X(Y)];
+
+    // -------- test for duplicate suggestions --------
+
+    let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (X(_t), X(_u))
+    if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &(Either::Two(_t), Either::One(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        | &(Either::Two(_t), Either::One(_u)) => (),
+        // FIXME: would really like a suggestion here too
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &(Either::Two(ref _t), Either::One(ref _u)) => (),
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        (Either::Two(_t), Either::One(_u)) => (),
+        _ => (),
+    }
+    fn f5(&(X(_t), X(_u)): &(X, X)) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (X(_t), X(_u))
+
+    let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (X(_t), X(_u))
+    if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(_t), Either::One(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        | &mut (Either::Two(_t), Either::One(_u)) => (),
+        // FIXME: would really like a suggestion here too
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        (Either::Two(_t), Either::One(_u)) => (),
+        _ => (),
+    }
+    fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (X(_t), X(_u))
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
new file mode 100644 (file)
index 0000000..bb36884
--- /dev/null
@@ -0,0 +1,328 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:51:27
+   |
+LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+   |         ---------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         |   |      |
+   |         |   |      ...and here
+   |         |   data moved here
+   |         help: consider removing the `&`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:51:13
+   |
+LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+   |             ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:55:50
+   |
+LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |            -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |            |             |                |
+   |            |             |                ...and here
+   |            |             data moved here
+   |            help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:55:26
+   |
+LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |                          ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:59:53
+   |
+LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |               -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |               |             |                |
+   |               |             |                ...and here
+   |               |             data moved here
+   |               help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:59:29
+   |
+LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |                             ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:63:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
+...
+LL |         &(Either::Two(_t), Either::One(_u)) => (),
+   |                       -- ...and here   -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:65:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+...
+LL |         &(Either::Two(_t), Either::One(_u)) => (),
+   |                       ^^               ^^
+help: consider removing the `&`
+   |
+LL |         (Either::One(_t), Either::Two(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&`
+   |
+LL |         (Either::Two(_t), Either::One(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:73:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u))
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:75:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u))
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:82:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:84:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:90:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:92:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:103:31
+   |
+LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |         -------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         |       |      |
+   |         |       |      ...and here
+   |         |       data moved here
+   |         help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:103:17
+   |
+LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |                 ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:107:54
+   |
+LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |            ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |            |                 |                |
+   |            |                 |                ...and here
+   |            |                 data moved here
+   |            help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:107:30
+   |
+LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |                              ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:111:57
+   |
+LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |               ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |               |                 |                |
+   |               |                 |                ...and here
+   |               |                 data moved here
+   |               help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:111:33
+   |
+LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |                                 ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:115:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
+...
+LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
+   |                           -- ...and here   -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:117:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+...
+LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
+   |                           ^^               ^^
+help: consider removing the `&mut`
+   |
+LL |         (Either::One(_t), Either::Two(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+   |
+LL |         (Either::Two(_t), Either::One(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:125:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u))
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:127:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u))
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:134:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:136:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:142:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:144:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:150:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:152:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:98:11
+   |
+LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+   |           ^^^^--^^^^^--^^
+   |           |   |      |
+   |           |   |      ...and here
+   |           |   data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:98:15
+   |
+LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+   |               ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:158:11
+   |
+LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+   |           ^^^^^^^^--^^^^^--^^
+   |           |       |      |
+   |           |       |      ...and here
+   |           |       data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:158:19
+   |
+LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+   |                   ^^     ^^
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
new file mode 100644 (file)
index 0000000..8cc847e
--- /dev/null
@@ -0,0 +1,171 @@
+// 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)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+fn consume_fn<F: Fn()>(_f: F) { }
+
+fn consume_fnmut<F: FnMut()>(_f: F) { }
+
+pub fn main() { }
+
+fn move_into_fn() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let x = X(Y);
+
+    // -------- move into Fn --------
+
+    consume_fn(|| {
+        let X(_t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        while let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t)
+            | Either::Two(_t) => (),
+        }
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+
+        let X(mut _t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        while let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t)
+            | Either::Two(mut _t) => (),
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+    });
+}
+
+fn move_into_fnmut() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let x = X(Y);
+
+    // -------- move into FnMut --------
+
+    consume_fnmut(|| {
+        let X(_t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        while let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t)
+            | Either::Two(_t) => (),
+        }
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+
+        let X(mut _t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        while let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t)
+            | Either::Two(mut _t) => (),
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref mut _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+    });
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
new file mode 100644 (file)
index 0000000..228ec5a
--- /dev/null
@@ -0,0 +1,420 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:40:21
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(_t) = x;
+   |               --    ^
+   |               |     |
+   |               |     cannot move out of captured variable in an `Fn` closure
+   |               |     help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:40:15
+   |
+LL |         let X(_t) = x;
+   |               ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:44:34
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         if let Either::One(_t) = e { }
+   |                            --    ^
+   |                            |     |
+   |                            |     cannot move out of captured variable in an `Fn` closure
+   |                            |     help: consider borrowing here: `&e`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:44:28
+   |
+LL |         if let Either::One(_t) = e { }
+   |                            ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:48:37
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         while let Either::One(_t) = e { }
+   |                               --    ^
+   |                               |     |
+   |                               |     cannot move out of captured variable in an `Fn` closure
+   |                               |     help: consider borrowing here: `&e`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:48:31
+   |
+LL |         while let Either::One(_t) = e { }
+   |                               ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:52:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t)
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:56:25
+   |
+LL |             Either::One(_t)
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:59:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t) => (),
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:63:25
+   |
+LL |             Either::One(_t) => (),
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:68:25
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(mut _t) = x;
+   |               ------    ^
+   |               |         |
+   |               |         cannot move out of captured variable in an `Fn` closure
+   |               |         help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:68:15
+   |
+LL |         let X(mut _t) = x;
+   |               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:72:38
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         if let Either::One(mut _t) = em { }
+   |                            ------    ^^
+   |                            |         |
+   |                            |         cannot move out of captured variable in an `Fn` closure
+   |                            |         help: consider borrowing here: `&em`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:72:28
+   |
+LL |         if let Either::One(mut _t) = em { }
+   |                            ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:76:41
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         while let Either::One(mut _t) = em { }
+   |                               ------    ^^
+   |                               |         |
+   |                               |         cannot move out of captured variable in an `Fn` closure
+   |                               |         help: consider borrowing here: `&em`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:76:31
+   |
+LL |         while let Either::One(mut _t) = em { }
+   |                               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:80:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t)
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:84:25
+   |
+LL |             Either::One(mut _t)
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:87:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:91:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:107:21
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(_t) = x;
+   |               --    ^
+   |               |     |
+   |               |     cannot move out of captured variable in an `FnMut` closure
+   |               |     help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:107:15
+   |
+LL |         let X(_t) = x;
+   |               ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:111:34
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         if let Either::One(_t) = e { }
+   |                            --    ^
+   |                            |     |
+   |                            |     cannot move out of captured variable in an `FnMut` closure
+   |                            |     help: consider borrowing here: `&e`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:111:28
+   |
+LL |         if let Either::One(_t) = e { }
+   |                            ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:115:37
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         while let Either::One(_t) = e { }
+   |                               --    ^
+   |                               |     |
+   |                               |     cannot move out of captured variable in an `FnMut` closure
+   |                               |     help: consider borrowing here: `&e`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:115:31
+   |
+LL |         while let Either::One(_t) = e { }
+   |                               ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:119:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t)
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:123:25
+   |
+LL |             Either::One(_t)
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:126:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t) => (),
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:130:25
+   |
+LL |             Either::One(_t) => (),
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:135:25
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(mut _t) = x;
+   |               ------    ^
+   |               |         |
+   |               |         cannot move out of captured variable in an `FnMut` closure
+   |               |         help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:135:15
+   |
+LL |         let X(mut _t) = x;
+   |               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:139:38
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         if let Either::One(mut _t) = em { }
+   |                            ------    ^^
+   |                            |         |
+   |                            |         cannot move out of captured variable in an `FnMut` closure
+   |                            |         help: consider borrowing here: `&em`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:139:28
+   |
+LL |         if let Either::One(mut _t) = em { }
+   |                            ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:143:41
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         while let Either::One(mut _t) = em { }
+   |                               ------    ^^
+   |                               |         |
+   |                               |         cannot move out of captured variable in an `FnMut` closure
+   |                               |         help: consider borrowing here: `&em`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:143:31
+   |
+LL |         while let Either::One(mut _t) = em { }
+   |                               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:147:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t)
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:151:25
+   |
+LL |             Either::One(mut _t)
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:154:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:158:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:162:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:166:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
new file mode 100644 (file)
index 0000000..474e88c
--- /dev/null
@@ -0,0 +1,376 @@
+// 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)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+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 ve = vec![Either::One(X(Y))];
+
+    let vr = &ve;
+    let vrm = &mut vec![Either::One(X(Y))];
+
+    let vx = vec![X(Y)];
+
+    let vs = &vx;
+    let vsm = &mut vec![X(Y)];
+
+    // -------- move from Either/X place --------
+
+    let X(_t) = *s;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION s
+    if let Either::One(_t) = *r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION r
+    while let Either::One(_t) = *r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION r
+    match *r {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION r
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match *r {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION r
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = *sm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION sm
+    if let Either::One(_t) = *rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION rm
+    while let Either::One(_t) = *rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION rm
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t) => (),
+        Either::Two(ref mut _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = vs[0];
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vs[0]
+    if let Either::One(_t) = vr[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vr[0]
+    while let Either::One(_t) = vr[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vr[0]
+    match vr[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vr[0]
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match vr[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vr[0]
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = vsm[0];
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vsm[0]
+    if let Either::One(_t) = vrm[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vrm[0]
+    while let Either::One(_t) = vrm[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vrm[0]
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t) => (),
+        Either::Two(ref mut _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    // -------- move from &Either/&X place --------
+
+    let &X(_t) = s;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+    if let &Either::One(_t) = r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    while let &Either::One(_t) = r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t)
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        | &Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        &Either::Two(ref _t) => (),
+    }
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+    fn f1(&X(_t): &X) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+
+    let &mut X(_t) = sm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+    if let &mut Either::One(_t) = rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    while let &mut Either::One(_t) = rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::Two(_t)
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref _t) => (),
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref mut _t) => (),
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+    fn f2(&mut X(_t): &mut X) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+
+    // -------- move from tuple of &Either/&X --------
+
+    // FIXME: These should have suggestions.
+
+    let (&X(_t),) = (&x.clone(),);
+    //~^ ERROR cannot move
+    if let (&Either::One(_t),) = (&e.clone(),) { }
+    //~^ ERROR cannot move
+    while let (&Either::One(_t),) = (&e.clone(),) { }
+    //~^ ERROR cannot move
+    match (&e.clone(),) {
+        //~^ ERROR cannot move
+        (&Either::One(_t),)
+        | (&Either::Two(_t),) => (),
+    }
+    fn f3((&X(_t),): (&X,)) { }
+    //~^ ERROR cannot move
+
+    let (&mut X(_t),) = (&mut xm.clone(),);
+    //~^ ERROR cannot move
+    if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+    //~^ ERROR cannot move
+    while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+    //~^ ERROR cannot move
+    match (&mut em.clone(),) {
+        //~^ ERROR cannot move
+        (&mut Either::One(_t),) => (),
+        (&mut Either::Two(_t),) => (),
+    }
+    fn f4((&mut X(_t),): (&mut X,)) { }
+    //~^ ERROR cannot move
+
+    // -------- move from &Either/&X value --------
+
+    let &X(_t) = &x;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+    if let &Either::One(_t) = &e { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    while let &Either::One(_t) = &e { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t)
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        | &Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        &Either::Two(ref _t) => (),
+    }
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+
+    let &mut X(_t) = &mut xm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+    if let &mut Either::One(_t) = &mut em { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    while let &mut Either::One(_t) = &mut em { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t)
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        | &mut Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref _t) => (),
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref mut _t) => (),
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
new file mode 100644 (file)
index 0000000..d7a32db
--- /dev/null
@@ -0,0 +1,998 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:50:17
+   |
+LL |     let X(_t) = *s;
+   |           --    ^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider removing the `*`: `s`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:50:11
+   |
+LL |     let X(_t) = *s;
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:54:30
+   |
+LL |     if let Either::One(_t) = *r { }
+   |                        --    ^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider removing the `*`: `r`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:54:24
+   |
+LL |     if let Either::One(_t) = *r { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:58:33
+   |
+LL |     while let Either::One(_t) = *r { }
+   |                           --    ^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider removing the `*`: `r`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:58:27
+   |
+LL |     while let Either::One(_t) = *r { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:62:11
+   |
+LL |     match *r {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `r`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:66:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:69:11
+   |
+LL |     match *r {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `r`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:73:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:78:17
+   |
+LL |     let X(_t) = *sm;
+   |           --    ^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider removing the `*`: `sm`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:78:11
+   |
+LL |     let X(_t) = *sm;
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:82:30
+   |
+LL |     if let Either::One(_t) = *rm { }
+   |                        --    ^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider removing the `*`: `rm`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:82:24
+   |
+LL |     if let Either::One(_t) = *rm { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:86:33
+   |
+LL |     while let Either::One(_t) = *rm { }
+   |                           --    ^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider removing the `*`: `rm`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:86:27
+   |
+LL |     while let Either::One(_t) = *rm { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:90:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:94:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:97:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:101:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:105:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:109:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:114:17
+   |
+LL |     let X(_t) = vs[0];
+   |           --    ^^^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider borrowing here: `&vs[0]`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:114:11
+   |
+LL |     let X(_t) = vs[0];
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:118:30
+   |
+LL |     if let Either::One(_t) = vr[0] { }
+   |                        --    ^^^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider borrowing here: `&vr[0]`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:118:24
+   |
+LL |     if let Either::One(_t) = vr[0] { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:122:33
+   |
+LL |     while let Either::One(_t) = vr[0] { }
+   |                           --    ^^^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider borrowing here: `&vr[0]`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:122:27
+   |
+LL |     while let Either::One(_t) = vr[0] { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:126:11
+   |
+LL |     match vr[0] {
+   |           ^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vr[0]`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:130:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:133:11
+   |
+LL |     match vr[0] {
+   |           ^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vr[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:137:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:142:17
+   |
+LL |     let X(_t) = vsm[0];
+   |           --    ^^^^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider borrowing here: `&vsm[0]`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:142:11
+   |
+LL |     let X(_t) = vsm[0];
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:146:30
+   |
+LL |     if let Either::One(_t) = vrm[0] { }
+   |                        --    ^^^^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider borrowing here: `&vrm[0]`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:146:24
+   |
+LL |     if let Either::One(_t) = vrm[0] { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:150:33
+   |
+LL |     while let Either::One(_t) = vrm[0] { }
+   |                           --    ^^^^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider borrowing here: `&vrm[0]`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:150:27
+   |
+LL |     while let Either::One(_t) = vrm[0] { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:154:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:158:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:161:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:165:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:169:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:173:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:180:18
+   |
+LL |     let &X(_t) = s;
+   |         ------   ^ cannot move out of borrowed content
+   |         |  |
+   |         |  data moved here
+   |         help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:180:12
+   |
+LL |     let &X(_t) = s;
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:184:31
+   |
+LL |     if let &Either::One(_t) = r { }
+   |            ----------------   ^ cannot move out of borrowed content
+   |            |            |
+   |            |            data moved here
+   |            help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:184:25
+   |
+LL |     if let &Either::One(_t) = r { }
+   |                         ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:188:34
+   |
+LL |     while let &Either::One(_t) = r { }
+   |               ----------------   ^ cannot move out of borrowed content
+   |               |            |
+   |               |            data moved here
+   |               help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:188:28
+   |
+LL |     while let &Either::One(_t) = r { }
+   |                            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:192:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t)
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:194:22
+   |
+LL |         &Either::One(_t)
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:200:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:202:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:207:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:209:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:219:22
+   |
+LL |     let &mut X(_t) = sm;
+   |         ----------   ^^ cannot move out of borrowed content
+   |         |      |
+   |         |      data moved here
+   |         help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:219:16
+   |
+LL |     let &mut X(_t) = sm;
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:223:35
+   |
+LL |     if let &mut Either::One(_t) = rm { }
+   |            --------------------   ^^ cannot move out of borrowed content
+   |            |                |
+   |            |                data moved here
+   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:223:29
+   |
+LL |     if let &mut Either::One(_t) = rm { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:227:38
+   |
+LL |     while let &mut Either::One(_t) = rm { }
+   |               --------------------   ^^ cannot move out of borrowed content
+   |               |                |
+   |               |                data moved here
+   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:227:32
+   |
+LL |     while let &mut Either::One(_t) = rm { }
+   |                                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:231: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 these variables have types that don't implement the `Copy` trait
+  --> $DIR/simple.rs:233:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+...
+LL |         &mut Either::Two(_t) => (),
+   |                          ^^
+help: consider removing the `&mut`
+   |
+LL |         Either::One(_t) => (),
+   |         ^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+   |
+LL |         Either::Two(_t) => (),
+   |         ^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:240: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:242:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:247: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:249:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:254: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:256:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:270:21
+   |
+LL |     let (&X(_t),) = (&x.clone(),);
+   |             --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |             |
+   |             data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:270:13
+   |
+LL |     let (&X(_t),) = (&x.clone(),);
+   |             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:272:34
+   |
+LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
+   |                          --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                          |
+   |                          data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:272:26
+   |
+LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:274:37
+   |
+LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
+   |                             --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                             |
+   |                             data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:274:29
+   |
+LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:276:11
+   |
+LL |     match (&e.clone(),) {
+   |           ^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         (&Either::One(_t),)
+   |                       -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:278:23
+   |
+LL |         (&Either::One(_t),)
+   |                       ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:284:25
+   |
+LL |     let (&mut X(_t),) = (&mut xm.clone(),);
+   |                 --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                 |
+   |                 data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:284:17
+   |
+LL |     let (&mut X(_t),) = (&mut xm.clone(),);
+   |                 ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:286:38
+   |
+LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                              --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                              |
+   |                              data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:286:30
+   |
+LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:288:41
+   |
+LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                                 --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                                 |
+   |                                 data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:288:33
+   |
+LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                                 ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:290:11
+   |
+LL |     match (&mut em.clone(),) {
+   |           ^^^^^^^^^^^^^^^^^^ 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 these variables have types that don't implement the `Copy` trait
+  --> $DIR/simple.rs:292:27
+   |
+LL |         (&mut Either::One(_t),) => (),
+   |                           ^^
+LL |         (&mut Either::Two(_t),) => (),
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:300:18
+   |
+LL |     let &X(_t) = &x;
+   |         ------   ^^ cannot move out of borrowed content
+   |         |  |
+   |         |  data moved here
+   |         help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:300:12
+   |
+LL |     let &X(_t) = &x;
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:304:31
+   |
+LL |     if let &Either::One(_t) = &e { }
+   |            ----------------   ^^ cannot move out of borrowed content
+   |            |            |
+   |            |            data moved here
+   |            help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:304:25
+   |
+LL |     if let &Either::One(_t) = &e { }
+   |                         ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:308:34
+   |
+LL |     while let &Either::One(_t) = &e { }
+   |               ----------------   ^^ cannot move out of borrowed content
+   |               |            |
+   |               |            data moved here
+   |               help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:308:28
+   |
+LL |     while let &Either::One(_t) = &e { }
+   |                            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:312:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t)
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:314:22
+   |
+LL |         &Either::One(_t)
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:320:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:322:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:327:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:329:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:335:22
+   |
+LL |     let &mut X(_t) = &mut xm;
+   |         ----------   ^^^^^^^ cannot move out of borrowed content
+   |         |      |
+   |         |      data moved here
+   |         help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:335:16
+   |
+LL |     let &mut X(_t) = &mut xm;
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:339:35
+   |
+LL |     if let &mut Either::One(_t) = &mut em { }
+   |            --------------------   ^^^^^^^ cannot move out of borrowed content
+   |            |                |
+   |            |                data moved here
+   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:339:29
+   |
+LL |     if let &mut Either::One(_t) = &mut em { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:343:38
+   |
+LL |     while let &mut Either::One(_t) = &mut em { }
+   |               --------------------   ^^^^^^^ cannot move out of borrowed content
+   |               |                |
+   |               |                data moved here
+   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:343:32
+   |
+LL |     while let &mut Either::One(_t) = &mut em { }
+   |                                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:347: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:349:26
+   |
+LL |         &mut Either::One(_t)
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:355: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:357:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:362: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:364:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:369: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 the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:371:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:214:11
+   |
+LL |     fn f1(&X(_t): &X) { }
+   |           ^^^--^
+   |           |  |
+   |           |  data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:214:14
+   |
+LL |     fn f1(&X(_t): &X) { }
+   |              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:261:11
+   |
+LL |     fn f2(&mut X(_t): &mut X) { }
+   |           ^^^^^^^--^
+   |           |      |
+   |           |      data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:261:18
+   |
+LL |     fn f2(&mut X(_t): &mut X) { }
+   |                  ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:281:11
+   |
+LL |     fn f3((&X(_t),): (&X,)) { }
+   |           ^^^^--^^^
+   |           |   |
+   |           |   data moved here
+   |           cannot move out of borrowed content
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:281:15
+   |
+LL |     fn f3((&X(_t),): (&X,)) { }
+   |               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:295:11
+   |
+LL |     fn f4((&mut X(_t),): (&mut X,)) { }
+   |           ^^^^^^^^--^^^
+   |           |       |
+   |           |       data moved here
+   |           cannot move out of borrowed content
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:295:19
+   |
+LL |     fn f4((&mut X(_t),): (&mut X,)) { }
+   |                   ^^
+
+error: aborting due to 60 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
index 201a661726e9179940849bc4dca2126aeca410c6..58220ba992c7a28b7e40637c4a0807b10827b5fc 100644 (file)
@@ -82,7 +82,7 @@ pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String {
                     Err(error) => {
                         proc_res.fatal(Some(&format!(
                             "failed to decode compiler output as json: \
-                             `{}`\noutput: {}\nline: {}",
+                             `{}`\nline: {}\noutput: {}",
                             error, line, output
                         )));
                     }
@@ -114,7 +114,7 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
             Err(error) => {
                 proc_res.fatal(Some(&format!(
                     "failed to decode compiler output as json: \
-                     `{}`\noutput: {}\nline: {}",
+                     `{}`\nline: {}\noutput: {}",
                     error, line, output
                 )));
             }