Skip to content

Commit

Permalink
Suggest using Arc on !Send/!Sync types
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Aug 9, 2023
1 parent 19a647d commit 9de1a47
Show file tree
Hide file tree
Showing 113 changed files with 223 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2743,6 2743,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::BindingObligation(item_def_id, span)
| ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
if self.tcx.is_diagnostic_item(sym::Send, item_def_id)
|| self.tcx.lang_items().sync_trait() == Some(item_def_id)
{
return;
}

let item_name = tcx.def_path_str(item_def_id);
let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
let mut multispan = MultiSpan::from(span);
Expand Down
10 changes: 8 additions & 2 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 76,11 @@ macro marker_impls {
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Send")]
#[rustc_on_unimplemented(
on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"),
message = "`{Self}` cannot be sent between threads safely",
label = "`{Self}` cannot be sent between threads safely"
label = "`{Self}` cannot be sent between threads safely",
note = "consider using `std::sync::Arc<{Self}>`; for more information visit \
<https://doc.rust-lang.org/book/ch16-03-shared-state.html>"
)]
pub unsafe auto trait Send {
// empty.
Expand Down Expand Up @@ -628,8 631,11 @@ impl<T: ?Sized> Copy for &T {}
any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
),
on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"),
message = "`{Self}` cannot be shared between threads safely",
label = "`{Self}` cannot be shared between threads safely"
label = "`{Self}` cannot be shared between threads safely",
note = "consider using `std::sync::Arc<{Self}>`; for more information visit \
<https://doc.rust-lang.org/book/ch16-03-shared-state.html>"
)]
pub unsafe auto trait Sync {
// FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | type C: Clone Iterator<Item: Send Iterator<Item: for<'a> Lam<&'a u8
| ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
= note: consider using `std::sync::Arc<<<Self as Case1>::C as Iterator>::Item>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
Expand All @@ -29,6 30,7 @@ LL | type C: Clone Iterator<Item: Send Iterator<Item: for<'a> Lam<&'a u8
| ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
= note: consider using `std::sync::Arc<<<Self as Case1>::C as Iterator>::Item>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 14,7 @@ LL | is_send(foo::<T>());
| ^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>`
= note: consider using `std::sync::Arc<impl Future<Output = Result<(), ()>>>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/basic.rs:13:5
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_send(foo(Some(true)));
| ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:11:15
|
Expand Down Expand Up @@ -32,6 33,7 @@ LL | is_send(foo2(Some(true)));
| required by a bound introduced by this call
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: required because it's used within this `async fn` body
--> $DIR/async-await-let-else.rs:27:29
|
Expand Down Expand Up @@ -64,6 66,7 @@ LL | is_send(foo3(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:33:29
|
Expand All @@ -85,6 88,7 @@ LL | is_send(foo4(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:41:15
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_send(foo(Some(true)));
| ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:11:15
|
Expand All @@ -30,6 31,7 @@ LL | is_send(foo2(Some(true)));
| required by a bound introduced by this call
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: required because it's used within this `async fn` body
--> $DIR/async-await-let-else.rs:27:29
|
Expand Down Expand Up @@ -62,6 64,7 @@ LL | is_send(foo3(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:33:29
|
Expand All @@ -82,6 85,7 @@ LL | is_send(foo4(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:41:15
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_send(foo(Some(true)));
| ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:11:15
|
Expand All @@ -27,6 28,7 @@ LL | is_send(foo2(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:23:27
|
Expand All @@ -49,6 51,7 @@ LL | is_send(foo3(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:33:29
|
Expand All @@ -70,6 73,7 @@ LL | is_send(foo4(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:41:15
|
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:36:26
|
Expand All @@ -28,6 29,7 @@ LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
= note: consider using `std::sync::Arc<dyn std::fmt::Write>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:49:15
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:36:26
|
Expand All @@ -25,6 26,7 @@ LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
= note: consider using `std::sync::Arc<dyn std::fmt::Write>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:49:15
|
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(local_dropped_before_await());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:27:11
|
Expand All @@ -28,6 29,7 @@ LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:36:26
|
Expand All @@ -51,6 53,7 @@ LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
= note: consider using `std::sync::Arc<dyn std::fmt::Write>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:49:15
|
Expand All @@ -75,6 78,7 @@ LL | assert_send(non_sync_with_method_call_panic());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call_panic` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
= note: consider using `std::sync::Arc<dyn std::fmt::Write>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:56:15
|
Expand All @@ -99,6 103,7 @@ LL | assert_send(non_sync_with_method_call_infinite_loop());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call_infinite_loop` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
= note: consider using `std::sync::Arc<dyn std::fmt::Write>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:63:15
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/drop-track-field-assign-nonsend.rs:23:39
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/drop-track-field-assign-nonsend.rs:23:39
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/drop-track-field-assign-nonsend.rs:23:39
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/field-assign-nonsend.rs:23:39
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/field-assign-nonsend.rs:23:39
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/field-assign-nonsend.rs:23:39
|
Expand Down
1 change: 1 addition & 0 deletions tests/ui/async-await/in-trait/missing-send-bound.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | assert_is_send(test::<T>());
| ^^^^^^^^^^^ future returned by `test` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
= note: consider using `std::sync::Arc<impl Future<Output = ()>>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/missing-send-bound.rs:10:5
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_sync(bar());
| ^^^^^ future returned by `bar` is not `Sync`
|
= help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
= note: consider using `std::sync::Arc<Foo>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Sync` as this value is used across an await
--> $DIR/issue-64130-1-sync.rs:18:11
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_sync(bar());
| ^^^^^ future returned by `bar` is not `Sync`
|
= help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
= note: consider using `std::sync::Arc<Foo>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Sync` as this value is used across an await
--> $DIR/issue-64130-1-sync.rs:18:11
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_sync(bar());
| ^^^^^ future returned by `bar` is not `Sync`
|
= help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
= note: consider using `std::sync::Arc<Foo>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Sync` as this value is used across an await
--> $DIR/issue-64130-1-sync.rs:18:11
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | pub fn foo() -> impl Future Send {
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `(dyn Any Send 'static)`
= note: consider using `std::sync::Arc<(dyn Any Send 'static)>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/issue-64130-4-async-move.rs:27:23
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | is_send(foo());
| ^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
= note: consider using `std::sync::Arc<MutexGuard<'_, u32>>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/issue-64130-non-send-future-diags.rs:17:11
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 10,7 @@ LL | | });
| |_____^ future created by async block is not `Send`
|
= help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()`
= note: consider using `std::sync::Arc<*mut ()>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/issue-67252-unnamed-future.rs:23:17
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ LL | spawn(async {
| ^^^^^ future created by async block is not `Send`
|
= help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()`
= note: consider using `std::sync::Arc<*mut ()>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/issue-67252-unnamed-future.rs:23:17
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 10,7 @@ LL | | });
| |_____^ future created by async block is not `Send`
|
= help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()`
= note: consider using `std::sync::Arc<*mut ()>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as this value is used across an await
--> $DIR/issue-67252-unnamed-future.rs:23:17
|
Expand Down
Loading

0 comments on commit 9de1a47

Please sign in to comment.