Suggest using move
when trying to share ...::channel::{Receiver, Sender}
Extend `rustc_on_unimplemented` to match on ADT without evaluating type arguments.
This commit is contained in:
parent
6d8a173980
commit
fe1975448c
@ -344,6 +344,14 @@ pub trait Copy : Clone {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "sync"]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
_Self="std::sync::mpsc::Receiver<T>",
|
||||
label="`{Self}` cannot be shared safely, if using a closure consider marking it `move`"
|
||||
),
|
||||
on(
|
||||
_Self="std::sync::mpsc::Sender<T>",
|
||||
label="`{Self}` cannot be shared safely, if using a closure consider marking it `move`"
|
||||
),
|
||||
message="`{Self}` cannot be shared between threads safely",
|
||||
label="`{Self}` cannot be shared between threads safely"
|
||||
)]
|
||||
|
@ -338,18 +338,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
.unwrap_or(trait_ref.def_id());
|
||||
let trait_ref = *trait_ref.skip_binder();
|
||||
|
||||
let desugaring;
|
||||
let method;
|
||||
let mut flags = vec![];
|
||||
let direct = match obligation.cause.code {
|
||||
match obligation.cause.code {
|
||||
ObligationCauseCode::BuiltinDerivedObligation(..) |
|
||||
ObligationCauseCode::ImplDerivedObligation(..) => false,
|
||||
_ => true
|
||||
};
|
||||
if direct {
|
||||
// this is a "direct", user-specified, rather than derived,
|
||||
// obligation.
|
||||
flags.push(("direct".to_string(), None));
|
||||
ObligationCauseCode::ImplDerivedObligation(..) => {}
|
||||
_ => {
|
||||
// this is a "direct", user-specified, rather than derived,
|
||||
// obligation.
|
||||
flags.push(("direct".to_string(), None));
|
||||
}
|
||||
}
|
||||
|
||||
if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
|
||||
@ -359,21 +356,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
//
|
||||
// Currently I'm leaving it for what I need for `try`.
|
||||
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
|
||||
method = self.tcx.item_name(item);
|
||||
let method = self.tcx.item_name(item);
|
||||
flags.push(("from_method".to_string(), None));
|
||||
flags.push(("from_method".to_string(), Some(method.to_string())));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
|
||||
desugaring = k.as_symbol().as_str();
|
||||
let desugaring = k.as_symbol().as_str();
|
||||
flags.push(("from_desugaring".to_string(), None));
|
||||
flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
|
||||
}
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let self_ty_str = self_ty.to_string();
|
||||
flags.push(("_Self".to_string(), Some(self_ty_str.clone())));
|
||||
// This is also included through the generics list as `Self`,
|
||||
// but the parser won't allow you to use it
|
||||
flags.push(("_Self".to_string(), Some(self_ty.to_string())));
|
||||
if let Some(def) = self_ty.ty_adt_def() {
|
||||
// We also want to be able to select self's original
|
||||
// signature with no type arguments resolved
|
||||
flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
|
||||
}
|
||||
|
||||
for param in generics.types.iter() {
|
||||
let name = param.name.as_str().to_string();
|
||||
|
32
src/test/ui/closure-move-sync.rs
Normal file
32
src/test/ui/closure-move-sync.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
use std::thread;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
fn bar() {
|
||||
let (send, recv) = channel();
|
||||
let t = thread::spawn(|| {
|
||||
recv.recv().unwrap();
|
||||
//~^^ ERROR `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
|
||||
});
|
||||
|
||||
send.send(());
|
||||
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let (tx, _rx) = channel();
|
||||
thread::spawn(|| tx.send(()).unwrap());
|
||||
//~^ ERROR `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
|
||||
}
|
||||
|
||||
fn main() {}
|
24
src/test/ui/closure-move-sync.stderr
Normal file
24
src/test/ui/closure-move-sync.stderr
Normal file
@ -0,0 +1,24 @@
|
||||
error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
|
||||
--> $DIR/closure-move-sync.rs:16:13
|
||||
|
|
||||
16 | let t = thread::spawn(|| {
|
||||
| ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared safely, if using a closure consider marking it `move`
|
||||
|
|
||||
= help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
|
||||
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Receiver<()>`
|
||||
= note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:16:27: 19:6 recv:&std::sync::mpsc::Receiver<()>]`
|
||||
= note: required by `std::thread::spawn`
|
||||
|
||||
error[E0277]: `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
|
||||
--> $DIR/closure-move-sync.rs:28:5
|
||||
|
|
||||
28 | thread::spawn(|| tx.send(()).unwrap());
|
||||
| ^^^^^^^^^^^^^ `std::sync::mpsc::Sender<()>` cannot be shared safely, if using a closure consider marking it `move`
|
||||
|
|
||||
= help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>`
|
||||
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<()>`
|
||||
= note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:28:19: 28:42 tx:&std::sync::mpsc::Sender<()>]`
|
||||
= note: required by `std::thread::spawn`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
x
Reference in New Issue
Block a user