@@ -118,8 +118,9 @@ impl<'py> PyBitGeneratorMethods<'py> for Bound<'py, PyBitGenerator> {
118
118
} ;
119
119
Ok ( PyBitGeneratorGuard {
120
120
raw_bitgen : non_null,
121
- _capsule : capsule,
122
- lock,
121
+ _capsule : capsule. unbind ( ) ,
122
+ lock : lock. unbind ( ) ,
123
+ py : self . py ( ) ,
123
124
} )
124
125
}
125
126
}
@@ -134,8 +135,14 @@ impl<'py> TryFrom<&Bound<'py, PyBitGenerator>> for PyBitGeneratorGuard<'py> {
134
135
/// [`PyBitGenerator`] lock allowing to access its methods without holding the GIL.
135
136
pub struct PyBitGeneratorGuard < ' py > {
136
137
raw_bitgen : NonNull < npy_bitgen > ,
137
- _capsule : Bound < ' py , PyCapsule > ,
138
- lock : Bound < ' py , PyAny > ,
138
+ /// This field makes sure the `raw_bitgen` inside the capsule doesn’t get deallocated.
139
+ _capsule : Py < PyCapsule > ,
140
+ /// This lock makes sure no other threads try to use the BitGenerator while we do.
141
+ lock : Py < PyAny > ,
142
+ /// This should be an unsafe field (https://github.com/rust-lang/rust/issues/132922)
143
+ ///
144
+ /// SAFETY: only use this in `Drop::drop` (when we are sure the GIL is held).
145
+ py : Python < ' py > ,
139
146
}
140
147
141
148
// SAFETY: we can’t have public APIs that access the Python objects,
@@ -145,18 +152,17 @@ unsafe impl Send for PyBitGeneratorGuard<'_> {}
145
152
impl Drop for PyBitGeneratorGuard < ' _ > {
146
153
fn drop ( & mut self ) {
147
154
// ignore errors. This includes when `try_drop` was called manually
148
- let _ = self . lock . call_method0 ( "release" ) ;
155
+ let _ = self . lock . bind ( self . py ) . call_method0 ( "release" ) ;
149
156
}
150
157
}
151
158
152
159
// SAFETY: We hold the `BitGenerator.lock`,
153
160
// so nothing apart from us is allowed to change its state.
154
- impl PyBitGeneratorGuard < ' _ > {
161
+ impl < ' py > PyBitGeneratorGuard < ' py > {
155
162
/// Drop the lock manually before `Drop::drop` tries to do it (used for testing).
156
- /// SAFETY: Can’t be used inside of a `Python::allow_threads` block.
157
163
#[ allow( dead_code) ]
158
- unsafe fn try_drop ( self ) -> PyResult < ( ) > {
159
- self . lock . call_method0 ( "release" ) ?;
164
+ fn try_drop ( self , py : Python < ' py > ) -> PyResult < ( ) > {
165
+ self . lock . bind ( py ) . call_method0 ( "release" ) ?;
160
166
Ok ( ( ) )
161
167
}
162
168
@@ -223,7 +229,7 @@ mod tests {
223
229
py. allow_threads ( || {
224
230
let _ = bitgen. next_raw ( ) ;
225
231
} ) ;
226
- assert ! ( unsafe { bitgen. try_drop( ) } . is_ok( ) ) ;
232
+ assert ! ( bitgen. try_drop( py ) . is_ok( ) ) ;
227
233
Ok ( ( ) )
228
234
} )
229
235
}
@@ -240,7 +246,7 @@ mod tests {
240
246
assert ! ( bitgen. random_ratio( 1 , 1 ) ) ;
241
247
assert ! ( !bitgen. random_ratio( 0 , 1 ) ) ;
242
248
} ) ;
243
- assert ! ( unsafe { bitgen. try_drop( ) } . is_ok( ) ) ;
249
+ assert ! ( bitgen. try_drop( py ) . is_ok( ) ) ;
244
250
Ok ( ( ) )
245
251
} )
246
252
}
@@ -251,7 +257,7 @@ mod tests {
251
257
let generator = get_bit_generator ( py) ?;
252
258
let bitgen = generator. lock ( ) ?;
253
259
assert ! ( generator. lock( ) . is_err( ) ) ;
254
- assert ! ( unsafe { bitgen. try_drop( ) } . is_ok( ) ) ;
260
+ assert ! ( bitgen. try_drop( py ) . is_ok( ) ) ;
255
261
Ok ( ( ) )
256
262
} )
257
263
}
0 commit comments