Skip to content

Add help message if a FnOnce is moved #41772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions src/librustc_borrowck/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/fn_once-moved.rs
Original file line number Diff line number Diff line change
@@ -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`
}
12 changes: 12 additions & 0 deletions src/test/ui/fn_once-moved.stderr
Original file line number Diff line number Diff line change
@@ -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`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this point at the closure's span? If so, the text should be changed to something along the lines of

error[E0382]: use of moved value: `debug_dump_dict`
  --> $DIR/fn_once-moved.rs:21:5
15 |    let debug_dump_dict = || {
   |        --------------- closure only implements `FnOnce` so calling it moves it
...
20 |     debug_dump_dict();
   |     --------------- value moved here
21 |     debug_dump_dict();
   |     ^^^^^^^^^^^^^^^ value used here after move

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!


error: aborting due to previous error