Rollup merge of #106944 - Nilstrieb:there-once-was-a-diagnostic, r=WaffleLapkin

Suggest using a lock for `*Cell: Sync` bounds

I mostly did this for `OnceCell<T>` at first because users will be confused to see that the `OnceCell<T>` in `std` isn't `Sync` but then extended it to `Cell<T>` and `RefCell<T>` as well.
This commit is contained in:
Matthias Krüger 2023-01-25 22:19:52 +01:00 committed by GitHub
commit 22e62a4fca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 233 additions and 5 deletions

View File

@ -298,3 +298,7 @@ impl<T> const From<T> for OnceCell<T> {
OnceCell { inner: UnsafeCell::new(Some(value)) }
}
}
// Just like for `Cell<T>` this isn't needed, but results in nicer error messages.
#[unstable(feature = "once_cell", issue = "74465")]
impl<T> !Sync for OnceCell<T> {}

View File

@ -469,6 +469,62 @@ pub macro Copy($item:item) {
#[cfg_attr(not(test), rustc_diagnostic_item = "Sync")]
#[lang = "sync"]
#[rustc_on_unimplemented(
on(
_Self = "std::cell::OnceCell<T>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead"
),
on(
_Self = "std::cell::Cell<u8>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead",
),
on(
_Self = "std::cell::Cell<u16>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU16` instead",
),
on(
_Self = "std::cell::Cell<u32>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU32` instead",
),
on(
_Self = "std::cell::Cell<u64>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU64` instead",
),
on(
_Self = "std::cell::Cell<usize>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicUsize` instead",
),
on(
_Self = "std::cell::Cell<i8>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI8` instead",
),
on(
_Self = "std::cell::Cell<i16>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI16` instead",
),
on(
_Self = "std::cell::Cell<i32>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead",
),
on(
_Self = "std::cell::Cell<i64>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI64` instead",
),
on(
_Self = "std::cell::Cell<isize>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicIsize` instead",
),
on(
_Self = "std::cell::Cell<bool>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead",
),
on(
_Self = "std::cell::Cell<T>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`",
),
on(
_Self = "std::cell::RefCell<T>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
),
message = "`{Self}` cannot be shared between threads safely",
label = "`{Self}` cannot be shared between threads safely"
)]

View File

@ -5,6 +5,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:34:17
|
@ -23,6 +24,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:43:17
|
@ -43,6 +45,7 @@ LL | require_send(send_fut);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this `async fn` body
--> $DIR/issue-68112.rs:50:31

View File

@ -5,6 +5,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:34:17
|
@ -23,6 +24,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:43:17
|
@ -43,6 +45,7 @@ LL | require_send(send_fut);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this `async fn` body
--> $DIR/issue-68112.rs:50:31

View File

@ -40,6 +40,7 @@ fn test1() {
require_send(send_gen);
//~^ ERROR generator cannot be sent between threads
//~| NOTE not `Send`
//~| NOTE use `std::sync::RwLock` instead
}
pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
@ -66,6 +67,7 @@ fn test2() {
//~| NOTE required for
//~| NOTE required by a bound introduced by this call
//~| NOTE captures the following types
//~| NOTE use `std::sync::RwLock` instead
}
fn main() {}

View File

