@@ -7,11 +7,26 @@ use crate::{BoundObject, IntoPyObject, Py, PyAny, Python};
77use std:: ffi:: c_int;
88
99/// A type which can be the return type of a python C-API callback
10- pub trait PyCallbackOutput : Copy {
10+ pub trait PyCallbackOutput : Copy + py_callback_output :: Sealed {
1111 /// The error value to return to python if the callback raised an exception
1212 const ERR_VALUE : Self ;
1313}
1414
15+ /// Seals `PyCallbackOutput` so that types outside PyO3 cannot implement it.
16+ mod py_callback_output {
17+ use std:: os:: raw:: c_int;
18+
19+ use pyo3_ffi:: Py_ssize_t ;
20+
21+ use crate :: ffi:: PyObject ;
22+
23+ pub trait Sealed { }
24+
25+ impl Sealed for * mut PyObject { }
26+ impl Sealed for c_int { }
27+ impl Sealed for Py_ssize_t { }
28+ }
29+
1530impl PyCallbackOutput for * mut ffi:: PyObject {
1631 const ERR_VALUE : Self = std:: ptr:: null_mut ( ) ;
1732}
@@ -25,10 +40,36 @@ impl PyCallbackOutput for ffi::Py_ssize_t {
2540}
2641
2742/// Convert the result of callback function into the appropriate return value.
28- pub trait IntoPyCallbackOutput < ' py , Target > {
43+ pub trait IntoPyCallbackOutput < ' py , Target > : into_py_callback_output :: Sealed < ' py , Target > {
2944 fn convert ( self , py : Python < ' py > ) -> PyResult < Target > ;
3045}
3146
47+ /// Seals `IntoPyCallbackOutput` so that types outside PyO3 cannot implement it.
48+ mod into_py_callback_output {
49+ use pyo3_ffi:: Py_hash_t ;
50+
51+ use crate :: {
52+ ffi,
53+ impl_:: callback:: { HashCallbackOutput , IntoPyCallbackOutput , WrappingCastTo } ,
54+ IntoPyObject , Py , PyAny , PyErr ,
55+ } ;
56+
57+ pub trait Sealed < ' py , Target > { }
58+
59+ impl < ' py , T : IntoPyObject < ' py > > Sealed < ' py , * mut ffi:: PyObject > for T { }
60+ impl < ' py , T : IntoPyCallbackOutput < ' py , U > , E : Into < PyErr > , U > Sealed < ' py , U > for Result < T , E > { }
61+ impl Sealed < ' _ , Self > for * mut ffi:: PyObject { }
62+ impl Sealed < ' _ , std:: ffi:: c_int > for ( ) { }
63+ impl Sealed < ' _ , std:: ffi:: c_int > for bool { }
64+ impl Sealed < ' _ , ( ) > for ( ) { }
65+ impl Sealed < ' _ , ffi:: Py_ssize_t > for usize { }
66+ impl Sealed < ' _ , bool > for bool { }
67+ impl Sealed < ' _ , usize > for usize { }
68+ impl < ' py , T : IntoPyObject < ' py > > Sealed < ' py , Py < PyAny > > for T { }
69+ impl Sealed < ' _ , Py_hash_t > for HashCallbackOutput { }
70+ impl < T : WrappingCastTo < Py_hash_t > > Sealed < ' _ , HashCallbackOutput > for T { }
71+ }
72+
3273impl < ' py , T , E , U > IntoPyCallbackOutput < ' py , U > for Result < T , E >
3374where
3475 T : IntoPyCallbackOutput < ' py , U > ,
@@ -119,10 +160,15 @@ where
119160 }
120161}
121162
122- pub trait WrappingCastTo < T > {
163+ pub trait WrappingCastTo < T > : wrapping_cast_to :: Sealed < T > {
123164 fn wrapping_cast ( self ) -> T ;
124165}
125166
167+ /// Seals `WrappingCastTo` so that types outside PyO3 cannot implement it.
168+ mod wrapping_cast_to {
169+ pub trait Sealed < T > { }
170+ }
171+
126172macro_rules! wrapping_cast {
127173 ( $from: ty, $to: ty) => {
128174 impl WrappingCastTo <$to> for $from {
@@ -131,6 +177,7 @@ macro_rules! wrapping_cast {
131177 self as $to
132178 }
133179 }
180+ impl wrapping_cast_to:: Sealed <$to> for $from { }
134181 } ;
135182}
136183wrapping_cast ! ( u8 , Py_hash_t ) ;
0 commit comments