diff --git a/newsfragments/5133.removed.md b/newsfragments/5133.removed.md new file mode 100644 index 00000000000..bfcb550e58f --- /dev/null +++ b/newsfragments/5133.removed.md @@ -0,0 +1,2 @@ +* Removed PyASCIIObjectState from the FFI bindings on Python 3.14 and newer. +* Removed PyUnicode_IS_ASCII, PyUnicode_IS_COMPACT, and PyUnicode_IS_COMPACT_ASCII from the FFI bindings on Python 3.14 and newer, since they relied on PyASCIIObjectState. \ No newline at end of file diff --git a/pyo3-ffi/src/cpython/unicodeobject.rs b/pyo3-ffi/src/cpython/unicodeobject.rs index 51317bf0bdd..452c82e4c4b 100644 --- a/pyo3-ffi/src/cpython/unicodeobject.rs +++ b/pyo3-ffi/src/cpython/unicodeobject.rs @@ -2,8 +2,6 @@ use crate::Py_hash_t; use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_ssize_t}; use libc::wchar_t; -#[cfg(Py_3_14)] -use std::os::raw::c_ushort; use std::os::raw::{c_char, c_int, c_uint, c_void}; // skipped Py_UNICODE_ISSPACE() @@ -33,11 +31,13 @@ use std::os::raw::{c_char, c_int, c_uint, c_void}; // skipped Py_UNICODE_LOW_SURROGATE // generated by bindgen v0.63.0 (with small adaptations) +#[cfg(not(Py_3_14))] #[repr(C)] struct BitfieldUnit { storage: Storage, } +#[cfg(not(Py_3_14))] impl BitfieldUnit { #[inline] pub const fn new(storage: Storage) -> Self { @@ -45,7 +45,7 @@ impl BitfieldUnit { } } -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] impl BitfieldUnit where Storage: AsRef<[u8]> + AsMut<[u8]>, @@ -119,33 +119,31 @@ where } } -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_INTERNED_INDEX: usize = 0; -#[cfg(all(not(GraalPy), not(Py_3_14)))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_INTERNED_WIDTH: u8 = 2; -#[cfg(all(not(GraalPy), Py_3_14))] -const STATE_INTERNED_WIDTH: u8 = 16; -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_KIND_INDEX: usize = STATE_INTERNED_WIDTH as usize; -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_KIND_WIDTH: u8 = 3; -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_COMPACT_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH) as usize; -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_COMPACT_WIDTH: u8 = 1; -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_ASCII_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH) as usize; -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] const STATE_ASCII_WIDTH: u8 = 1; -#[cfg(all(not(GraalPy), Py_3_12))] +#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))] const STATE_STATICALLY_ALLOCATED_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize; -#[cfg(all(not(GraalPy), Py_3_12))] +#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))] const STATE_STATICALLY_ALLOCATED_WIDTH: u8 = 1; #[cfg(not(any(Py_3_12, GraalPy)))] @@ -163,19 +161,18 @@ const STATE_READY_WIDTH: u8 = 1; /// /// Memory layout of C bitfields is implementation defined, so these functions are still /// unsafe. Users must verify that they work as expected on the architectures they target. +#[cfg(not(Py_3_14))] #[repr(C)] -#[repr(align(4))] struct PyASCIIObjectState { bitfield_align: [u8; 0], bitfield: BitfieldUnit<[u8; 4usize]>, } // c_uint and u32 are not necessarily the same type on all targets / architectures -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] #[allow(clippy::useless_transmute)] impl PyASCIIObjectState { #[inline] - #[cfg(not(Py_3_14))] unsafe fn interned(&self) -> c_uint { std::mem::transmute( self.bitfield @@ -184,7 +181,6 @@ impl PyASCIIObjectState { } #[inline] - #[cfg(not(Py_3_14))] unsafe fn set_interned(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield @@ -192,36 +188,11 @@ impl PyASCIIObjectState { } #[inline] - #[cfg(Py_3_14)] - unsafe fn interned(&self) -> u16 { - std::mem::transmute( - self.bitfield - .get(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH) as u16, - ) - } - - #[inline] - #[cfg(Py_3_14)] - unsafe fn set_interned(&mut self, val: u16) { - let val: u16 = std::mem::transmute(val); - self.bitfield - .set(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH, val as u64) - } - - #[inline] - #[cfg(not(Py_3_14))] unsafe fn kind(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_KIND_INDEX, STATE_KIND_WIDTH) as u32) } #[inline] - #[cfg(Py_3_14)] - unsafe fn kind(&self) -> c_ushort { - std::mem::transmute(self.bitfield.get(STATE_KIND_INDEX, STATE_KIND_WIDTH) as c_ushort) - } - - #[inline] - #[cfg(not(Py_3_14))] unsafe fn set_kind(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield @@ -229,27 +200,11 @@ impl PyASCIIObjectState { } #[inline] - #[cfg(Py_3_14)] - unsafe fn set_kind(&mut self, val: c_ushort) { - let val: c_ushort = std::mem::transmute(val); - self.bitfield - .set(STATE_KIND_INDEX, STATE_KIND_WIDTH, val as u64) - } - - #[inline] - #[cfg(not(Py_3_14))] unsafe fn compact(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH) as u32) } #[inline] - #[cfg(Py_3_14)] - unsafe fn compact(&self) -> c_ushort { - std::mem::transmute(self.bitfield.get(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH) as c_ushort) - } - - #[inline] - #[cfg(not(Py_3_14))] unsafe fn set_compact(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield @@ -257,42 +212,18 @@ impl PyASCIIObjectState { } #[inline] - #[cfg(Py_3_14)] - unsafe fn set_compact(&mut self, val: c_ushort) { - let val: c_ushort = std::mem::transmute(val); - self.bitfield - .set(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH, val as u64) - } - - #[inline] - #[cfg(not(Py_3_14))] unsafe fn ascii(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_ASCII_INDEX, STATE_ASCII_WIDTH) as u32) } #[inline] - #[cfg(not(Py_3_14))] unsafe fn set_ascii(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield .set(STATE_ASCII_INDEX, STATE_ASCII_WIDTH, val as u64) } - #[inline] - #[cfg(Py_3_14)] - unsafe fn ascii(&self) -> c_ushort { - std::mem::transmute(self.bitfield.get(STATE_ASCII_INDEX, STATE_ASCII_WIDTH) as c_ushort) - } - - #[inline] - #[cfg(Py_3_14)] - unsafe fn set_ascii(&mut self, val: c_ushort) { - let val: c_ushort = std::mem::transmute(val); - self.bitfield - .set(STATE_ASCII_INDEX, STATE_ASCII_WIDTH, val as u64) - } - - #[cfg(all(Py_3_12, not(Py_3_14)))] + #[cfg(Py_3_12)] #[inline] unsafe fn statically_allocated(&self) -> c_uint { std::mem::transmute(self.bitfield.get( @@ -301,7 +232,7 @@ impl PyASCIIObjectState { ) as u32) } - #[cfg(all(Py_3_12, not(Py_3_14)))] + #[cfg(Py_3_12)] #[inline] unsafe fn set_statically_allocated(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); @@ -312,26 +243,6 @@ impl PyASCIIObjectState { ) } - #[inline] - #[cfg(Py_3_14)] - unsafe fn statically_allocated(&self) -> c_ushort { - std::mem::transmute(self.bitfield.get( - STATE_STATICALLY_ALLOCATED_INDEX, - STATE_STATICALLY_ALLOCATED_WIDTH, - ) as c_ushort) - } - - #[inline] - #[cfg(Py_3_14)] - unsafe fn set_statically_allocated(&mut self, val: c_ushort) { - let val: c_ushort = std::mem::transmute(val); - self.bitfield.set( - STATE_STATICALLY_ALLOCATED_INDEX, - STATE_STATICALLY_ALLOCATED_WIDTH, - val as u64, - ) - } - #[cfg(not(Py_3_12))] #[inline] unsafe fn ready(&self) -> c_uint { @@ -347,6 +258,7 @@ impl PyASCIIObjectState { } } +#[cfg(not(Py_3_14))] impl From for PyASCIIObjectState { #[inline] fn from(value: u32) -> Self { @@ -357,6 +269,7 @@ impl From for PyASCIIObjectState { } } +#[cfg(not(Py_3_14))] impl From for u32 { #[inline] fn from(value: PyASCIIObjectState) -> Self { @@ -383,28 +296,21 @@ pub struct PyASCIIObject { /// unsigned int ready:1; /// unsigned int :24; /// - /// 3.12 and 3.13: + /// 3.12, and 3.13 /// unsigned int interned:2; // SSTATE_* constants. /// unsigned int kind:3; // PyUnicode_*_KIND constants. /// unsigned int compact:1; /// unsigned int ascii:1; /// unsigned int statically_allocated:1; /// unsigned int :24; - /// - /// 3.14 and later: - /// uint16_t interned; // SSTATE_* constants. - /// unsigned short kind:3; // PyUnicode_*_KIND constants. - /// unsigned short compact:1; - /// unsigned short ascii:1; - /// unsigned int statically_allocated:1; - /// unsigned int :10; + /// on 3.14 and higher PyO3 doesn't access the internal state pub state: u32, #[cfg(not(Py_3_12))] pub wstr: *mut wchar_t, } /// Interacting with the bitfield is not actually well-defined, so we mark these APIs unsafe. -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] impl PyASCIIObject { #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12 /// Get the `interned` field of the [`PyASCIIObject`] state bitfield. @@ -412,7 +318,6 @@ impl PyASCIIObject { /// Returns one of: [`SSTATE_NOT_INTERNED`], [`SSTATE_INTERNED_MORTAL`], /// [`SSTATE_INTERNED_IMMORTAL`], or [`SSTATE_INTERNED_IMMORTAL_STATIC`]. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn interned(&self) -> c_uint { PyASCIIObjectState::from(self.state).interned() } @@ -424,131 +329,56 @@ impl PyASCIIObject { /// [`SSTATE_INTERNED_MORTAL`], [`SSTATE_INTERNED_IMMORTAL`], or /// [`SSTATE_INTERNED_IMMORTAL_STATIC`] is invalid. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn set_interned(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_interned(val); self.state = u32::from(state); } - #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12 - /// Get the `interned` field of the [`PyASCIIObject`] state bitfield. - /// - /// Returns one of: [`SSTATE_NOT_INTERNED`], [`SSTATE_INTERNED_MORTAL`], - /// [`SSTATE_INTERNED_IMMORTAL`], or [`SSTATE_INTERNED_IMMORTAL_STATIC`]. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn interned(&self) -> u16 { - PyASCIIObjectState::from(self.state).interned() - } - - #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12 - /// Set the `interned` field of the [`PyASCIIObject`] state bitfield. - /// - /// Calling this function with an argument that is not [`SSTATE_NOT_INTERNED`], - /// [`SSTATE_INTERNED_MORTAL`], [`SSTATE_INTERNED_IMMORTAL`], or - /// [`SSTATE_INTERNED_IMMORTAL_STATIC`] is invalid. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn set_interned(&mut self, val: u16) { - let mut state = PyASCIIObjectState::from(self.state); - state.set_interned(val); - self.state = u32::from(state); - } - /// Get the `kind` field of the [`PyASCIIObject`] state bitfield. /// /// Returns one of: #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")] /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`]. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn kind(&self) -> c_uint { PyASCIIObjectState::from(self.state).kind() } - /// Get the `kind` field of the [`PyASCIIObject`] state bitfield. - /// - /// Returns one of: - #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")] - /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`]. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn kind(&self) -> c_ushort { - PyASCIIObjectState::from(self.state).kind() - } - /// Set the `kind` field of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is not #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")] /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`] is invalid. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn set_kind(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_kind(val); self.state = u32::from(state); } - /// Set the `kind` field of the [`PyASCIIObject`] state bitfield. - /// - /// Calling this function with an argument that is not - #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")] - /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`] is invalid. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn set_kind(&mut self, val: c_ushort) { - let mut state = PyASCIIObjectState::from(self.state); - state.set_kind(val); - self.state = u32::from(state); - } - /// Get the `compact` field of the [`PyASCIIObject`] state bitfield. /// /// Returns either `0` or `1`. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn compact(&self) -> c_uint { PyASCIIObjectState::from(self.state).compact() } - /// Get the `compact` field of the [`PyASCIIObject`] state bitfield. - /// - /// Returns either `0` or `1`. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn compact(&self) -> c_ushort { - PyASCIIObjectState::from(self.state).compact() - } - /// Set the `compact` flag of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is neither `0` nor `1` is invalid. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn set_compact(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_compact(val); self.state = u32::from(state); } - /// Set the `compact` flag of the [`PyASCIIObject`] state bitfield. - /// - /// Calling this function with an argument that is neither `0` nor `1` is invalid. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn set_compact(&mut self, val: c_ushort) { - let mut state = PyASCIIObjectState::from(self.state); - state.set_compact(val); - self.state = u32::from(state); - } - /// Get the `ascii` field of the [`PyASCIIObject`] state bitfield. /// /// Returns either `0` or `1`. #[inline] - #[cfg(not(Py_3_14))] pub unsafe fn ascii(&self) -> c_uint { PyASCIIObjectState::from(self.state).ascii() } @@ -557,33 +387,13 @@ impl PyASCIIObject { /// /// Calling this function with an argument that is neither `0` nor `1` is invalid. #[inline] - #[cfg(not(Py_3_14))] + #[cfg(not(all(Py_3_14, Py_GIL_DISABLED)))] pub unsafe fn set_ascii(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_ascii(val); self.state = u32::from(state); } - /// Get the `ascii` field of the [`PyASCIIObject`] state bitfield. - /// - /// Returns either `0` or `1`. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn ascii(&self) -> c_ushort { - PyASCIIObjectState::from(self.state).ascii() - } - - /// Set the `ascii` flag of the [`PyASCIIObject`] state bitfield. - /// - /// Calling this function with an argument that is neither `0` nor `1` is invalid. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn set_ascii(&mut self, val: c_ushort) { - let mut state = PyASCIIObjectState::from(self.state); - state.set_ascii(val); - self.state = u32::from(state); - } - /// Get the `ready` field of the [`PyASCIIObject`] state bitfield. /// /// Returns either `0` or `1`. @@ -608,7 +418,7 @@ impl PyASCIIObject { /// /// Returns either `0` or `1`. #[inline] - #[cfg(all(Py_3_12, not(Py_3_14)))] + #[cfg(Py_3_12)] pub unsafe fn statically_allocated(&self) -> c_uint { PyASCIIObjectState::from(self.state).statically_allocated() } @@ -617,32 +427,12 @@ impl PyASCIIObject { /// /// Calling this function with an argument that is neither `0` nor `1` is invalid. #[inline] - #[cfg(all(Py_3_12, not(Py_3_14)))] + #[cfg(Py_3_12)] pub unsafe fn set_statically_allocated(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_statically_allocated(val); self.state = u32::from(state); } - - /// Get the `statically_allocated` field of the [`PyASCIIObject`] state bitfield. - /// - /// Returns either `0` or `1`. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn statically_allocated(&self) -> c_ushort { - PyASCIIObjectState::from(self.state).statically_allocated() - } - - /// Set the `statically_allocated` flag of the [`PyASCIIObject`] state bitfield. - /// - /// Calling this function with an argument that is neither `0` nor `1` is invalid. - #[inline] - #[cfg(Py_3_14)] - pub unsafe fn set_statically_allocated(&mut self, val: c_ushort) { - let mut state = PyASCIIObjectState::from(self.state); - state.set_statically_allocated(val); - self.state = u32::from(state); - } } #[repr(C)] @@ -684,7 +474,7 @@ pub const SSTATE_INTERNED_IMMORTAL: c_uint = 2; #[cfg(Py_3_12)] pub const SSTATE_INTERNED_IMMORTAL_STATIC: c_uint = 3; -#[cfg(all(not(GraalPy), not(Py_3_14)))] +#[cfg(not(any(GraalPy, Py_3_14)))] #[inline] pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint { debug_assert!(crate::PyUnicode_Check(op) != 0); @@ -694,29 +484,13 @@ pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).ascii() } -#[cfg(all(not(GraalPy), not(Py_3_14)))] +#[cfg(not(any(GraalPy, Py_3_14)))] #[inline] pub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).compact() } -#[cfg(all(not(GraalPy), Py_3_14))] -#[inline] -pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_ushort { - debug_assert!(crate::PyUnicode_Check(op) != 0); - #[cfg(not(Py_3_12))] - debug_assert!(PyUnicode_IS_READY(op) != 0); - - (*(op as *mut PyASCIIObject)).ascii() -} - -#[cfg(all(not(GraalPy), Py_3_14))] -#[inline] -pub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_ushort { - (*(op as *mut PyASCIIObject)).compact() -} - -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] #[inline] pub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint { ((*(op as *mut PyASCIIObject)).ascii() != 0 && PyUnicode_IS_COMPACT(op) != 0).into() @@ -726,20 +500,10 @@ pub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint { #[deprecated(note = "Removed in Python 3.12")] pub const PyUnicode_WCHAR_KIND: c_uint = 0; -#[cfg(not(Py_3_14))] pub const PyUnicode_1BYTE_KIND: c_uint = 1; -#[cfg(not(Py_3_14))] pub const PyUnicode_2BYTE_KIND: c_uint = 2; -#[cfg(not(Py_3_14))] pub const PyUnicode_4BYTE_KIND: c_uint = 4; -#[cfg(Py_3_14)] -pub const PyUnicode_1BYTE_KIND: c_ushort = 1; -#[cfg(Py_3_14)] -pub const PyUnicode_2BYTE_KIND: c_ushort = 2; -#[cfg(Py_3_14)] -pub const PyUnicode_4BYTE_KIND: c_ushort = 4; - #[cfg(not(any(GraalPy, PyPy)))] #[inline] pub unsafe fn PyUnicode_1BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS1 { @@ -758,19 +522,15 @@ pub unsafe fn PyUnicode_4BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS4 { PyUnicode_DATA(op) as *mut Py_UCS4 } -#[cfg(all(not(GraalPy), not(Py_3_14)))] -#[inline] -pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint { - debug_assert!(crate::PyUnicode_Check(op) != 0); - #[cfg(not(Py_3_12))] - debug_assert!(PyUnicode_IS_READY(op) != 0); - - (*(op as *mut PyASCIIObject)).kind() +#[cfg(all(not(GraalPy), Py_3_14))] +extern "C" { + #[cfg_attr(PyPy, link_name = "PyPyUnicode_KIND")] + pub fn PyUnicode_KIND(op: *mut PyObject) -> c_uint; } -#[cfg(all(not(GraalPy), Py_3_14))] +#[cfg(all(not(GraalPy), not(Py_3_14)))] #[inline] -pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_ushort { +pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint { debug_assert!(crate::PyUnicode_Check(op) != 0); #[cfg(not(Py_3_12))] debug_assert!(PyUnicode_IS_READY(op) != 0); @@ -778,7 +538,7 @@ pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_ushort { (*(op as *mut PyASCIIObject)).kind() } -#[cfg(not(GraalPy))] +#[cfg(not(any(GraalPy, Py_3_14)))] #[inline] pub unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void { if PyUnicode_IS_ASCII(op) != 0 { @@ -796,7 +556,7 @@ pub unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void { (*(op as *mut PyUnicodeObject)).data.any } -#[cfg(not(any(GraalPy, PyPy)))] +#[cfg(not(any(GraalPy, PyPy, Py_3_14)))] #[inline] pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void { debug_assert!(crate::PyUnicode_Check(op) != 0); @@ -808,6 +568,13 @@ pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void { } } +#[cfg(Py_3_14)] +#[cfg(all(not(GraalPy), Py_3_14))] +extern "C" { + #[cfg_attr(PyPy, link_name = "PyPyUnicode_DATA")] + pub fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void; +} + // skipped PyUnicode_WRITE // skipped PyUnicode_READ // skipped PyUnicode_READ_CHAR diff --git a/src/ffi/tests.rs b/src/ffi/tests.rs index 1f934d670d2..7de4e3b1875 100644 --- a/src/ffi/tests.rs +++ b/src/ffi/tests.rs @@ -118,6 +118,7 @@ fn test_timezone_from_offset_and_name() { fn ascii_object_bitfield() { let ob_base: PyObject = unsafe { std::mem::zeroed() }; + #[cfg_attr(Py_3_14, allow(unused_mut, unused_variables))] let mut o = PyASCIIObject { ob_base, length: 0, @@ -128,6 +129,7 @@ fn ascii_object_bitfield() { wstr: std::ptr::null_mut() as *mut wchar_t, }; + #[cfg(not(Py_3_14))] unsafe { assert_eq!(o.interned(), 0); assert_eq!(o.kind(), 0); @@ -175,24 +177,28 @@ fn ascii() { let ptr = s.as_ptr(); unsafe { - let ascii_ptr = ptr as *mut PyASCIIObject; - let ascii = ascii_ptr.as_ref().unwrap(); - - assert_eq!(ascii.interned(), 0); - assert_eq!(ascii.kind(), PyUnicode_1BYTE_KIND); - assert_eq!(ascii.compact(), 1); - assert_eq!(ascii.ascii(), 1); - #[cfg(not(Py_3_12))] - assert_eq!(ascii.ready(), 1); - - assert_eq!(PyUnicode_IS_ASCII(ptr), 1); - assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); - assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 1); + #[cfg(not(Py_3_14))] + { + let ascii_ptr = ptr as *mut PyASCIIObject; + let ascii = ascii_ptr.as_ref().unwrap(); + + assert_eq!(ascii.interned(), 0); + assert_eq!(ascii.kind(), PyUnicode_1BYTE_KIND); + assert_eq!(ascii.compact(), 1); + assert_eq!(ascii.ascii(), 1); + #[cfg(not(Py_3_12))] + assert_eq!(ascii.ready(), 1); + + assert_eq!(PyUnicode_IS_ASCII(ptr), 1); + assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); + assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 1); + } assert!(!PyUnicode_1BYTE_DATA(ptr).is_null()); // 2 and 4 byte macros return nonsense for this string instance. assert_eq!(PyUnicode_KIND(ptr), PyUnicode_1BYTE_KIND); + #[cfg(not(Py_3_14))] assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null()); // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings. assert!(!PyUnicode_DATA(ptr).is_null()); @@ -216,23 +222,26 @@ fn ucs4() { let ptr = py_string.as_ptr(); unsafe { - let ascii_ptr = ptr as *mut PyASCIIObject; - let ascii = ascii_ptr.as_ref().unwrap(); - - assert_eq!(ascii.interned(), 0); - assert_eq!(ascii.kind(), PyUnicode_4BYTE_KIND); - assert_eq!(ascii.compact(), 1); - assert_eq!(ascii.ascii(), 0); - #[cfg(not(Py_3_12))] - assert_eq!(ascii.ready(), 1); - - assert_eq!(PyUnicode_IS_ASCII(ptr), 0); - assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); - assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 0); - + #[cfg(not(Py_3_14))] + { + let ascii_ptr = ptr as *mut PyASCIIObject; + let ascii = ascii_ptr.as_ref().unwrap(); + + assert_eq!(ascii.interned(), 0); + assert_eq!(ascii.kind(), PyUnicode_4BYTE_KIND); + assert_eq!(ascii.compact(), 1); + assert_eq!(ascii.ascii(), 0); + #[cfg(not(Py_3_12))] + assert_eq!(ascii.ready(), 1); + + assert_eq!(PyUnicode_IS_ASCII(ptr), 0); + assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); + assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 0); + } assert!(!PyUnicode_4BYTE_DATA(ptr).is_null()); assert_eq!(PyUnicode_KIND(ptr), PyUnicode_4BYTE_KIND); + #[cfg(not(Py_3_14))] assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null()); // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings. assert!(!PyUnicode_DATA(ptr).is_null());