|
175 | 175 | //! [Interior Mutability]: https://doc.rust-lang.org/book/ch15-05-interior-mutability.html "RefCell<T> and the Interior Mutability Pattern - The Rust Programming Language"
|
176 | 176 |
|
177 | 177 | use crate::exceptions::PyRuntimeError;
|
| 178 | +use crate::impl_::pyclass::{PyClassDict, PyClassWeakRef}; |
178 | 179 | use crate::pyclass::PyClass;
|
179 | 180 | use crate::pyclass_init::PyClassInitializer;
|
180 |
| -use crate::pyclass_slots::{PyClassDict, PyClassWeakRef}; |
181 | 181 | use crate::type_object::{PyLayout, PySizedLayout};
|
182 | 182 | use crate::types::PyAny;
|
183 | 183 | use crate::{class::impl_::PyClassBaseType, class::impl_::PyClassThreadChecker};
|
@@ -253,84 +253,6 @@ pub(crate) struct PyCellContents<T: PyClass> {
|
253 | 253 | pub(crate) weakref: T::WeakRef,
|
254 | 254 | }
|
255 | 255 |
|
256 |
| -impl<T: PyClass> PyCell<T> { |
257 |
| - /// Get the offset of the dictionary from the start of the struct in bytes. |
258 |
| - #[cfg(not(all(Py_LIMITED_API, not(Py_3_9))))] |
259 |
| - pub(crate) fn dict_offset() -> Option<ffi::Py_ssize_t> { |
260 |
| - use std::convert::TryInto; |
261 |
| - if T::Dict::IS_DUMMY { |
262 |
| - None |
263 |
| - } else { |
264 |
| - #[cfg(addr_of)] |
265 |
| - let offset = { |
266 |
| - // With std::ptr::addr_of - can measure offset using uninit memory without UB. |
267 |
| - let cell = std::mem::MaybeUninit::<Self>::uninit(); |
268 |
| - let base_ptr = cell.as_ptr(); |
269 |
| - let dict_ptr = unsafe { std::ptr::addr_of!((*base_ptr).contents.dict) }; |
270 |
| - unsafe { (dict_ptr as *const u8).offset_from(base_ptr as *const u8) } |
271 |
| - }; |
272 |
| - #[cfg(not(addr_of))] |
273 |
| - let offset = { |
274 |
| - // No std::ptr::addr_of - need to take references to PyCell to measure offsets; |
275 |
| - // make a zero-initialised "fake" one so that referencing it is not UB. |
276 |
| - let mut cell = std::mem::MaybeUninit::<Self>::uninit(); |
277 |
| - unsafe { |
278 |
| - std::ptr::write_bytes(cell.as_mut_ptr(), 0, 1); |
279 |
| - } |
280 |
| - let cell = unsafe { cell.assume_init() }; |
281 |
| - let dict_ptr = &cell.contents.dict; |
282 |
| - // offset_from wasn't stabilised until 1.47, so we also have to work around |
283 |
| - // that... |
284 |
| - let offset = (dict_ptr as *const _ as usize) - (&cell as *const _ as usize); |
285 |
| - // This isn't a valid cell, so ensure no Drop code runs etc. |
286 |
| - std::mem::forget(cell); |
287 |
| - offset |
288 |
| - }; |
289 |
| - // Py_ssize_t may not be equal to isize on all platforms |
290 |
| - #[allow(clippy::useless_conversion)] |
291 |
| - Some(offset.try_into().expect("offset should fit in Py_ssize_t")) |
292 |
| - } |
293 |
| - } |
294 |
| - |
295 |
| - /// Get the offset of the weakref list from the start of the struct in bytes. |
296 |
| - #[cfg(not(all(Py_LIMITED_API, not(Py_3_9))))] |
297 |
| - pub(crate) fn weakref_offset() -> Option<ffi::Py_ssize_t> { |
298 |
| - use std::convert::TryInto; |
299 |
| - if T::WeakRef::IS_DUMMY { |
300 |
| - None |
301 |
| - } else { |
302 |
| - #[cfg(addr_of)] |
303 |
| - let offset = { |
304 |
| - // With std::ptr::addr_of - can measure offset using uninit memory without UB. |
305 |
| - let cell = std::mem::MaybeUninit::<Self>::uninit(); |
306 |
| - let base_ptr = cell.as_ptr(); |
307 |
| - let weaklist_ptr = unsafe { std::ptr::addr_of!((*base_ptr).contents.weakref) }; |
308 |
| - unsafe { (weaklist_ptr as *const u8).offset_from(base_ptr as *const u8) } |
309 |
| - }; |
310 |
| - #[cfg(not(addr_of))] |
311 |
| - let offset = { |
312 |
| - // No std::ptr::addr_of - need to take references to PyCell to measure offsets; |
313 |
| - // make a zero-initialised "fake" one so that referencing it is not UB. |
314 |
| - let mut cell = std::mem::MaybeUninit::<Self>::uninit(); |
315 |
| - unsafe { |
316 |
| - std::ptr::write_bytes(cell.as_mut_ptr(), 0, 1); |
317 |
| - } |
318 |
| - let cell = unsafe { cell.assume_init() }; |
319 |
| - let weaklist_ptr = &cell.contents.weakref; |
320 |
| - // offset_from wasn't stabilised until 1.47, so we also have to work around |
321 |
| - // that... |
322 |
| - let offset = (weaklist_ptr as *const _ as usize) - (&cell as *const _ as usize); |
323 |
| - // This isn't a valid cell, so ensure no Drop code runs etc. |
324 |
| - std::mem::forget(cell); |
325 |
| - offset |
326 |
| - }; |
327 |
| - // Py_ssize_t may not be equal to isize on all platforms |
328 |
| - #[allow(clippy::useless_conversion)] |
329 |
| - Some(offset.try_into().expect("offset should fit in Py_ssize_t")) |
330 |
| - } |
331 |
| - } |
332 |
| -} |
333 |
| - |
334 | 256 | unsafe impl<T: PyClass> PyNativeType for PyCell<T> {}
|
335 | 257 |
|
336 | 258 | impl<T: PyClass> PyCell<T> {
|
@@ -502,6 +424,72 @@ impl<T: PyClass> PyCell<T> {
|
502 | 424 | fn get_ptr(&self) -> *mut T {
|
503 | 425 | self.contents.value.get()
|
504 | 426 | }
|
| 427 | + |
| 428 | + /// Gets the offset of the dictionary from the start of the struct in bytes. |
| 429 | + pub(crate) fn dict_offset() -> ffi::Py_ssize_t { |
| 430 | + use std::convert::TryInto; |
| 431 | + #[cfg(addr_of)] |
| 432 | + let offset = { |
| 433 | + // With std::ptr::addr_of - can measure offset using uninit memory without UB. |
| 434 | + let cell = std::mem::MaybeUninit::<Self>::uninit(); |
| 435 | + let base_ptr = cell.as_ptr(); |
| 436 | + let dict_ptr = unsafe { std::ptr::addr_of!((*base_ptr).contents.dict) }; |
| 437 | + unsafe { (dict_ptr as *const u8).offset_from(base_ptr as *const u8) } |
| 438 | + }; |
| 439 | + #[cfg(not(addr_of))] |
| 440 | + let offset = { |
| 441 | + // No std::ptr::addr_of - need to take references to PyCell to measure offsets; |
| 442 | + // make a zero-initialised "fake" one so that referencing it is not UB. |
| 443 | + let mut cell = std::mem::MaybeUninit::<Self>::uninit(); |
| 444 | + unsafe { |
| 445 | + std::ptr::write_bytes(cell.as_mut_ptr(), 0, 1); |
| 446 | + } |
| 447 | + let cell = unsafe { cell.assume_init() }; |
| 448 | + let dict_ptr = &cell.contents.dict; |
| 449 | + // offset_from wasn't stabilised until 1.47, so we also have to work around |
| 450 | + // that... |
| 451 | + let offset = (dict_ptr as *const _ as usize) - (&cell as *const _ as usize); |
| 452 | + // This isn't a valid cell, so ensure no Drop code runs etc. |
| 453 | + std::mem::forget(cell); |
| 454 | + offset |
| 455 | + }; |
| 456 | + // Py_ssize_t may not be equal to isize on all platforms |
| 457 | + #[allow(clippy::useless_conversion)] |
| 458 | + offset.try_into().expect("offset should fit in Py_ssize_t") |
| 459 | + } |
| 460 | + |
| 461 | + /// Gets the offset of the weakref list from the start of the struct in bytes. |
| 462 | + pub(crate) fn weaklist_offset() -> ffi::Py_ssize_t { |
| 463 | + use std::convert::TryInto; |
| 464 | + #[cfg(addr_of)] |
| 465 | + let offset = { |
| 466 | + // With std::ptr::addr_of - can measure offset using uninit memory without UB. |
| 467 | + let cell = std::mem::MaybeUninit::<Self>::uninit(); |
| 468 | + let base_ptr = cell.as_ptr(); |
| 469 | + let weaklist_ptr = unsafe { std::ptr::addr_of!((*base_ptr).contents.weakref) }; |
| 470 | + unsafe { (weaklist_ptr as *const u8).offset_from(base_ptr as *const u8) } |
| 471 | + }; |
| 472 | + #[cfg(not(addr_of))] |
| 473 | + let offset = { |
| 474 | + // No std::ptr::addr_of - need to take references to PyCell to measure offsets; |
| 475 | + // make a zero-initialised "fake" one so that referencing it is not UB. |
| 476 | + let mut cell = std::mem::MaybeUninit::<Self>::uninit(); |
| 477 | + unsafe { |
| 478 | + std::ptr::write_bytes(cell.as_mut_ptr(), 0, 1); |
| 479 | + } |
| 480 | + let cell = unsafe { cell.assume_init() }; |
| 481 | + let weaklist_ptr = &cell.contents.weakref; |
| 482 | + // offset_from wasn't stabilised until 1.47, so we also have to work around |
| 483 | + // that... |
| 484 | + let offset = (weaklist_ptr as *const _ as usize) - (&cell as *const _ as usize); |
| 485 | + // This isn't a valid cell, so ensure no Drop code runs etc. |
| 486 | + std::mem::forget(cell); |
| 487 | + offset |
| 488 | + }; |
| 489 | + // Py_ssize_t may not be equal to isize on all platforms |
| 490 | + #[allow(clippy::useless_conversion)] |
| 491 | + offset.try_into().expect("offset should fit in Py_ssize_t") |
| 492 | + } |
505 | 493 | }
|
506 | 494 |
|
507 | 495 | unsafe impl<T: PyClass> PyLayout<T> for PyCell<T> {}
|
|
0 commit comments