@@ -118,8 +118,9 @@ impl<'py> PyBitGeneratorMethods<'py> for Bound<'py, PyBitGenerator> {
118118 } ;
119119 Ok ( PyBitGeneratorGuard {
120120 raw_bitgen : non_null,
121- _capsule : capsule,
122- lock,
121+ _capsule : capsule. unbind ( ) ,
122+ lock : lock. unbind ( ) ,
123+ py : self . py ( ) ,
123124 } )
124125 }
125126}
@@ -134,8 +135,14 @@ impl<'py> TryFrom<&Bound<'py, PyBitGenerator>> for PyBitGeneratorGuard<'py> {
134135/// [`PyBitGenerator`] lock allowing to access its methods without holding the GIL.
135136pub struct PyBitGeneratorGuard < ' py > {
136137 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 > ,
139146}
140147
141148// SAFETY: we can’t have public APIs that access the Python objects,
@@ -145,18 +152,17 @@ unsafe impl Send for PyBitGeneratorGuard<'_> {}
145152impl Drop for PyBitGeneratorGuard < ' _ > {
146153 fn drop ( & mut self ) {
147154 // 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" ) ;
149156 }
150157}
151158
152159// SAFETY: We hold the `BitGenerator.lock`,
153160// so nothing apart from us is allowed to change its state.
154- impl PyBitGeneratorGuard < ' _ > {
161+ impl < ' py > PyBitGeneratorGuard < ' py > {
155162 /// 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.
157163 #[ 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" ) ?;
160166 Ok ( ( ) )
161167 }
162168
@@ -223,7 +229,7 @@ mod tests {
223229 py. allow_threads ( || {
224230 let _ = bitgen. next_raw ( ) ;
225231 } ) ;
226- assert ! ( unsafe { bitgen. try_drop( ) } . is_ok( ) ) ;
232+ assert ! ( bitgen. try_drop( py ) . is_ok( ) ) ;
227233 Ok ( ( ) )
228234 } )
229235 }
@@ -240,7 +246,7 @@ mod tests {
240246 assert ! ( bitgen. random_ratio( 1 , 1 ) ) ;
241247 assert ! ( !bitgen. random_ratio( 0 , 1 ) ) ;
242248 } ) ;
243- assert ! ( unsafe { bitgen. try_drop( ) } . is_ok( ) ) ;
249+ assert ! ( bitgen. try_drop( py ) . is_ok( ) ) ;
244250 Ok ( ( ) )
245251 } )
246252 }
@@ -251,7 +257,7 @@ mod tests {
251257 let generator = get_bit_generator ( py) ?;
252258 let bitgen = generator. lock ( ) ?;
253259 assert ! ( generator. lock( ) . is_err( ) ) ;
254- assert ! ( unsafe { bitgen. try_drop( ) } . is_ok( ) ) ;
260+ assert ! ( bitgen. try_drop( py ) . is_ok( ) ) ;
255261 Ok ( ( ) )
256262 } )
257263 }
0 commit comments