Skip to content

Commit 6c5d391

Browse files
Tptdavidhewitt
andauthored
Introspection: fix return type hint for Result<()> (#5674)
* Introspection: fix return type hint for Result<()> Uses a hack to get const specialization working Closes #5645 * Reuse pyclass::boolean_struct * Update newsfragments/5674.fixed.md Co-authored-by: David Hewitt <[email protected]> * Use Probe * Update src/pyclass.rs Co-authored-by: David Hewitt <[email protected]> --------- Co-authored-by: David Hewitt <[email protected]>
1 parent af7a820 commit 6c5d391

File tree

6 files changed

+27
-10
lines changed

6 files changed

+27
-10
lines changed

newsfragments/5674.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introspection: fix the return type annotation of `PyResult<()>` (must be `None` and not `tuple`)

pyo3-macros-backend/src/introspection.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,7 @@ pub fn function_introspection_code(
112112
} else {
113113
match returns {
114114
ReturnType::Default => PythonTypeHint::builtin("None"),
115-
ReturnType::Type(_, ty) => match *ty {
116-
Type::Tuple(t) if t.elems.is_empty() => {
117-
// () is converted to None in return types
118-
PythonTypeHint::builtin("None")
119-
}
120-
ty => PythonTypeHint::from_return_type(ty, parent),
121-
},
115+
ReturnType::Type(_, ty) => PythonTypeHint::from_return_type(*ty, parent),
122116
}
123117
.into()
124118
},

pyo3-macros-backend/src/type_hint.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,16 @@ impl PythonTypeHint {
148148
}
149149
}
150150
PythonTypeHintVariant::ReturnType(t) => {
151-
quote! { <#t as #pyo3_crate_path::impl_::introspection::PyReturnType>::OUTPUT_TYPE }
151+
quote! {{
152+
#[allow(unused_imports)]
153+
use #pyo3_crate_path::impl_::pyclass::Probe as _;
154+
const TYPE: #pyo3_crate_path::inspect::TypeHint = if #pyo3_crate_path::impl_::pyclass::IsReturningEmptyTuple::<#t>::VALUE {
155+
#pyo3_crate_path::inspect::TypeHint::builtin("None")
156+
} else {
157+
<#t as #pyo3_crate_path::impl_::introspection::PyReturnType>::OUTPUT_TYPE
158+
};
159+
TYPE
160+
}}
152161
}
153162
PythonTypeHintVariant::Type(t) => {
154163
quote! { <#t as #pyo3_crate_path::type_object::PyTypeCheck>::TYPE_HINT }

pytests/stubs/pyclasses.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from _typeshed import Incomplete
2-
from typing import Any, final
2+
from typing import final
33

44
class AssertingBaseClass:
55
def __new__(cls, /, expected_type: type) -> AssertingBaseClass: ...
@@ -55,7 +55,7 @@ class PyClassThreadIter:
5555

5656
@final
5757
class SubClassWithInit(dict):
58-
def __init__(self, /, *args, **kwargs) -> Any: ...
58+
def __init__(self, /, *args, **kwargs) -> None: ...
5959
def __new__(cls, /, *args, **kwargs) -> SubClassWithInit: ...
6060

6161
def map_a_class(

src/conversion.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,9 @@ impl<'py> IntoPyObject<'py> for () {
595595
type Output = Bound<'py, Self::Target>;
596596
type Error = Infallible;
597597

598+
#[cfg(feature = "experimental-inspect")]
599+
const OUTPUT_TYPE: TypeHint = PyTuple::TYPE_HINT; // TODO(Tpt): should be tuple[()]
600+
598601
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
599602
Ok(PyTuple::empty(py))
600603
}

src/impl_/pyclass/probes.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ impl<T: Clone> IsClone<T> {
7979
pub const VALUE: bool = true;
8080
}
8181

82+
probe!(IsReturningEmptyTuple);
83+
84+
impl IsReturningEmptyTuple<()> {
85+
pub const VALUE: bool = true;
86+
}
87+
88+
impl<E> IsReturningEmptyTuple<Result<(), E>> {
89+
pub const VALUE: bool = true;
90+
}
91+
8292
#[cfg(test)]
8393
macro_rules! value_of {
8494
($probe:ident, $ty:ty) => {{

0 commit comments

Comments
 (0)