about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-05-19 23:38:49 +0000
committerbors <bors@rust-lang.org>2017-05-19 23:38:49 +0000
commit4662b15be0c8fdb27d74295858d88eb024a59f87 (patch)
treeba56d9c988ad2411035e3808bf2b7eecde94927a
parent5dfcd85fd4bae49445383baadf472fbdb414a0e6 (diff)
parent0c0d11b8220f33ca58f8506014e9f1a61c7cff83 (diff)
downloadrust-4662b15be0c8fdb27d74295858d88eb024a59f87.tar.gz
rust-4662b15be0c8fdb27d74295858d88eb024a59f87.zip
Auto merge of #41772 - GuillaumeGomez:fn-once-message, r=estebank
Add help message if a FnOnce is moved

Fixes #40855.

r? @eddyb
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs31
-rw-r--r--src/test/ui/fn_once-moved.rs24
-rw-r--r--src/test/ui/fn_once-moved.stderr12
3 files changed, 60 insertions, 7 deletions
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 99df1431265..c28d45be18d 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -39,6 +39,8 @@ use rustc::middle::free_region::RegionRelations;
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::maps::Providers;
 
+use syntax_pos::DUMMY_SP;
+
 use std::fmt;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
@@ -539,7 +541,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             MovedInCapture => ("capture", "captured"),
         };
 
-        let (_ol, _moved_lp_msg, mut err) = match the_move.kind {
+        let (_ol, _moved_lp_msg, mut err, need_note) = match the_move.kind {
             move_data::Declared => {
                 // If this is an uninitialized variable, just emit a simple warning
                 // and return.
@@ -586,11 +588,24 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 let msg = if !has_fork && partial { "partially " }
                           else if has_fork && !has_common { "collaterally "}
                           else { "" };
-                let err = struct_span_err!(
+                let mut err = struct_span_err!(
                     self.tcx.sess, use_span, E0382,
                     "{} of {}moved value: `{}`",
                     verb, msg, nl);
-                (ol, moved_lp_msg, err)}
+                let need_note = match lp.ty.sty {
+                    ty::TypeVariants::TyClosure(id, _) => {
+                        if let Ok(ty::ClosureKind::FnOnce) =
+                           ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
+                            err.help("closure was moved because it only implements `FnOnce`");
+                            false
+                        } else {
+                            true
+                        }
+                    }
+                    _ => true,
+                };
+                (ol, moved_lp_msg, err, need_note)
+            }
         };
 
         // Get type of value and span where it was previously
@@ -627,10 +642,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             err
         };
 
-        err.note(&format!("move occurs because `{}` has type `{}`, \
-                           which does not implement the `Copy` trait",
-                          self.loan_path_to_string(moved_lp),
-                          moved_lp.ty));
+        if need_note {
+            err.note(&format!("move occurs because `{}` has type `{}`, \
+                               which does not implement the `Copy` trait",
+                              self.loan_path_to_string(moved_lp),
+                              moved_lp.ty));
+        }
 
         // Note: we used to suggest adding a `ref binding` or calling
         // `clone` but those suggestions have been removed because
diff --git a/src/test/ui/fn_once-moved.rs b/src/test/ui/fn_once-moved.rs
new file mode 100644
index 00000000000..781d3885eae
--- /dev/null
+++ b/src/test/ui/fn_once-moved.rs
@@ -0,0 +1,24 @@
+// Copyright 2017 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.
+
+use std::collections::HashMap;
+
+fn main() {
+    let dict: HashMap<i32, i32> = HashMap::new();
+    let debug_dump_dict = || {
+        for (key, value) in dict {
+            println!("{:?} - {:?}", key, value);
+        }
+    };
+    debug_dump_dict();
+    debug_dump_dict();
+    //~^ ERROR use of moved value: `debug_dump_dict`
+    //~| NOTE closure was moved because it only implements `FnOnce`
+}
diff --git a/src/test/ui/fn_once-moved.stderr b/src/test/ui/fn_once-moved.stderr
new file mode 100644
index 00000000000..322ab64ebd4
--- /dev/null
+++ b/src/test/ui/fn_once-moved.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `debug_dump_dict`
+  --> $DIR/fn_once-moved.rs:21:5
+   |
+20 |     debug_dump_dict();
+   |     --------------- value moved here
+21 |     debug_dump_dict();
+   |     ^^^^^^^^^^^^^^^ value used here after move
+   |
+   = help: closure was moved because it only implements `FnOnce`
+
+error: aborting due to previous error
+