@ -5,6 +5,7 @@ LL | require_send(send_gen);
| ^^^^^^^^ generator is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: generator is not `Send` as this value is used across a yield
--> $DIR/issue-68112.rs:36:9
|
@ -23,7 +24,7 @@ LL | fn require_send(_: impl Send) {}
| ^^^^ required by this bound in `require_send`
error[E0277]: `RefCell<i32>` cannot be shared between threads safely
--> $DIR/issue-68112.rs:63:18
--> $DIR/issue-68112.rs:64:18
|
LL | require_send(send_gen);
| ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
@ -31,25 +32,26 @@ LL | require_send(send_gen);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this generator
--> $DIR/issue-68112.rs:48:5
--> $DIR/issue-68112.rs:49:5
|
LL | || {
| ^^
note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
--> $DIR/issue-68112.rs:45:30
--> $DIR/issue-68112.rs:46:30
|
LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
--> $DIR/issue-68112.rs:53:34
--> $DIR/issue-68112.rs:54:34
|
LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`, `()`
note: required because it's used within this generator
--> $DIR/issue-68112.rs:59:20
--> $DIR/issue-68112.rs:60:20
|
LL | let send_gen = || {
| ^^

View File

@ -12,6 +12,7 @@ LL | | });
| |_____^ `Cell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
= note: required for `&Cell<i32>` to implement `Send`
note: required because it's used within this generator
--> $DIR/not-send-sync.rs:16:17
@ -36,6 +37,7 @@ LL | | });
| |_____^ generator is not `Sync`
|
= help: within `[generator@$DIR/not-send-sync.rs:9:17: 9:19]`, the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
note: generator is not `Sync` as this value is used across a yield
--> $DIR/not-send-sync.rs:12:9
|

View File

@ -5,6 +5,7 @@ LL | require_send(send_gen);
| ^^^^^^^^ generator is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: generator is not `Send` as this value is used across a yield
--> $DIR/generator-print-verbose-1.rs:35:9
|
@ -29,6 +30,7 @@ LL | require_send(send_gen);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this generator
--> $DIR/generator-print-verbose-1.rs:42:5

View File

@ -12,6 +12,7 @@ LL | | });
| |_____^ `Cell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
= note: required for `&'_#4r Cell<i32>` to implement `Send`
note: required because it's used within this generator
--> $DIR/generator-print-verbose-2.rs:19:17
@ -36,6 +37,7 @@ LL | | });
| |_____^ generator is not `Sync`
|
= help: within `[main::{closure#0} upvar_tys=() {Cell<i32>, ()}]`, the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
note: generator is not `Sync` as this value is used across a yield
--> $DIR/generator-print-verbose-2.rs:15:9
|

View File

@ -5,6 +5,7 @@ LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
| ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `RefCell<isize>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Unique<RefCell<isize>>` to implement `Sync`
= note: required because it appears within the type `Box<RefCell<isize>>`
= note: shared static variables must have a type that implements `Sync`

View File

@ -5,6 +5,7 @@ LL | test::<Cell<i32>>();
| ^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
note: required by a bound in `test`
--> $DIR/not-sync.rs:5:12
|
@ -18,6 +19,7 @@ LL | test::<RefCell<i32>>();
| ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required by a bound in `test`
--> $DIR/not-sync.rs:5:12
|

View File

@ -7,6 +7,7 @@ LL | test_sync(guard);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
= note: required for `MutexGuard<'_, Cell<i32>>` to implement `Sync`
note: required by a bound in `test_sync`
--> $DIR/mutexguard-sync.rs:5:17

View File

@ -0,0 +1,31 @@
fn require_sync<T: Sync>() {}
//~^ NOTE required by this bound in `require_sync`
//~| NOTE required by this bound in `require_sync`
//~| NOTE required by this bound in `require_sync`
//~| NOTE required by this bound in `require_sync`
//~| NOTE required by a bound in `require_sync`
//~| NOTE required by a bound in `require_sync`
//~| NOTE required by a bound in `require_sync`
//~| NOTE required by a bound in `require_sync`
fn main() {
require_sync::<std::cell::Cell<()>>();
//~^ ERROR `Cell<()>` cannot be shared between threads safely
//~| NOTE `Cell<()>` cannot be shared between threads safely
//~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`
require_sync::<std::cell::Cell<u8>>();
//~^ ERROR `Cell<u8>` cannot be shared between threads safely
//~| NOTE `Cell<u8>` cannot be shared between threads safely
//~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead
require_sync::<std::cell::Cell<i32>>();
//~^ ERROR `Cell<i32>` cannot be shared between threads safely
//~| NOTE `Cell<i32>` cannot be shared between threads safely
//~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
require_sync::<std::cell::Cell<bool>>();
//~^ ERROR `Cell<bool>` cannot be shared between threads safely
//~| NOTE `Cell<bool>` cannot be shared between threads safely
//~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead
}

