From 0c0d11b8220f33ca58f8506014e9f1a61c7cff83 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 5 May 2017 23:28:36 +0200 Subject: [PATCH] Add help message if a FnOnce is moved --- src/librustc_borrowck/borrowck/mod.rs | 31 +++++++++++++++++++++------ src/test/ui/fn_once-moved.rs | 24 +++++++++++++++++++++ src/test/ui/fn_once-moved.stderr | 12 +++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/fn_once-moved.rs create mode 100644 src/test/ui/fn_once-moved.stderr diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 99df143126508..c28d45be18d9e 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 0000000000000..781d3885eaee8 --- /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 or the MIT license +// , 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 = 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 0000000000000..322ab64ebd4ea --- /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 +