diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index fd57491fcc765..51d2e29e6b15a 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -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", + label="`{Self}` cannot be shared safely, if using a closure consider marking it `move`" + ), + on( + _Self="std::sync::mpsc::Sender", + 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" )] diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index cd2d0d7e2a043..9cdab856b05ec 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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(); diff --git a/src/test/ui/closure-move-sync.rs b/src/test/ui/closure-move-sync.rs new file mode 100644 index 0000000000000..e096e7ca3a06b --- /dev/null +++ b/src/test/ui/closure-move-sync.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/ui/closure-move-sync.stderr b/src/test/ui/closure-move-sync.stderr new file mode 100644 index 0000000000000..fc53deeeef7ad --- /dev/null +++ b/src/test/ui/closure-move-sync.stderr @@ -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 +