document FnType and refactor FnType::self_arg (#4276)

This commit is contained in:
Bruno Kolenbrander 2024-06-23 12:36:19 +02:00 committed by GitHub
parent c67625d683
commit 6a0221ba2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 32 additions and 26 deletions

View File

@ -192,16 +192,26 @@ fn handle_argument_error(pat: &syn::Pat) -> syn::Error {
syn::Error::new(span, msg) syn::Error::new(span, msg)
} }
/// Represents what kind of a function a pyfunction or pymethod is
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum FnType { pub enum FnType {
/// Represents a pymethod annotated with `#[getter]`
Getter(SelfType), Getter(SelfType),
/// Represents a pymethod annotated with `#[setter]`
Setter(SelfType), Setter(SelfType),
/// Represents a regular pymethod
Fn(SelfType), Fn(SelfType),
/// Represents a pymethod annotated with `#[new]`, i.e. the `__new__` dunder.
FnNew, FnNew,
/// Represents a pymethod annotated with both `#[new]` and `#[classmethod]` (in either order)
FnNewClass(Span), FnNewClass(Span),
/// Represents a pymethod annotated with `#[classmethod]`, like a `@classmethod`
FnClass(Span), FnClass(Span),
/// Represents a pyfunction or a pymethod annotated with `#[staticmethod]`, like a `@staticmethod`
FnStatic, FnStatic,
/// Represents a pyfunction annotated with `#[pyo3(pass_module)]
FnModule(Span), FnModule(Span),
/// Represents a pymethod or associated constant annotated with `#[classattr]`
ClassAttribute, ClassAttribute,
} }
@ -224,7 +234,7 @@ impl FnType {
error_mode: ExtractErrorMode, error_mode: ExtractErrorMode,
holders: &mut Holders, holders: &mut Holders,
ctx: &Ctx, ctx: &Ctx,
) -> TokenStream { ) -> Option<TokenStream> {
let Ctx { pyo3_path, .. } = ctx; let Ctx { pyo3_path, .. } = ctx;
match self { match self {
FnType::Getter(st) | FnType::Setter(st) | FnType::Fn(st) => { FnType::Getter(st) | FnType::Setter(st) | FnType::Fn(st) => {
@ -235,35 +245,35 @@ impl FnType {
ctx, ctx,
); );
syn::Token![,](Span::call_site()).to_tokens(&mut receiver); syn::Token![,](Span::call_site()).to_tokens(&mut receiver);
receiver Some(receiver)
}
FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => {
quote!()
} }
FnType::FnClass(span) | FnType::FnNewClass(span) => { FnType::FnClass(span) | FnType::FnNewClass(span) => {
let py = syn::Ident::new("py", Span::call_site()); let py = syn::Ident::new("py", Span::call_site());
let slf: Ident = syn::Ident::new("_slf_ref", Span::call_site()); let slf: Ident = syn::Ident::new("_slf_ref", Span::call_site());
let pyo3_path = pyo3_path.to_tokens_spanned(*span); let pyo3_path = pyo3_path.to_tokens_spanned(*span);
quote_spanned! { *span => let ret = quote_spanned! { *span =>
#[allow(clippy::useless_conversion)] #[allow(clippy::useless_conversion)]
::std::convert::Into::into( ::std::convert::Into::into(
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(#slf as *const _ as *const *mut _)) #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(#slf as *const _ as *const *mut _))
.downcast_unchecked::<#pyo3_path::types::PyType>() .downcast_unchecked::<#pyo3_path::types::PyType>()
), ),
} };
Some(ret)
} }
FnType::FnModule(span) => { FnType::FnModule(span) => {
let py = syn::Ident::new("py", Span::call_site()); let py = syn::Ident::new("py", Span::call_site());
let slf: Ident = syn::Ident::new("_slf_ref", Span::call_site()); let slf: Ident = syn::Ident::new("_slf_ref", Span::call_site());
let pyo3_path = pyo3_path.to_tokens_spanned(*span); let pyo3_path = pyo3_path.to_tokens_spanned(*span);
quote_spanned! { *span => let ret = quote_spanned! { *span =>
#[allow(clippy::useless_conversion)] #[allow(clippy::useless_conversion)]
::std::convert::Into::into( ::std::convert::Into::into(
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(#slf as *const _ as *const *mut _)) #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(#slf as *const _ as *const *mut _))
.downcast_unchecked::<#pyo3_path::types::PyModule>() .downcast_unchecked::<#pyo3_path::types::PyModule>()
), ),
} };
Some(ret)
} }
FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => None,
} }
} }
} }
@ -658,10 +668,7 @@ impl<'a> FnSpec<'a> {
}} }}
} }
_ => { _ => {
let self_arg = self_arg(); if let Some(self_arg) = self_arg() {
if self_arg.is_empty() {
quote! { function(#(#args),*) }
} else {
let self_checker = holders.push_gil_refs_checker(self_arg.span()); let self_checker = holders.push_gil_refs_checker(self_arg.span());
quote! { quote! {
function( function(
@ -670,6 +677,8 @@ impl<'a> FnSpec<'a> {
#(#args),* #(#args),*
) )
} }
} else {
quote! { function(#(#args),*) }
} }
} }
}; };
@ -690,20 +699,17 @@ impl<'a> FnSpec<'a> {
}}; }};
} }
call call
} else { } else if let Some(self_arg) = self_arg() {
let self_arg = self_arg(); let self_checker = holders.push_gil_refs_checker(self_arg.span());
if self_arg.is_empty() { quote! {
quote! { function(#(#args),*) } function(
} else { // NB #self_arg includes a comma, so none inserted here
let self_checker = holders.push_gil_refs_checker(self_arg.span()); #pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker),
quote! { #(#args),*
function( )
// NB #self_arg includes a comma, so none inserted here
#pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker),
#(#args),*
)
}
} }
} else {
quote! { function(#(#args),*) }
}; };
// We must assign the output_span to the return value of the call, // We must assign the output_span to the return value of the call,