From e1e347d2725b9c9dd4a70b63eb08532ca9687652 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 9 Nov 2021 20:27:27 -0800 Subject: [PATCH 1/2] Require inventory element type to be Sync --- src/lib.rs | 2 +- tests/ui/collect-unsized.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 87258fa..bfaed7f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,7 +149,7 @@ struct Node { /// inventory::iter::.into_iter().count() /// } /// ``` -pub trait Collect: Sized + 'static { +pub trait Collect: Sync + Sized + 'static { #[doc(hidden)] fn registry() -> &'static Registry; } diff --git a/tests/ui/collect-unsized.stderr b/tests/ui/collect-unsized.stderr index 41f2aa8..c6f5841 100644 --- a/tests/ui/collect-unsized.stderr +++ b/tests/ui/collect-unsized.stderr @@ -13,8 +13,8 @@ note: required because it appears within the type `Unsized` note: required by a bound in `Collect` --> src/lib.rs | - | pub trait Collect: Sized + 'static { - | ^^^^^ required by this bound in `Collect` + | pub trait Collect: Sync + Sized + 'static { + | ^^^^^ required by this bound in `Collect` = note: this error originates in the macro `inventory::collect` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `str` cannot be known at compilation time From ea173f9ca99701b148ae01bb768bdd01a29f7462 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 9 Nov 2021 20:26:05 -0800 Subject: [PATCH 2/2] Add ui test of sync bound --- tests/ui/non-sync.rs | 21 +++++++++++++++++++++ tests/ui/non-sync.stderr | 18 ++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/ui/non-sync.rs create mode 100644 tests/ui/non-sync.stderr diff --git a/tests/ui/non-sync.rs b/tests/ui/non-sync.rs new file mode 100644 index 0000000..190655d --- /dev/null +++ b/tests/ui/non-sync.rs @@ -0,0 +1,21 @@ +use std::rc::Rc; +use std::thread; + +struct Thing(Rc); + +inventory::collect!(Thing); + +fn clone_all() { + for thing in inventory::iter:: { + let _ = Rc::clone(&thing.0); + } +} + +fn main() { + // It would be bad if this were allowed. These threads would race on the + // nonatomic reference counts. + let thread1 = thread::spawn(clone_all); + let thread2 = thread::spawn(clone_all); + thread1.join().unwrap(); + thread2.join().unwrap(); +} diff --git a/tests/ui/non-sync.stderr b/tests/ui/non-sync.stderr new file mode 100644 index 0000000..4eca860 --- /dev/null +++ b/tests/ui/non-sync.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Rc` cannot be shared between threads safely + --> tests/ui/non-sync.rs:6:1 + | +6 | inventory::collect!(Thing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc` cannot be shared between threads safely + | + = help: within `Thing`, the trait `Sync` is not implemented for `Rc` +note: required because it appears within the type `Thing` + --> tests/ui/non-sync.rs:4:8 + | +4 | struct Thing(Rc); + | ^^^^^ +note: required by a bound in `Collect` + --> src/lib.rs + | + | pub trait Collect: Sync + Sized + 'static { + | ^^^^ required by this bound in `Collect` + = note: this error originates in the macro `inventory::collect` (in Nightly builds, run with -Z macro-backtrace for more info)