diff --git a/src/marker.rs b/src/marker.rs index 55b48119..dfe876c8 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -185,84 +185,87 @@ pub unsafe trait Ungil {} #[cfg(not(feature = "nightly"))] unsafe impl Ungil for T {} -/// Types that are safe to access while the GIL is not held. -/// -/// # Safety -/// -/// The type must not carry borrowed Python references or, if it does, not allow access to them if -/// the GIL is not held. -/// -/// See the [module-level documentation](self) for more information. -/// -/// # Examples -/// -/// Types which are `Ungil` cannot be used in contexts where the GIL was released, e.g. -/// -/// ```compile_fail -/// # use pyo3::prelude::*; -/// # use pyo3::types::PyString; -/// Python::with_gil(|py| { -/// let string = PyString::new(py, "foo"); -/// -/// py.allow_threads(|| { -/// println!("{:?}", string); -/// }); -/// }); -/// ``` -/// -/// This applies to the GIL token `Python` itself as well, e.g. -/// -/// ```compile_fail -/// # use pyo3::prelude::*; -/// Python::with_gil(|py| { -/// py.allow_threads(|| { -/// drop(py); -/// }); -/// }); -/// ``` -/// -/// On nightly Rust, this is not based on the [`Send`] auto trait and hence we are able -/// to prevent incorrectly circumventing it using e.g. the [`send_wrapper`](https://docs.rs/send_wrapper/) crate: -/// -/// ```compile_fail -/// # use pyo3::prelude::*; -/// # use pyo3::types::PyString; -/// use send_wrapper::SendWrapper; -/// -/// Python::with_gil(|py| { -/// let string = PyString::new(py, "foo"); -/// -/// let wrapped = SendWrapper::new(string); -/// -/// py.allow_threads(|| { -/// let sneaky: &PyString = *wrapped; -/// -/// println!("{:?}", sneaky); -/// }); -/// }); -/// ``` -/// -/// This also enables using non-[`Send`] types in `allow_threads`, -/// at least if they are not also bound to the GIL: -/// -/// ```rust -/// # use pyo3::prelude::*; -/// use std::rc::Rc; -/// -/// Python::with_gil(|py| { -/// let rc = Rc::new(42); -/// -/// py.allow_threads(|| { -/// println!("{:?}", rc); -/// }); -/// }); -/// ``` #[cfg(feature = "nightly")] -pub unsafe auto trait Ungil {} +mod nightly { + macro_rules! define { + ($($tt:tt)*) => { $($tt)* } + } -#[cfg(feature = "nightly")] -mod negative_impls { - use super::Ungil; + define! { + /// Types that are safe to access while the GIL is not held. + /// + /// # Safety + /// + /// The type must not carry borrowed Python references or, if it does, not allow access to them if + /// the GIL is not held. + /// + /// See the [module-level documentation](self) for more information. + /// + /// # Examples + /// + /// Types which are `Ungil` cannot be used in contexts where the GIL was released, e.g. + /// + /// ```compile_fail + /// # use pyo3::prelude::*; + /// # use pyo3::types::PyString; + /// Python::with_gil(|py| { + /// let string = PyString::new(py, "foo"); + /// + /// py.allow_threads(|| { + /// println!("{:?}", string); + /// }); + /// }); + /// ``` + /// + /// This applies to the GIL token `Python` itself as well, e.g. + /// + /// ```compile_fail + /// # use pyo3::prelude::*; + /// Python::with_gil(|py| { + /// py.allow_threads(|| { + /// drop(py); + /// }); + /// }); + /// ``` + /// + /// On nightly Rust, this is not based on the [`Send`] auto trait and hence we are able + /// to prevent incorrectly circumventing it using e.g. the [`send_wrapper`](https://docs.rs/send_wrapper/) crate: + /// + /// ```compile_fail + /// # use pyo3::prelude::*; + /// # use pyo3::types::PyString; + /// use send_wrapper::SendWrapper; + /// + /// Python::with_gil(|py| { + /// let string = PyString::new(py, "foo"); + /// + /// let wrapped = SendWrapper::new(string); + /// + /// py.allow_threads(|| { + /// let sneaky: &PyString = *wrapped; + /// + /// println!("{:?}", sneaky); + /// }); + /// }); + /// ``` + /// + /// This also enables using non-[`Send`] types in `allow_threads`, + /// at least if they are not also bound to the GIL: + /// + /// ```rust + /// # use pyo3::prelude::*; + /// use std::rc::Rc; + /// + /// Python::with_gil(|py| { + /// let rc = Rc::new(42); + /// + /// py.allow_threads(|| { + /// println!("{:?}", rc); + /// }); + /// }); + /// ``` + pub unsafe auto trait Ungil {} + } impl !Ungil for crate::Python<'_> {} @@ -289,6 +292,9 @@ mod negative_impls { impl !Ungil for crate::ffi::PyArena {} } +#[cfg(feature = "nightly")] +pub use nightly::Ungil; + /// A marker token that represents holding the GIL. /// /// It serves three main purposes: