diff --git a/newsfragments/4434.changed.md b/newsfragments/4434.changed.md new file mode 100644 index 00000000000..f16513add1b --- /dev/null +++ b/newsfragments/4434.changed.md @@ -0,0 +1,5 @@ +* The `PyO3::ffi` bindings for the C `PyObject` struct no longer derive from + `Copy` and `Clone`. If you use the ffi directly you will need to remove `Copy` + and `Clone` from any derived types. Any cases where a PyObject struct was + copied or cloned directly likely indicates a bug, it is not safe to allocate + PyObject structs outside of the Python runtime. diff --git a/pyo3-ffi/src/bytearrayobject.rs b/pyo3-ffi/src/bytearrayobject.rs index c09eac5b22c..24a97bcc31b 100644 --- a/pyo3-ffi/src/bytearrayobject.rs +++ b/pyo3-ffi/src/bytearrayobject.rs @@ -5,7 +5,6 @@ use std::ptr::addr_of_mut; #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyByteArrayObject { pub ob_base: PyVarObject, pub ob_alloc: Py_ssize_t, diff --git a/pyo3-ffi/src/complexobject.rs b/pyo3-ffi/src/complexobject.rs index a03d9b00932..78bb9ccaaaf 100644 --- a/pyo3-ffi/src/complexobject.rs +++ b/pyo3-ffi/src/complexobject.rs @@ -26,7 +26,6 @@ extern "C" { } #[repr(C)] -#[derive(Copy, Clone)] // non-limited pub struct PyComplexObject { pub ob_base: PyObject, diff --git a/pyo3-ffi/src/cpython/bytesobject.rs b/pyo3-ffi/src/cpython/bytesobject.rs index fb0b38cf1d8..d0ac5b9c30e 100644 --- a/pyo3-ffi/src/cpython/bytesobject.rs +++ b/pyo3-ffi/src/cpython/bytesobject.rs @@ -6,7 +6,6 @@ use std::os::raw::c_int; #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyBytesObject { pub ob_base: PyVarObject, pub ob_shash: crate::Py_hash_t, diff --git a/pyo3-ffi/src/cpython/code.rs b/pyo3-ffi/src/cpython/code.rs index 86e862f21ab..230096ca378 100644 --- a/pyo3-ffi/src/cpython/code.rs +++ b/pyo3-ffi/src/cpython/code.rs @@ -82,7 +82,6 @@ opaque_struct!(PyCodeObject); #[cfg(all(not(any(PyPy, GraalPy)), Py_3_7, not(Py_3_8)))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyObject, pub co_argcount: c_int, @@ -111,7 +110,6 @@ opaque_struct!(_PyExecutorArray); #[cfg(all(not(any(PyPy, GraalPy)), Py_3_8, not(Py_3_11)))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyObject, pub co_argcount: c_int, @@ -145,7 +143,6 @@ pub struct PyCodeObject { #[cfg(all(not(any(PyPy, GraalPy)), Py_3_11))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyVarObject, pub co_consts: *mut PyObject, @@ -198,7 +195,6 @@ pub struct PyCodeObject { #[cfg(PyPy)] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyObject, pub co_name: *mut PyObject, diff --git a/pyo3-ffi/src/cpython/frameobject.rs b/pyo3-ffi/src/cpython/frameobject.rs index a85818ace0a..6d2346f9288 100644 --- a/pyo3-ffi/src/cpython/frameobject.rs +++ b/pyo3-ffi/src/cpython/frameobject.rs @@ -21,7 +21,6 @@ pub struct PyTryBlock { } #[repr(C)] -#[derive(Copy, Clone)] #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub struct PyFrameObject { pub ob_base: PyVarObject, diff --git a/pyo3-ffi/src/cpython/genobject.rs b/pyo3-ffi/src/cpython/genobject.rs index 73ebdb491ff..17348b2f7bd 100644 --- a/pyo3-ffi/src/cpython/genobject.rs +++ b/pyo3-ffi/src/cpython/genobject.rs @@ -9,7 +9,6 @@ use std::ptr::addr_of_mut; #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyGenObject { pub ob_base: PyObject, #[cfg(not(Py_3_11))] diff --git a/pyo3-ffi/src/cpython/listobject.rs b/pyo3-ffi/src/cpython/listobject.rs index ea15cfc1ff5..963ddfbea87 100644 --- a/pyo3-ffi/src/cpython/listobject.rs +++ b/pyo3-ffi/src/cpython/listobject.rs @@ -4,7 +4,6 @@ use crate::pyport::Py_ssize_t; #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] -#[derive(Copy, Clone)] pub struct PyListObject { pub ob_base: PyVarObject, pub ob_item: *mut *mut PyObject, diff --git a/pyo3-ffi/src/cpython/object.rs b/pyo3-ffi/src/cpython/object.rs index b4f6ce5a878..04811cbda9e 100644 --- a/pyo3-ffi/src/cpython/object.rs +++ b/pyo3-ffi/src/cpython/object.rs @@ -205,7 +205,6 @@ pub type printfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut ::libc::FILE, arg3: c_int) -> c_int; #[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct PyTypeObject { #[cfg(all(PyPy, not(Py_3_9)))] pub ob_refcnt: Py_ssize_t, @@ -301,7 +300,6 @@ pub struct _specialization_cache { } #[repr(C)] -#[derive(Clone)] pub struct PyHeapTypeObject { pub ht_type: PyTypeObject, pub as_async: PyAsyncMethods, diff --git a/pyo3-ffi/src/datetime.rs b/pyo3-ffi/src/datetime.rs index 5da2956c5e9..2ab76c3830f 100644 --- a/pyo3-ffi/src/datetime.rs +++ b/pyo3-ffi/src/datetime.rs @@ -27,7 +27,6 @@ const _PyDateTime_TIME_DATASIZE: usize = 6; const _PyDateTime_DATETIME_DATASIZE: usize = 10; #[repr(C)] -#[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.timedelta`. pub struct PyDateTime_Delta { pub ob_base: PyObject, @@ -46,7 +45,6 @@ pub struct PyDateTime_Delta { #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] -#[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time` without a `tzinfo` member. pub struct _PyDateTime_BaseTime { pub ob_base: PyObject, @@ -56,7 +54,6 @@ pub struct _PyDateTime_BaseTime { } #[repr(C)] -#[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time`. pub struct PyDateTime_Time { pub ob_base: PyObject, @@ -77,7 +74,6 @@ pub struct PyDateTime_Time { } #[repr(C)] -#[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.date` pub struct PyDateTime_Date { pub ob_base: PyObject, @@ -91,7 +87,6 @@ pub struct PyDateTime_Date { #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] -#[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime` without a `tzinfo` member. pub struct _PyDateTime_BaseDateTime { pub ob_base: PyObject, @@ -101,7 +96,6 @@ pub struct _PyDateTime_BaseDateTime { } #[repr(C)] -#[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime`. pub struct PyDateTime_DateTime { pub ob_base: PyObject, @@ -130,8 +124,8 @@ pub struct PyDateTime_DateTime { /// Returns a signed integer greater than 0. pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { // This should work for Date or DateTime - let d = *(o as *mut PyDateTime_Date); - c_int::from(d.data[0]) << 8 | c_int::from(d.data[1]) + let data = (*(o as *mut PyDateTime_Date)).data; + c_int::from(data[0]) << 8 | c_int::from(data[1]) } #[inline] @@ -139,8 +133,8 @@ pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { /// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer in the range `[1, 12]`. pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { - let d = *(o as *mut PyDateTime_Date); - c_int::from(d.data[2]) + let data = (*(o as *mut PyDateTime_Date)).data; + c_int::from(data[2]) } #[inline] @@ -148,8 +142,8 @@ pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { /// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[1, 31]`. pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { - let d = *(o as *mut PyDateTime_Date); - c_int::from(d.data[3]) + let data = (*(o as *mut PyDateTime_Date)).data; + c_int::from(data[3]) } // Accessor macros for times diff --git a/pyo3-ffi/src/moduleobject.rs b/pyo3-ffi/src/moduleobject.rs index f4306b18639..b9026997d2e 100644 --- a/pyo3-ffi/src/moduleobject.rs +++ b/pyo3-ffi/src/moduleobject.rs @@ -52,7 +52,6 @@ extern "C" { } #[repr(C)] -#[derive(Copy, Clone)] pub struct PyModuleDef_Base { pub ob_base: PyObject, pub m_init: Option *mut PyObject>, @@ -98,7 +97,6 @@ pub const Py_MOD_PER_INTERPRETER_GIL_SUPPORTED: *mut c_void = 2 as *mut c_void; // skipped non-limited _Py_mod_LAST_SLOT #[repr(C)] -#[derive(Copy, Clone)] pub struct PyModuleDef { pub m_base: PyModuleDef_Base, pub m_name: *const c_char, diff --git a/pyo3-ffi/src/object.rs b/pyo3-ffi/src/object.rs index 21161a34d3a..9181cb17dd2 100644 --- a/pyo3-ffi/src/object.rs +++ b/pyo3-ffi/src/object.rs @@ -61,7 +61,7 @@ impl std::fmt::Debug for PyObjectObRefcnt { pub type PyObjectObRefcnt = Py_ssize_t; #[repr(C)] -#[derive(Copy, Clone, Debug)] +#[derive(Debug)] pub struct PyObject { #[cfg(py_sys_config = "Py_TRACE_REFS")] pub _ob_next: *mut PyObject, @@ -76,7 +76,7 @@ pub struct PyObject { // skipped _PyObject_CAST #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug)] pub struct PyVarObject { pub ob_base: PyObject, #[cfg(not(GraalPy))]