@@ -12,8 +12,8 @@ use core::ops::{Deref, DerefMut};
12
12
pub unsafe trait RawLock : Default + Send + Sync {
13
13
/// Raw lock's token type.
14
14
///
15
- /// We don't enforce Send + Sync, as some locks may not satisfy it. Necessary bounds will be
16
- /// auto-derived .
15
+ /// We don't enforce Send/ Sync, as some locks may not satisfy it. We restrict them at
16
+ /// Send/Sync impl for [LockGuard] .
17
17
type Token ;
18
18
19
19
/// Acquires the raw lock.
@@ -87,13 +87,22 @@ impl<L: RawTryLock, T> Lock<L, T> {
87
87
}
88
88
89
89
/// A guard that holds the lock and dereferences the inner value.
90
- // `Send` and `Sync` are automatically derived.
91
90
#[ derive( Debug ) ]
92
91
pub struct LockGuard < ' s , L : RawLock , T > {
93
92
lock : & ' s Lock < L , T > ,
94
93
token : ManuallyDrop < L :: Token > ,
95
94
}
96
95
96
+ // Not auto derived as the auto-derived impls are incorrect. Remember, auto-derived impls are only
97
+ // correct if there are no unsafe code used in the struct's methods.
98
+
99
+ // SAFETY: Ownership of `LockGuard` implies ownership of `L::Token` and `T`. Thus, they must both be
100
+ // `Send`.
101
+ unsafe impl < L : RawLock , T : Send > Send for LockGuard < ' _ , L , T > where L :: Token : Send { }
102
+
103
+ // SAFETY: Reference to `LockGuard` implies reference to `T`. Thus, `T` must be `Sync`.
104
+ unsafe impl < L : RawLock , T : Sync > Sync for LockGuard < ' _ , L , T > { }
105
+
97
106
impl < L : RawLock , T > Drop for LockGuard < ' _ , L , T > {
98
107
fn drop ( & mut self ) {
99
108
// SAFETY: `self.token` is not used anymore in this function, and as we are `drop`ing
@@ -110,14 +119,17 @@ impl<L: RawLock, T> Deref for LockGuard<'_, L, T> {
110
119
type Target = T ;
111
120
112
121
fn deref ( & self ) -> & Self :: Target {
113
- // SAFETY: Having a `LockGuard` means the underlying lock is acquired.
122
+ // SAFETY: Having a `LockGuard` means the underlying lock is acquired, so the underlying
123
+ // data is valid. Hence we can create a shared reference to it.
114
124
unsafe { & * self . lock . data . get ( ) }
115
125
}
116
126
}
117
127
118
128
impl < L : RawLock , T > DerefMut for LockGuard < ' _ , L , T > {
119
129
fn deref_mut ( & mut self ) -> & mut Self :: Target {
120
- // SAFETY: Having a `LockGuard` means the underlying lock is held.
130
+ // SAFETY: Having a `LockGuard` means the underlying lock is acquired, so the underlying
131
+ // data is valid. Having a mutable refererence to it implies that we are the only one with
132
+ // access to the underlying data. Hence we can create a mutable reference to it.
121
133
unsafe { & mut * self . lock . data . get ( ) }
122
134
}
123
135
}
0 commit comments