diff --git a/src/gil.rs b/src/gil.rs index 7034af6c..e56b7eb5 100644 --- a/src/gil.rs +++ b/src/gil.rs @@ -3,11 +3,12 @@ //! Interaction with python's global interpreter lock use crate::ffi; +use crate::internal_tricks::Unsendable; use crate::types::PyAny; use crate::Python; use spin; use std::ptr::NonNull; -use std::{any, marker, rc, sync}; +use std::{any, sync}; static START: sync::Once = sync::Once::new(); static START_PYO3: sync::Once = sync::Once::new(); @@ -101,9 +102,8 @@ pub struct GILGuard { owned: usize, borrowed: usize, gstate: ffi::PyGILState_STATE, - // hack to opt out of Send on stable rust, which doesn't - // have negative impls - no_send: marker::PhantomData>, + // Stable solution for impl !Send + no_send: Unsendable, } /// The Drop implementation for `GILGuard` will release the GIL. @@ -181,7 +181,7 @@ pub struct GILPool<'p> { owned: usize, borrowed: usize, pointers: bool, - no_send: marker::PhantomData>, + no_send: Unsendable, } impl<'p> GILPool<'p> { @@ -193,7 +193,7 @@ impl<'p> GILPool<'p> { owned: p.owned.len(), borrowed: p.borrowed.len(), pointers: true, - no_send: marker::PhantomData, + no_send: Unsendable::default(), } } #[inline] @@ -204,7 +204,7 @@ impl<'p> GILPool<'p> { owned: p.owned.len(), borrowed: p.borrowed.len(), pointers: false, - no_send: marker::PhantomData, + no_send: Unsendable::default(), } } } @@ -260,7 +260,7 @@ impl GILGuard { owned: pool.owned.len(), borrowed: pool.borrowed.len(), gstate, - no_send: marker::PhantomData, + no_send: Unsendable::default(), } } } diff --git a/src/instance.rs b/src/instance.rs index 779d1861..10071027 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -2,6 +2,7 @@ use crate::err::{PyErr, PyResult}; use crate::gil; use crate::instance; +use crate::internal_tricks::Unsendable; use crate::object::PyObject; use crate::objectprotocol::ObjectProtocol; use crate::type_object::PyTypeCreate; @@ -13,7 +14,6 @@ use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut}; use std::ptr::NonNull; -use std::rc::Rc; /// Types that are built into the python interpreter. /// @@ -55,7 +55,7 @@ pub unsafe trait PyNativeType: Sized { /// py.run("assert p.length() == 12", None, Some(d)).unwrap(); /// ``` #[derive(Debug)] -pub struct PyRef<'a, T: PyTypeInfo>(&'a T, PhantomData>); +pub struct PyRef<'a, T: PyTypeInfo>(&'a T, Unsendable); #[allow(clippy::cast_ptr_alignment)] fn ref_to_ptr(t: &T) -> *mut ffi::PyObject @@ -67,7 +67,7 @@ where impl<'a, T: PyTypeInfo> PyRef<'a, T> { pub(crate) fn from_ref(r: &'a T) -> Self { - PyRef(r, PhantomData) + PyRef(r, Unsendable::default()) } } @@ -143,11 +143,11 @@ where /// py.run("assert p.length() == 100", None, Some(d)).unwrap(); /// ``` #[derive(Debug)] -pub struct PyRefMut<'a, T: PyTypeInfo>(&'a mut T, PhantomData>); +pub struct PyRefMut<'a, T: PyTypeInfo>(&'a mut T, Unsendable); impl<'a, T: PyTypeInfo> PyRefMut<'a, T> { pub(crate) fn from_mut(t: &'a mut T) -> Self { - PyRefMut(t, PhantomData) + PyRefMut(t, Unsendable::default()) } } @@ -267,7 +267,7 @@ pub trait AsPyRef: Sized { /// `Py` is thread-safe, because any python related operations require a Python<'p> token. #[derive(Debug)] #[repr(transparent)] -pub struct Py(NonNull, std::marker::PhantomData); +pub struct Py(NonNull, PhantomData); unsafe impl Send for Py {} @@ -295,7 +295,7 @@ impl Py { !ptr.is_null() && ffi::Py_REFCNT(ptr) > 0, format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)) ); - Py(NonNull::new_unchecked(ptr), std::marker::PhantomData) + Py(NonNull::new_unchecked(ptr), PhantomData) } /// Creates a `Py` instance for the given FFI pointer. @@ -304,7 +304,7 @@ impl Py { #[inline] pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py { match NonNull::new(ptr) { - Some(nonnull_ptr) => Py(nonnull_ptr, std::marker::PhantomData), + Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData), None => { crate::err::panic_after_error(); } @@ -317,7 +317,7 @@ impl Py { /// Unsafe because the pointer might be invalid. pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult> { match NonNull::new(ptr) { - Some(nonnull_ptr) => Ok(Py(nonnull_ptr, std::marker::PhantomData)), + Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)), None => Err(PyErr::fetch(py)), } } @@ -332,7 +332,7 @@ impl Py { format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr)) ); ffi::Py_INCREF(ptr); - Py(NonNull::new_unchecked(ptr), std::marker::PhantomData) + Py(NonNull::new_unchecked(ptr), PhantomData) } /// Gets the reference count of the ffi::PyObject pointer. diff --git a/src/internal_tricks.rs b/src/internal_tricks.rs new file mode 100644 index 00000000..1cf8a56a --- /dev/null +++ b/src/internal_tricks.rs @@ -0,0 +1,6 @@ +use std::marker::PhantomData; +use std::rc::Rc; + +/// A marker type that makes the type !Send. +/// Temporal hack until https://github.com/rust-lang/rust/issues/13231 is resolved. +pub(crate) type Unsendable = PhantomData>; diff --git a/src/lib.rs b/src/lib.rs index f5bbcdec..f65a33e6 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -161,6 +161,7 @@ pub mod exceptions; pub mod freelist; mod gil; mod instance; +mod internal_tricks; pub mod marshal; mod object; mod objectprotocol;