View File

@ -0,0 +1,59 @@
error[E0277]: `Cell<()>` cannot be shared between threads safely
--> $DIR/suggest-cell.rs:12:20
|
LL | require_sync::<std::cell::Cell<()>>();
| ^^^^^^^^^^^^^^^^^^^ `Cell<()>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<()>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`
note: required by a bound in `require_sync`
--> $DIR/suggest-cell.rs:1:20
|
LL | fn require_sync<T: Sync>() {}
| ^^^^ required by this bound in `require_sync`
error[E0277]: `Cell<u8>` cannot be shared between threads safely
--> $DIR/suggest-cell.rs:17:20
|
LL | require_sync::<std::cell::Cell<u8>>();
| ^^^^^^^^^^^^^^^^^^^ `Cell<u8>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<u8>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead
note: required by a bound in `require_sync`
--> $DIR/suggest-cell.rs:1:20
|
LL | fn require_sync<T: Sync>() {}
| ^^^^ required by this bound in `require_sync`
error[E0277]: `Cell<i32>` cannot be shared between threads safely
--> $DIR/suggest-cell.rs:22:20
|
LL | require_sync::<std::cell::Cell<i32>>();
| ^^^^^^^^^^^^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
note: required by a bound in `require_sync`
--> $DIR/suggest-cell.rs:1:20
|
LL | fn require_sync<T: Sync>() {}
| ^^^^ required by this bound in `require_sync`
error[E0277]: `Cell<bool>` cannot be shared between threads safely
--> $DIR/suggest-cell.rs:27:20
|
LL | require_sync::<std::cell::Cell<bool>>();
| ^^^^^^^^^^^^^^^^^^^^^ `Cell<bool>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<bool>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead
note: required by a bound in `require_sync`
--> $DIR/suggest-cell.rs:1:20
|
LL | fn require_sync<T: Sync>() {}
| ^^^^ required by this bound in `require_sync`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,12 @@
#![feature(once_cell)]
fn require_sync<T: Sync>() {}
//~^ NOTE required by this bound in `require_sync`
//~| NOTE required by a bound in `require_sync`
fn main() {
require_sync::<std::cell::OnceCell<()>>();
//~^ ERROR `OnceCell<()>` cannot be shared between threads safely
//~| NOTE `OnceCell<()>` cannot be shared between threads safely
//~| NOTE use `std::sync::OnceLock` instead
}

View File

@ -0,0 +1,17 @@
error[E0277]: `OnceCell<()>` cannot be shared between threads safely
--> $DIR/suggest-once-cell.rs:8:20
|
LL | require_sync::<std::cell::OnceCell<()>>();
| ^^^^^^^^^^^^^^^^^^^^^^^ `OnceCell<()>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `OnceCell<()>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead
note: required by a bound in `require_sync`
--> $DIR/suggest-once-cell.rs:3:20
|
LL | fn require_sync<T: Sync>() {}
| ^^^^ required by this bound in `require_sync`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,12 @@
#![feature(once_cell)]
fn require_sync<T: Sync>() {}
//~^ NOTE required by this bound in `require_sync`
//~| NOTE required by a bound in `require_sync`
fn main() {
require_sync::<std::cell::RefCell<()>>();
//~^ ERROR `RefCell<()>` cannot be shared between threads safely
//~| NOTE `RefCell<()>` cannot be shared between threads safely
//~| NOTE use `std::sync::RwLock` instead
}

View File

@ -0,0 +1,17 @@
error[E0277]: `RefCell<()>` cannot be shared between threads safely
--> $DIR/suggest-ref-cell.rs:8:20
|
LL | require_sync::<std::cell::RefCell<()>>();
| ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<()>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `RefCell<()>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required by a bound in `require_sync`
--> $DIR/suggest-ref-cell.rs:3:20
|
LL | fn require_sync<T: Sync>() {}
| ^^^^ required by this bound in `require_sync`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.