Skip to content

Commit ff2d506

Browse files
committed
Auto merge of #48138 - estebank:issue-45092, r=nikomatsakis
Reword E0044 and message for `!Send` types - Reword E0044 help. - Change error message for types that don't implement `Send` CC #45092, #46678, #24909, #33307.
2 parents a4af6f0 + 1bbd4fd commit ff2d506

29 files changed

+152
-69
lines changed

src/libcore/marker.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,21 @@ pub trait Copy : Clone {
343343
/// [transmute]: ../../std/mem/fn.transmute.html
344344
#[stable(feature = "rust1", since = "1.0.0")]
345345
#[lang = "sync"]
346-
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
346+
#[rustc_on_unimplemented(
347+
message="`{Self}` cannot be shared between threads safely",
348+
label="`{Self}` cannot be shared between threads safely"
349+
)]
347350
pub unsafe auto trait Sync {
351+
// FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
352+
// lands in beta, and it has been extended to check whether a closure is
353+
// anywhere in the requirement chain, extend it as such (#48534):
354+
// ```
355+
// on(
356+
// closure,
357+
// note="`{Self}` cannot be shared safely, consider marking the closure `move`"
358+
// ),
359+
// ```
360+
348361
// Empty
349362
}
350363

src/librustc/traits/error_reporting.rs

+17-14
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
339339
.unwrap_or(trait_ref.def_id());
340340
let trait_ref = *trait_ref.skip_binder();
341341

342-
let desugaring;
343-
let method;
344342
let mut flags = vec![];
345-
let direct = match obligation.cause.code {
343+
match obligation.cause.code {
346344
ObligationCauseCode::BuiltinDerivedObligation(..) |
347-
ObligationCauseCode::ImplDerivedObligation(..) => false,
348-
_ => true
349-
};
350-
if direct {
351-
// this is a "direct", user-specified, rather than derived,
352-
// obligation.
353-
flags.push(("direct".to_string(), None));
345+
ObligationCauseCode::ImplDerivedObligation(..) => {}
346+
_ => {
347+
// this is a "direct", user-specified, rather than derived,
348+
// obligation.
349+
flags.push(("direct".to_string(), None));
350+
}
354351
}
355352

356353
if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
@@ -360,21 +357,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
360357
//
361358
// Currently I'm leaving it for what I need for `try`.
362359
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
363-
method = self.tcx.item_name(item);
360+
let method = self.tcx.item_name(item);
364361
flags.push(("from_method".to_string(), None));
365362
flags.push(("from_method".to_string(), Some(method.to_string())));
366363
}
367364
}
368365

369366
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
370-
desugaring = k.as_symbol().as_str();
367+
let desugaring = k.as_symbol().as_str();
371368
flags.push(("from_desugaring".to_string(), None));
372369
flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
373370
}
374371
let generics = self.tcx.generics_of(def_id);
375372
let self_ty = trait_ref.self_ty();
376-
let self_ty_str = self_ty.to_string();
377-
flags.push(("_Self".to_string(), Some(self_ty_str.clone())));
373+
// This is also included through the generics list as `Self`,
374+
// but the parser won't allow you to use it
375+
flags.push(("_Self".to_string(), Some(self_ty.to_string())));
376+
if let Some(def) = self_ty.ty_adt_def() {
377+
// We also want to be able to select self's original
378+
// signature with no type arguments resolved
379+
flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
380+
}
378381

