@@ -20,12 +20,12 @@ type PyArg<'py> = Borrowed<'py, 'py, PyAny>;
2020/// will be dropped as soon as the pyfunction call ends.
2121///
2222/// There exists a trivial blanket implementation for `T: FromPyObject` with `Holder = ()`.
23- pub trait PyFunctionArgument < ' a , ' py > : Sized + ' a {
23+ pub trait PyFunctionArgument < ' a , ' py , const IS_OPTION : bool > : Sized + ' a {
2424 type Holder : FunctionArgumentHolder ;
2525 fn extract ( obj : & ' a Bound < ' py , PyAny > , holder : & ' a mut Self :: Holder ) -> PyResult < Self > ;
2626}
2727
28- impl < ' a , ' py , T > PyFunctionArgument < ' a , ' py > for T
28+ impl < ' a , ' py , T > PyFunctionArgument < ' a , ' py , false > for T
2929where
3030 T : FromPyObjectBound < ' a , ' py > + ' a ,
3131{
3737 }
3838}
3939
40- impl < ' a , ' py , T : ' py > PyFunctionArgument < ' a , ' py > for & ' a Bound < ' py , T >
40+ impl < ' a , ' py , T : ' py > PyFunctionArgument < ' a , ' py , false > for & ' a Bound < ' py , T >
4141where
4242 T : PyTypeCheck ,
4343{
@@ -49,24 +49,24 @@ where
4949 }
5050}
5151
52- impl < ' a , ' py , T : ' py > PyFunctionArgument < ' a , ' py > for Option < & ' a Bound < ' py , T > >
52+ impl < ' a , ' py , T > PyFunctionArgument < ' a , ' py , true > for Option < T >
5353where
54- T : PyTypeCheck ,
54+ T : PyFunctionArgument < ' a , ' py , false > , // inner `Option`s will use `FromPyObject`
5555{
56- type Holder = ( ) ;
56+ type Holder = T :: Holder ;
5757
5858 #[ inline]
59- fn extract ( obj : & ' a Bound < ' py , PyAny > , _ : & ' a mut ( ) ) -> PyResult < Self > {
59+ fn extract ( obj : & ' a Bound < ' py , PyAny > , holder : & ' a mut T :: Holder ) -> PyResult < Self > {
6060 if obj. is_none ( ) {
6161 Ok ( None )
6262 } else {
63- Ok ( Some ( obj . downcast ( ) ?) )
63+ Ok ( Some ( T :: extract ( obj , holder ) ?) )
6464 }
6565 }
6666}
6767
6868#[ cfg( all( Py_LIMITED_API , not( Py_3_10 ) ) ) ]
69- impl < ' a > PyFunctionArgument < ' a , ' _ > for & ' a str {
69+ impl < ' a > PyFunctionArgument < ' a , ' _ , false > for & ' a str {
7070 type Holder = Option < std:: borrow:: Cow < ' a , str > > ;
7171
7272 #[ inline]
@@ -110,13 +110,13 @@ pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
110110
111111/// The standard implementation of how PyO3 extracts a `#[pyfunction]` or `#[pymethod]` function argument.
112112#[ doc( hidden) ]
113- pub fn extract_argument < ' a , ' py , T > (
113+ pub fn extract_argument < ' a , ' py , T , const IS_OPTION : bool > (
114114 obj : & ' a Bound < ' py , PyAny > ,
115115 holder : & ' a mut T :: Holder ,
116116 arg_name : & str ,
117117) -> PyResult < T >
118118where
119- T : PyFunctionArgument < ' a , ' py > ,
119+ T : PyFunctionArgument < ' a , ' py , IS_OPTION > ,
120120{
121121 match PyFunctionArgument :: extract ( obj, holder) {
122122 Ok ( value) => Ok ( value) ,
@@ -127,14 +127,14 @@ where
127127/// Alternative to [`extract_argument`] used for `Option<T>` arguments. This is necessary because Option<&T>
128128/// does not implement `PyFunctionArgument` for `T: PyClass`.
129129#[ doc( hidden) ]
130- pub fn extract_optional_argument < ' a , ' py , T > (
130+ pub fn extract_optional_argument < ' a , ' py , T , const IS_OPTION : bool > (
131131 obj : Option < & ' a Bound < ' py , PyAny > > ,
132132 holder : & ' a mut T :: Holder ,
133133 arg_name : & str ,
134134 default : fn ( ) -> Option < T > ,
135135) -> PyResult < Option < T > >
136136where
137- T : PyFunctionArgument < ' a , ' py > ,
137+ T : PyFunctionArgument < ' a , ' py , IS_OPTION > ,
138138{
139139 match obj {
140140 Some ( obj) => {
@@ -151,14 +151,14 @@ where
151151
152152/// Alternative to [`extract_argument`] used when the argument has a default value provided by an annotation.
153153#[ doc( hidden) ]
154- pub fn extract_argument_with_default < ' a , ' py , T > (
154+ pub fn extract_argument_with_default < ' a , ' py , T , const IS_OPTION : bool > (
155155 obj : Option < & ' a Bound < ' py , PyAny > > ,
156156 holder : & ' a mut T :: Holder ,
157157 arg_name : & str ,
158158 default : fn ( ) -> T ,
159159) -> PyResult < T >
160160where
161- T : PyFunctionArgument < ' a , ' py > ,
161+ T : PyFunctionArgument < ' a , ' py , IS_OPTION > ,
162162{
163163 match obj {
164164 Some ( obj) => extract_argument ( obj, holder, arg_name) ,
0 commit comments