Skip to main content

pyo3/impl_/pyclass/
probes.rs

1use core::marker::PhantomData;
2
3use crate::conversion::IntoPyObject;
4use crate::{FromPyObject, Py};
5
6/// Trait used to combine with zero-sized types to calculate at compile time
7/// some property of a type.
8///
9/// The trick uses the fact that an associated constant has higher priority
10/// than a trait constant, so we can use the trait to define the false case.
11///
12/// The true case is defined in the zero-sized type's impl block, which is
13/// gated on some property like trait bound or only being implemented
14/// for fixed concrete types.
15pub trait Probe: probe::Sealed {
16    const VALUE: bool = false;
17}
18
19/// Seals `Probe` so that types outside PyO3 cannot implement it.
20mod probe {
21    pub trait Sealed {}
22}
23
24macro_rules! probe {
25    ($name:ident) => {
26        pub struct $name<T>(PhantomData<T>);
27        impl<T> Probe for $name<T> {}
28        impl<T> probe::Sealed for $name<T> {}
29    };
30}
31
32probe!(IsPyT);
33
34impl<T> IsPyT<Py<T>> {
35    pub const VALUE: bool = true;
36}
37
38probe!(IsIntoPyObjectRef);
39
40impl<'a, 'py, T: 'a> IsIntoPyObjectRef<T>
41where
42    &'a T: IntoPyObject<'py>,
43{
44    pub const VALUE: bool = true;
45}
46
47probe!(IsSend);
48
49impl<T: Send> IsSend<T> {
50    pub const VALUE: bool = true;
51}
52
53probe!(IsSync);
54
55impl<T: Sync> IsSync<T> {
56    pub const VALUE: bool = true;
57}
58
59probe!(IsFromPyObject);
60
61impl<'a, 'py, T> IsFromPyObject<T>
62where
63    T: FromPyObject<'a, 'py>,
64{
65    pub const VALUE: bool = true;
66}
67
68probe!(HasNewTextSignature);
69
70impl<T: super::doc::PyClassNewTextSignature> HasNewTextSignature<T> {
71    pub const VALUE: bool = true;
72}
73
74probe!(IsClone);
75
76impl<T: Clone> IsClone<T> {
77    pub const VALUE: bool = true;
78}
79
80probe!(IsReturningEmptyTuple);
81
82impl IsReturningEmptyTuple<()> {
83    pub const VALUE: bool = true;
84}
85
86impl<E> IsReturningEmptyTuple<Result<(), E>> {
87    pub const VALUE: bool = true;
88}
89
90#[cfg(test)]
91macro_rules! value_of {
92    ($probe:ident, $ty:ty) => {{
93        #[allow(unused_imports)] // probe trait not used if VALUE is true
94        use crate::impl_::pyclass::Probe as _;
95        $probe::<$ty>::VALUE
96    }};
97}
98
99#[cfg(test)]
100pub(crate) use value_of;
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here