379382
for param in generics.types.iter() {
380383
let name = param.name.as_str().to_string();

src/librustc_typeck/check/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1223,9 +1223,11 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
12231223
if !generics.types.is_empty() {
12241224
let mut err = struct_span_err!(tcx.sess, item.span, E0044,
12251225
"foreign items may not have type parameters");
1226-
span_help!(&mut err, item.span,
1227-
"consider using specialization instead of \
1228-
type parameters");
1226+
err.span_label(item.span, "can't have type parameters");
1227+
// FIXME: once we start storing spans for type arguments, turn this into a
1228+
// suggestion.
1229+
err.help("use specialization instead of type parameters by replacing them \
1230+
with concrete types like `u32`");
12291231
err.emit();
12301232
}
12311233

src/test/compile-fail/builtin-superkinds-double-superkind.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
trait Foo : Send+Sync { }
1515

16-
impl <T: Sync+'static> Foo for (T,) { } //~ ERROR `T: std::marker::Send` is not satisfied
16+
impl <T: Sync+'static> Foo for (T,) { }
17+
//~^ ERROR the trait bound `T: std::marker::Send` is not satisfied in `(T,)` [E0277]
1718

18-
impl <T: Send> Foo for (T,T) { } //~ ERROR `T: std::marker::Sync` is not satisfied
19+
impl <T: Send> Foo for (T,T) { }
20+
//~^ ERROR `T` cannot be shared between threads safely [E0277]
1921

2022
impl <T: Send+Sync> Foo for (T,T,T) { } // (ok)
2123

src/test/compile-fail/closure-bounds-subtype.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn give_any<F>(f: F) where F: FnOnce() {
2121

2222
fn give_owned<F>(f: F) where F: FnOnce() + Send {
2323
take_any(f);
24-
take_const_owned(f); //~ ERROR `F: std::marker::Sync` is not satisfied
24+
take_const_owned(f); //~ ERROR `F` cannot be shared between threads safely [E0277]
2525
}
2626

2727
fn main() {}

src/test/compile-fail/extern-types-not-sync-send.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn assert_send<T: ?Sized + Send>() { }
2121

2222
fn main() {
2323
assert_sync::<A>();
24-
//~^ ERROR the trait bound `A: std::marker::Sync` is not satisfied
24+
//~^ ERROR `A` cannot be shared between threads safely [E0277]
2525

2626
assert_send::<A>();
2727
//~^ ERROR the trait bound `A: std::marker::Send` is not satisfied

src/test/compile-fail/issue-16538.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod Y {
2121
}
2222

2323
static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
24-
//~^ ERROR `*const usize: std::marker::Sync` is not satisfied
24+
//~^ ERROR `*const usize` cannot be shared between threads safely [E0277]
2525
//~| ERROR cannot refer to other statics by value, use the address-of operator or a constant instead
2626
//~| ERROR E0015
2727

src/test/compile-fail/issue-17718-static-sync.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ impl !Sync for Foo {}
1717

1818
static FOO: usize = 3;
1919
static BAR: Foo = Foo;
20-
//~^ ERROR: `Foo: std::marker::Sync` is not satisfied
20+
//~^ ERROR: `Foo` cannot be shared between threads safely [E0277]
2121

2222
fn main() {}

src/test/compile-fail/issue-43733-2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<T> Key<T> {
3333
use std::thread::__FastLocalKeyInner as Key;
3434

3535
static __KEY: Key<()> = Key::new();
36-
//~^ ERROR `std::cell::UnsafeCell<std::option::Option<()>>: std::marker::Sync` is not satisfied
37-
//~| ERROR `std::cell::Cell<bool>: std::marker::Sync` is not satisfied
36+
//~^ ERROR `std::cell::UnsafeCell<std::option::Option<()>>` cannot be shared between threads
37+
//~| ERROR `std::cell::Cell<bool>` cannot be shared between threads safely [E0277]
3838

3939
fn main() {}

src/test/compile-fail/issue-7364.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ use std::cell::RefCell;
1515
// Regression test for issue 7364
1616
static boxed: Box<RefCell<isize>> = box RefCell::new(0);
1717
//~^ ERROR allocations are not allowed in statics
18-
//~| ERROR `std::cell::RefCell<isize>: std::marker::Sync` is not satisfied
18+
//~| ERROR `std::cell::RefCell<isize>` cannot be shared between threads safely [E0277]
1919

2020
fn main() { }

src/test/compile-fail/kindck-send-object.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ trait Message : Send { }
2020

2121
fn object_ref_with_static_bound_not_ok() {
2222
assert_send::<&'static (Dummy+'static)>();
23-
//~^ ERROR : std::marker::Sync` is not satisfied
23+
//~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277]
2424
}
2525

2626
fn box_object_with_no_bound_not_ok<'a>() {

src/test/compile-fail/kindck-send-object1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ trait Dummy { }
1818
// careful with object types, who knows what they close over...
1919
fn test51<'a>() {
2020
assert_send::<&'a Dummy>();
21-
//~^ ERROR : std::marker::Sync` is not satisfied
21+
//~^ ERROR `Dummy + 'a` cannot be shared between threads safely [E0277]
2222
}
2323
fn test52<'a>() {
2424
assert_send::<&'a (Dummy+Sync)>();

src/test/compile-fail/kindck-send-object2.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ fn assert_send<T:Send>() { }
1414
trait Dummy { }
1515

1616
fn test50() {
17-
assert_send::<&'static Dummy>(); //~ ERROR : std::marker::Sync` is not satisfied
17+
assert_send::<&'static Dummy>();
18+
//~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277]
1819
}
1920

2021
fn test53() {

src/test/compile-fail/mutable-enum-indirect.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ fn bar<T: Sync>(_: T) {}
2424

2525
fn main() {
2626
let x = Foo::A(NoSync);
27-
bar(&x); //~ ERROR `NoSync: std::marker::Sync` is not satisfied
27+
bar(&x);
28+
//~^ ERROR `NoSync` cannot be shared between threads safely [E0277]
2829
}

src/test/compile-fail/mutexguard-sync.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ fn main()
1818
{
1919
let m = Mutex::new(Cell::new(0i32));
2020
let guard = m.lock().unwrap();
21-
test_sync(guard); //~ ERROR the trait bound
21+
test_sync(guard);
22+
//~^ ERROR `std::cell::Cell<i32>` cannot be shared between threads safely [E0277]
2223
}

src/test/compile-fail/no_share-enum.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ fn bar<T: Sync>(_: T) {}
2222
fn main() {
2323
let x = Foo::A(NoSync);
2424
bar(x);
25-
//~^ ERROR `NoSync: std::marker::Sync` is not satisfied
25+
//~^ ERROR `NoSync` cannot be shared between threads safely [E0277]
2626
}

src/test/compile-fail/no_share-struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ fn bar<T: Sync>(_: T) {}
2020
fn main() {
2121
let x = Foo { a: 5 };
2222
bar(x);
23-
//~^ ERROR `Foo: std::marker::Sync` is not satisfied
23+
//~^ ERROR `Foo` cannot be shared between threads safely [E0277]
2424
}

src/test/compile-fail/not-sync.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ fn test<T: Sync>() {}
1616

1717
fn main() {
1818
test::<Cell<i32>>();
19-
//~^ ERROR `std::cell::Cell<i32>: std::marker::Sync` is not satisfied
19+
//~^ ERROR `std::cell::Cell<i32>` cannot be shared between threads safely [E0277]
2020
test::<RefCell<i32>>();
21-
//~^ ERROR `std::cell::RefCell<i32>: std::marker::Sync` is not satisfied
21+
//~^ ERROR `std::cell::RefCell<i32>` cannot be shared between threads safely [E0277]
2222

2323
test::<Rc<i32>>();
24-
//~^ ERROR `std::rc::Rc<i32>: std::marker::Sync` is not satisfied
24+
//~^ ERROR `std::rc::Rc<i32>` cannot be shared between threads safely [E0277]
2525
test::<Weak<i32>>();
26-
//~^ ERROR `std::rc::Weak<i32>: std::marker::Sync` is not satisfied
26+
//~^ ERROR `std::rc::Weak<i32>` cannot be shared between threads safely [E0277]
2727

2828
test::<Receiver<i32>>();
29-
//~^ ERROR `std::sync::mpsc::Receiver<i32>: std::marker::Sync` is not satisfied
29+
//~^ ERROR `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely [E0277]
3030
test::<Sender<i32>>();
31-
//~^ ERROR `std::sync::mpsc::Sender<i32>: std::marker::Sync` is not satisfied
31+
//~^ ERROR `std::sync::mpsc::Sender<i32>` cannot be shared between threads safely [E0277]
3232
}

src/test/compile-fail/phantom-oibit.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ struct Nested<T>(T);
2828
fn is_zen<T: Zen>(_: T) {}
2929

3030
fn not_sync<T>(x: Guard<T>) {
31-
is_zen(x) //~ error: `T: std::marker::Sync` is not satisfied
31+
is_zen(x)
32+
//~^ ERROR `T` cannot be shared between threads safely [E0277]
3233
}
3334

3435
fn nested_not_sync<T>(x: Nested<Guard<T>>) {
35-
is_zen(x) //~ error: `T: std::marker::Sync` is not satisfied
36+
is_zen(x)
37+
//~^ ERROR `T` cannot be shared between threads safely [E0277]
3638
}
3739

3840
fn main() {}

src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ fn is_sync<T: Sync>() {}
4343
fn main() {
4444
is_sync::<MySync>();
4545
is_sync::<MyNotSync>();
46-
//~^ ERROR `MyNotSync: std::marker::Sync` is not satisfied
46+
//~^ ERROR `MyNotSync` cannot be shared between threads safely [E0277]
4747

4848
is_sync::<MyTypeWUnsafe>();
49-
//~^ ERROR `std::cell::UnsafeCell<u8>: std::marker::Sync` is not satisfied
49+
//~^ ERROR `std::cell::UnsafeCell<u8>` cannot be shared between threads safely [E0277]
5050

5151
is_sync::<MyTypeManaged>();
52-
//~^ ERROR `Managed: std::marker::Sync` is not satisfied
52+
//~^ ERROR `Managed` cannot be shared between threads safely [E0277]
5353
}

src/test/compile-fail/typeck-unsafe-always-share.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ fn test<T: Sync>(s: T) {}
2727
fn main() {
2828
let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0)});
2929
test(us);
30-
//~^ ERROR `std::cell::UnsafeCell<MySync<{integer}>>: std::marker::Sync` is not satisfied
30+
//~^ ERROR `std::cell::UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
3131

3232
let uns = UnsafeCell::new(NoSync);
3333
test(uns);
34-
//~^ ERROR `std::cell::UnsafeCell<NoSync>: std::marker::Sync` is not satisfied
34+
//~^ ERROR `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely [E0277]
3535

3636
let ms = MySync{u: uns};
3737
test(ms);
38-
//~^ ERROR `std::cell::UnsafeCell<NoSync>: std::marker::Sync` is not satisfied
38+
//~^ ERROR `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely [E0277]
3939

4040
test(NoSync);
41-
//~^ ERROR `NoSync: std::marker::Sync` is not satisfied
41+
//~^ ERROR `NoSync` cannot be shared between threads safely [E0277]
4242
}

src/test/ui/closure-move-sync.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::thread;
12+
use std::sync::mpsc::channel;
13+
14+
fn bar() {
15+
let (send, recv) = channel();
16+
let t = thread::spawn(|| {
17+
recv.recv().unwrap();
18+
//~^^ ERROR `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
19+
});
20+
21+
send.send(());
22+
23+
t.join().unwrap();
24+
}
25+
26+
fn foo() {
27+
let (tx, _rx) = channel();
28+
thread::spawn(|| tx.send(()).unwrap());
29+
//~^ ERROR `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
30+
}
31+
32+
fn main() {}

src/test/ui/closure-move-sync.stderr

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
2+
--> $DIR/closure-move-sync.rs:16:13
3+
|
4+
LL | let t = thread::spawn(|| {
5+
| ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
6+
|
7+
= help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
8+
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Receiver<()>`
9+
= note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:16:27: 19:6 recv:&std::sync::mpsc::Receiver<()>]`
10+
= note: required by `std::thread::spawn`
11+
12+
error[E0277]: `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
13+
--> $DIR/closure-move-sync.rs:28:5
14+
|
15+
LL | thread::spawn(|| tx.send(()).unwrap());
16+
| ^^^^^^^^^^^^^ `std::sync::mpsc::Sender<()>` cannot be shared between threads safely
17+
|
18+
= help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>`
19+
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<()>`
20+
= note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:28:19: 28:42 tx:&std::sync::mpsc::Sender<()>]`
21+
= note: required by `std::thread::spawn`
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/error-codes/E0044.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -8,7 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
extern { fn some_func<T>(x: T); } //~ ERROR E0044
11+
extern {
12+
fn sqrt<T>(f: T) -> T;
13+
//~^ ERROR foreign items may not have type parameters [E0044]
14+
//~| HELP use specialization instead of type parameters by replacing them with concrete types
15+
//~| NOTE can't have type parameters
16+
}
1217

1318
fn main() {
1419
}

src/test/ui/error-codes/E0044.stderr

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
error[E0044]: foreign items may not have type parameters
2-
--> $DIR/E0044.rs:11:10
2+
--> $DIR/E0044.rs:12:5
33
|
4-
LL | extern { fn some_func<T>(x: T); } //~ ERROR E0044
5-
| ^^^^^^^^^^^^^^^^^^^^^^
4+
LL | fn sqrt<T>(f: T) -> T;
5+
| ^^^^^^^^^^^^^^^^^^^^^^ can't have type parameters
66
|
7-
help: consider using specialization instead of type parameters
8-
--> $DIR/E0044.rs:11:10
9-
|
10-
LL | extern { fn some_func<T>(x: T); } //~ ERROR E0044
11-
| ^^^^^^^^^^^^^^^^^^^^^^
7+
= help: use specialization instead of type parameters by replacing them with concrete types like `u32`
128

139
error: aborting due to previous error
1410

0 commit comments

Comments
 (0)