remove the gil-ref deprecations infrastructure (#4320)

This commit is contained in:
Icxolu 2024-07-08 15:40:27 +02:00 committed by GitHub
parent d5c886f4c0
commit 3c155d9fef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 104 additions and 650 deletions

View File

@ -1,7 +1,7 @@
use crate::attributes::{self, get_pyo3_options, CrateAttribute, FromPyWithAttribute};
use crate::utils::Ctx;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned};
use quote::{format_ident, quote};
use syn::{
parenthesized,
parse::{Parse, ParseStream},
@ -44,16 +44,14 @@ impl<'a> Enum<'a> {
}
/// Build derivation body for enums.
fn build(&self, ctx: &Ctx) -> (TokenStream, TokenStream) {
fn build(&self, ctx: &Ctx) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let mut var_extracts = Vec::new();
let mut variant_names = Vec::new();
let mut error_names = Vec::new();
let mut deprecations = TokenStream::new();
for var in &self.variants {
let (struct_derive, dep) = var.build(ctx);
deprecations.extend(dep);
let struct_derive = var.build(ctx);
let ext = quote!({
let maybe_ret = || -> #pyo3_path::PyResult<Self> {
#struct_derive
@ -70,22 +68,19 @@ impl<'a> Enum<'a> {
error_names.push(&var.err_name);
}
let ty_name = self.enum_ident.to_string();
(
quote!(
let errors = [
#(#var_extracts),*
];
::std::result::Result::Err(
#pyo3_path::impl_::frompyobject::failed_to_extract_enum(
obj.py(),
#ty_name,
&[#(#variant_names),*],
&[#(#error_names),*],
&errors
)
quote!(
let errors = [
#(#var_extracts),*
];
::std::result::Result::Err(
#pyo3_path::impl_::frompyobject::failed_to_extract_enum(
obj.py(),
#ty_name,
&[#(#variant_names),*],
&[#(#error_names),*],
&errors
)
),
deprecations,
)
)
}
}
@ -244,7 +239,7 @@ impl<'a> Container<'a> {
}
/// Build derivation body for a struct.
fn build(&self, ctx: &Ctx) -> (TokenStream, TokenStream) {
fn build(&self, ctx: &Ctx) -> TokenStream {
match &self.ty {
ContainerType::StructNewtype(ident, from_py_with) => {
self.build_newtype_struct(Some(ident), from_py_with, ctx)
@ -262,73 +257,42 @@ impl<'a> Container<'a> {
field_ident: Option<&Ident>,
from_py_with: &Option<FromPyWithAttribute>,
ctx: &Ctx,
) -> (TokenStream, TokenStream) {
) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let self_ty = &self.path;
let struct_name = self.name();
if let Some(ident) = field_ident {
let field_name = ident.to_string();
match from_py_with {
None => (
quote! {
Ok(#self_ty {
#ident: #pyo3_path::impl_::frompyobject::extract_struct_field(obj, #struct_name, #field_name)?
})
},
TokenStream::new(),
),
None => quote! {
Ok(#self_ty {
#ident: #pyo3_path::impl_::frompyobject::extract_struct_field(obj, #struct_name, #field_name)?
})
},
Some(FromPyWithAttribute {
value: expr_path, ..
}) => (
quote! {
Ok(#self_ty {
#ident: #pyo3_path::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, #field_name)?
})
},
quote_spanned! { expr_path.span() =>
const _: () = {
fn check_from_py_with() {
let e = #pyo3_path::impl_::deprecations::GilRefs::new();
#pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e);
e.from_py_with_arg();
}
};
},
),
}) => quote! {
Ok(#self_ty {
#ident: #pyo3_path::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, #field_name)?
})
},
}
} else {
match from_py_with {
None => (
quote!(
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field(obj, #struct_name, 0).map(#self_ty)
),
TokenStream::new(),
),
None => quote! {
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field(obj, #struct_name, 0).map(#self_ty)
},
Some(FromPyWithAttribute {
value: expr_path, ..
}) => (
quote! (
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, 0).map(#self_ty)
),
quote_spanned! { expr_path.span() =>
const _: () = {
fn check_from_py_with() {
let e = #pyo3_path::impl_::deprecations::GilRefs::new();
#pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e);
e.from_py_with_arg();
}
};
},
),
}) => quote! {
#pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, 0).map(#self_ty)
},
}
}
}
fn build_tuple_struct(
&self,
struct_fields: &[TupleStructField],
ctx: &Ctx,
) -> (TokenStream, TokenStream) {
fn build_tuple_struct(&self, struct_fields: &[TupleStructField], ctx: &Ctx) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let self_ty = &self.path;
let struct_name = &self.name();
@ -348,40 +312,15 @@ impl<'a> Container<'a> {
}
});
let deprecations = struct_fields
.iter()
.filter_map(|field| {
let FromPyWithAttribute {
value: expr_path, ..
} = field.from_py_with.as_ref()?;
Some(quote_spanned! { expr_path.span() =>
const _: () = {
fn check_from_py_with() {
let e = #pyo3_path::impl_::deprecations::GilRefs::new();
#pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e);
e.from_py_with_arg();
}
};
})
})
.collect::<TokenStream>();
(
quote!(
match #pyo3_path::types::PyAnyMethods::extract(obj) {
::std::result::Result::Ok((#(#field_idents),*)) => ::std::result::Result::Ok(#self_ty(#(#fields),*)),
::std::result::Result::Err(err) => ::std::result::Result::Err(err),
}
),
deprecations,
quote!(
match #pyo3_path::types::PyAnyMethods::extract(obj) {
::std::result::Result::Ok((#(#field_idents),*)) => ::std::result::Result::Ok(#self_ty(#(#fields),*)),
::std::result::Result::Err(err) => ::std::result::Result::Err(err),
}
)
}
fn build_struct(
&self,
struct_fields: &[NamedStructField<'_>],
ctx: &Ctx,
) -> (TokenStream, TokenStream) {
fn build_struct(&self, struct_fields: &[NamedStructField<'_>], ctx: &Ctx) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let self_ty = &self.path;
let struct_name = &self.name();
@ -420,28 +359,7 @@ impl<'a> Container<'a> {
fields.push(quote!(#ident: #extractor));
}
let deprecations = struct_fields
.iter()
.filter_map(|field| {
let FromPyWithAttribute {
value: expr_path, ..
} = field.from_py_with.as_ref()?;
Some(quote_spanned! { expr_path.span() =>
const _: () = {
fn check_from_py_with() {
let e = #pyo3_path::impl_::deprecations::GilRefs::new();
#pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e);
e.from_py_with_arg();
}
};
})
})
.collect::<TokenStream>();
(
quote!(::std::result::Result::Ok(#self_ty{#fields})),
deprecations,
)
quote!(::std::result::Result::Ok(#self_ty{#fields}))
}
}
@ -673,7 +591,7 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
let ctx = &Ctx::new(&options.krate, None);
let Ctx { pyo3_path, .. } = &ctx;
let (derives, from_py_with_deprecations) = match &tokens.data {
let derives = match &tokens.data {
syn::Data::Enum(en) => {
if options.transparent || options.annotation.is_some() {
bail_spanned!(tokens.span() => "`transparent` or `annotation` is not supported \
@ -703,7 +621,5 @@ pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {
#derives
}
}
#from_py_with_deprecations
))
}

View File

@ -683,11 +683,10 @@ impl<'a> FnSpec<'a> {
}
_ => {
if let Some(self_arg) = self_arg() {
let self_checker = holders.push_gil_refs_checker(self_arg.span());
quote! {
function(
// NB #self_arg includes a comma, so none inserted here
#pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker),
#self_arg
#(#args),*
)
}
@ -714,11 +713,10 @@ impl<'a> FnSpec<'a> {
}
call
} else if let Some(self_arg) = self_arg() {
let self_checker = holders.push_gil_refs_checker(self_arg.span());
quote! {
function(
// NB #self_arg includes a comma, so none inserted here
#pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker),
#self_arg
#(#args),*
)
}
@ -762,7 +760,6 @@ impl<'a> FnSpec<'a> {
})
.collect();
let call = rust_call(args, &mut holders);
let check_gil_refs = holders.check_gil_refs();
let init_holders = holders.init_holders(ctx);
quote! {
unsafe fn #ident<'py>(
@ -774,7 +771,6 @@ impl<'a> FnSpec<'a> {
let function = #rust_name; // Shadow the function name to avoid #3017
#init_holders
let result = #call;
#check_gil_refs
result
}
}
@ -784,7 +780,6 @@ impl<'a> FnSpec<'a> {
let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders, ctx);
let call = rust_call(args, &mut holders);
let init_holders = holders.init_holders(ctx);
let check_gil_refs = holders.check_gil_refs();
quote! {
unsafe fn #ident<'py>(
@ -800,7 +795,6 @@ impl<'a> FnSpec<'a> {
#arg_convert
#init_holders
let result = #call;
#check_gil_refs
result
}
}
@ -810,7 +804,6 @@ impl<'a> FnSpec<'a> {
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx);
let call = rust_call(args, &mut holders);
let init_holders = holders.init_holders(ctx);
let check_gil_refs = holders.check_gil_refs();
quote! {
unsafe fn #ident<'py>(
@ -825,7 +818,6 @@ impl<'a> FnSpec<'a> {
#arg_convert
#init_holders
let result = #call;
#check_gil_refs
result
}
}
@ -838,7 +830,6 @@ impl<'a> FnSpec<'a> {
.self_arg(cls, ExtractErrorMode::Raise, &mut holders, ctx);
let call = quote_spanned! {*output_span=> #rust_name(#self_arg #(#args),*) };
let init_holders = holders.init_holders(ctx);
let check_gil_refs = holders.check_gil_refs();
quote! {
unsafe fn #ident(
py: #pyo3_path::Python<'_>,
@ -854,7 +845,6 @@ impl<'a> FnSpec<'a> {
#init_holders
let result = #call;
let initializer: #pyo3_path::PyClassInitializer::<#cls> = result.convert(py)?;
#check_gil_refs
#pyo3_path::impl_::pymethods::tp_new_impl(py, initializer, _slf)
}
}

View File

@ -16,7 +16,7 @@ use std::ffi::CString;
use syn::{
ext::IdentExt,
parse::{Parse, ParseStream},
parse_quote, parse_quote_spanned,
parse_quote,
punctuated::Punctuated,
spanned::Spanned,
token::Comma,
@ -377,7 +377,6 @@ pub fn pymodule_function_impl(mut function: syn::ItemFn) -> Result<TokenStream>
let options = PyModuleOptions::from_attrs(&mut function.attrs)?;
process_functions_in_module(&options, &mut function)?;
let ctx = &Ctx::new(&options.krate, None);
let stmts = std::mem::take(&mut function.block.stmts);
let Ctx { pyo3_path, .. } = ctx;
let ident = &function.sig.ident;
let name = options.name.unwrap_or_else(|| ident.unraw());
@ -394,30 +393,6 @@ pub fn pymodule_function_impl(mut function: syn::ItemFn) -> Result<TokenStream>
module_args
.push(quote!(::std::convert::Into::into(#pyo3_path::impl_::pymethods::BoundRef(module))));
let extractors = function
.sig
.inputs
.iter()
.filter_map(|param| {
if let syn::FnArg::Typed(pat_type) = param {
if let syn::Pat::Ident(pat_ident) = &*pat_type.pat {
let ident: &syn::Ident = &pat_ident.ident;
return Some([
parse_quote!{ let check_gil_refs = #pyo3_path::impl_::deprecations::GilRefs::new(); },
parse_quote! { let #ident = #pyo3_path::impl_::deprecations::inspect_type(#ident, &check_gil_refs); },
parse_quote_spanned! { pat_type.span() => check_gil_refs.function_arg(); },
]);
}
}
None
})
.flatten();
function.block.stmts = extractors.chain(stmts).collect();
function
.attrs
.push(parse_quote!(#[allow(clippy::used_underscore_binding)]));
Ok(quote! {
#function
#[doc(hidden)]

View File

@ -10,14 +10,12 @@ use syn::spanned::Spanned;
pub struct Holders {
holders: Vec<syn::Ident>,
gil_refs_checkers: Vec<GilRefChecker>,
}
impl Holders {
pub fn new() -> Self {
Holders {
holders: Vec::new(),
gil_refs_checkers: Vec::new(),
}
}
@ -27,58 +25,14 @@ impl Holders {
holder
}
pub fn push_gil_refs_checker(&mut self, span: Span) -> syn::Ident {
let gil_refs_checker = syn::Ident::new(
&format!("gil_refs_checker_{}", self.gil_refs_checkers.len()),
span,
);
self.gil_refs_checkers
.push(GilRefChecker::FunctionArg(gil_refs_checker.clone()));
gil_refs_checker
}
pub fn push_from_py_with_checker(&mut self, span: Span) -> syn::Ident {
let gil_refs_checker = syn::Ident::new(
&format!("gil_refs_checker_{}", self.gil_refs_checkers.len()),
span,
);
self.gil_refs_checkers
.push(GilRefChecker::FromPyWith(gil_refs_checker.clone()));
gil_refs_checker
}
pub fn init_holders(&self, ctx: &Ctx) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let holders = &self.holders;
let gil_refs_checkers = self.gil_refs_checkers.iter().map(|checker| match checker {
GilRefChecker::FunctionArg(ident) => ident,
GilRefChecker::FromPyWith(ident) => ident,
});
quote! {
#[allow(clippy::let_unit_value)]
#(let mut #holders = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;)*
#(let #gil_refs_checkers = #pyo3_path::impl_::deprecations::GilRefs::new();)*
}
}
pub fn check_gil_refs(&self) -> TokenStream {
self.gil_refs_checkers
.iter()
.map(|checker| match checker {
GilRefChecker::FunctionArg(ident) => {
quote_spanned! { ident.span() => #ident.function_arg(); }
}
GilRefChecker::FromPyWith(ident) => {
quote_spanned! { ident.span() => #ident.from_py_with_arg(); }
}
})
.collect()
}
}
enum GilRefChecker {
FunctionArg(syn::Ident),
FromPyWith(syn::Ident),
}
/// Return true if the argument list is simply (*args, **kwds).
@ -89,17 +43,6 @@ pub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool {
)
}
pub(crate) fn check_arg_for_gil_refs(
tokens: TokenStream,
gil_refs_checker: syn::Ident,
ctx: &Ctx,
) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
quote! {
#pyo3_path::impl_::deprecations::inspect_type(#tokens, &#gil_refs_checker)
}
}
pub fn impl_arg_params(
spec: &FnSpec<'_>,
self_: Option<&syn::Type>,
@ -119,9 +62,7 @@ pub fn impl_arg_params(
let from_py_with = &arg.from_py_with()?.value;
let from_py_with_holder = format_ident!("from_py_with_{}", i);
Some(quote_spanned! { from_py_with.span() =>
let e = #pyo3_path::impl_::deprecations::GilRefs::new();
let #from_py_with_holder = #pyo3_path::impl_::deprecations::inspect_fn(#from_py_with, &e);
e.from_py_with_arg();
let #from_py_with_holder = #from_py_with;
})
})
.collect::<TokenStream>();
@ -250,8 +191,7 @@ fn impl_arg_param(
let from_py_with = format_ident!("from_py_with_{}", pos);
let arg_value = quote!(#args_array[#option_pos].as_deref());
*option_pos += 1;
let tokens = impl_regular_arg_param(arg, from_py_with, arg_value, holders, ctx);
check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx)
impl_regular_arg_param(arg, from_py_with, arg_value, holders, ctx)
}
FnArg::VarArgs(arg) => {
let holder = holders.push_holder(arg.name.span());

View File

@ -4,7 +4,7 @@ use std::ffi::CString;
use crate::attributes::{NameAttribute, RenamingRule};
use crate::deprecations::deprecate_trailing_option_default;
use crate::method::{CallingConvention, ExtractErrorMode, PyArg};
use crate::params::{check_arg_for_gil_refs, impl_regular_arg_param, Holders};
use crate::params::{impl_regular_arg_param, Holders};
use crate::utils::PythonDoc;
use crate::utils::{Ctx, LitCStr};
use crate::{
@ -612,21 +612,18 @@ pub fn impl_py_setter_def(
PropertyType::Function { spec, .. } => {
let (_, args) = split_off_python_arg(&spec.signature.arguments);
let value_arg = &args[0];
let (from_py_with, ident) = if let Some(from_py_with) =
&value_arg.from_py_with().as_ref().map(|f| &f.value)
{
let ident = syn::Ident::new("from_py_with", from_py_with.span());
(
quote_spanned! { from_py_with.span() =>
let e = #pyo3_path::impl_::deprecations::GilRefs::new();
let #ident = #pyo3_path::impl_::deprecations::inspect_fn(#from_py_with, &e);
e.from_py_with_arg();
},
ident,
)
} else {
(quote!(), syn::Ident::new("dummy", Span::call_site()))
};
let (from_py_with, ident) =
if let Some(from_py_with) = &value_arg.from_py_with().as_ref().map(|f| &f.value) {
let ident = syn::Ident::new("from_py_with", from_py_with.span());
(
quote_spanned! { from_py_with.span() =>
let #ident = #from_py_with;
},
ident,
)
} else {
(quote!(), syn::Ident::new("dummy", Span::call_site()))
};
let arg = if let FnArg::Regular(arg) = &value_arg {
arg
@ -634,15 +631,13 @@ pub fn impl_py_setter_def(
bail_spanned!(value_arg.name().span() => "The #[setter] value argument can't be *args, **kwargs or `cancel_handle`.");
};
let tokens = impl_regular_arg_param(
let extract = impl_regular_arg_param(
arg,
ident,
quote!(::std::option::Option::Some(_value.into())),
&mut holders,
ctx,
);
let extract =
check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx);
let deprecation = deprecate_trailing_option_default(spec);
quote! {
@ -660,12 +655,8 @@ pub fn impl_py_setter_def(
.unwrap_or_default();
let holder = holders.push_holder(span);
let gil_refs_checker = holders.push_gil_refs_checker(span);
quote! {
let _val = #pyo3_path::impl_::deprecations::inspect_type(
#pyo3_path::impl_::extract_argument::extract_argument(_value.into(), &mut #holder, #name)?,
&#gil_refs_checker
);
let _val = #pyo3_path::impl_::extract_argument::extract_argument(_value.into(), &mut #holder, #name)?;
}
}
};
@ -682,7 +673,6 @@ pub fn impl_py_setter_def(
}
let init_holders = holders.init_holders(ctx);
let check_gil_refs = holders.check_gil_refs();
let associated_method = quote! {
#cfg_attrs
unsafe fn #wrapper_ident(
@ -698,7 +688,6 @@ pub fn impl_py_setter_def(
#init_holders
#extract
let result = #setter_impl;
#check_gil_refs
#pyo3_path::callback::convert(py, result)
}
};
@ -824,7 +813,6 @@ pub fn impl_py_getter_def(
};
let init_holders = holders.init_holders(ctx);
let check_gil_refs = holders.check_gil_refs();
let associated_method = quote! {
#cfg_attrs
unsafe fn #wrapper_ident(
@ -833,7 +821,6 @@ pub fn impl_py_getter_def(
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
#init_holders
let result = #body;
#check_gil_refs
result
}
};
@ -1139,35 +1126,30 @@ fn extract_object(
ctx: &Ctx,
) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let gil_refs_checker = holders.push_gil_refs_checker(arg.ty().span());
let name = arg.name().unraw().to_string();
let extract = if let Some(from_py_with) =
arg.from_py_with().map(|from_py_with| &from_py_with.value)
{
let from_py_with_checker = holders.push_from_py_with_checker(from_py_with.span());
quote! {
#pyo3_path::impl_::extract_argument::from_py_with(
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0,
#name,
#pyo3_path::impl_::deprecations::inspect_fn(#from_py_with, &#from_py_with_checker) as fn(_) -> _,
)
}
} else {
let holder = holders.push_holder(Span::call_site());
quote! {
#pyo3_path::impl_::extract_argument::extract_argument(
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0,
&mut #holder,
#name
)
}
};
let extract =
if let Some(from_py_with) = arg.from_py_with().map(|from_py_with| &from_py_with.value) {
quote! {
#pyo3_path::impl_::extract_argument::from_py_with(
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0,
#name,
#from_py_with as fn(_) -> _,
)
}
} else {
let holder = holders.push_holder(Span::call_site());
quote! {
#pyo3_path::impl_::extract_argument::extract_argument(
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0,
&mut #holder,
#name
)
}
};
let extracted = extract_error_mode.handle_error(extract, ctx);
quote! {
#pyo3_path::impl_::deprecations::inspect_type(#extracted, &#gil_refs_checker)
}
quote!(#extracted)
}
enum ReturnMode {
@ -1177,15 +1159,13 @@ enum ReturnMode {
}
impl ReturnMode {
fn return_call_output(&self, call: TokenStream, ctx: &Ctx, holders: &Holders) -> TokenStream {
fn return_call_output(&self, call: TokenStream, ctx: &Ctx) -> TokenStream {
let Ctx { pyo3_path, .. } = ctx;
let check_gil_refs = holders.check_gil_refs();
match self {
ReturnMode::Conversion(conversion) => {
let conversion = TokenGeneratorCtx(*conversion, ctx);
quote! {
let _result: #pyo3_path::PyResult<#conversion> = #pyo3_path::callback::convert(py, #call);
#check_gil_refs
#pyo3_path::callback::convert(py, _result)
}
}
@ -1195,14 +1175,12 @@ impl ReturnMode {
quote! {
let _result = #call;
use #pyo3_path::impl_::pymethods::{#traits};
#check_gil_refs
(&_result).#tag().convert(py, _result)
}
}
ReturnMode::ReturnSelf => quote! {
let _result: #pyo3_path::PyResult<()> = #pyo3_path::callback::convert(py, #call);
_result?;
#check_gil_refs
#pyo3_path::ffi::Py_XINCREF(_raw_slf);
::std::result::Result::Ok(_raw_slf)
},
@ -1369,12 +1347,10 @@ fn generate_method_body(
let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders, ctx)?;
let call = quote! { #cls::#rust_name(#self_arg #(#args),*) };
Ok(if let Some(return_mode) = return_mode {
return_mode.return_call_output(call, ctx, holders)
return_mode.return_call_output(call, ctx)
} else {
let check_gil_refs = holders.check_gil_refs();
quote! {
let result = #call;
#check_gil_refs;
#pyo3_path::callback::convert(py, result)
}
})

View File

@ -1,76 +1,4 @@
//! Symbols used to denote deprecated usages of PyO3's proc macros.
use crate::{PyResult, Python};
#[deprecated(since = "0.20.0", note = "use `#[new]` instead of `#[__new__]`")]
pub const PYMETHODS_NEW_DEPRECATED_FORM: () = ();
pub fn inspect_type<T>(t: T, _: &GilRefs<T>) -> T {
t
}
pub fn inspect_fn<A, T>(f: fn(A) -> PyResult<T>, _: &GilRefs<A>) -> fn(A) -> PyResult<T> {
f
}
pub struct GilRefs<T>(OptionGilRefs<T>);
pub struct OptionGilRefs<T>(NotAGilRef<T>);
pub struct NotAGilRef<T>(std::marker::PhantomData<T>);
pub trait IsGilRef {}
#[cfg(feature = "gil-refs")]
impl<T: crate::PyNativeType> IsGilRef for &'_ T {}
impl<T> GilRefs<T> {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
GilRefs(OptionGilRefs(NotAGilRef(std::marker::PhantomData)))
}
}
impl GilRefs<Python<'_>> {
#[deprecated(since = "0.21.0", note = "use `wrap_pyfunction_bound!` instead")]
pub fn is_python(&self) {}
}
impl<T: IsGilRef> GilRefs<T> {
#[deprecated(
since = "0.21.0",
note = "use `&Bound<'_, T>` instead for this function argument"
)]
pub fn function_arg(&self) {}
#[deprecated(
since = "0.21.0",
note = "use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor"
)]
pub fn from_py_with_arg(&self) {}
}
impl<T: IsGilRef> OptionGilRefs<Option<T>> {
#[deprecated(
since = "0.21.0",
note = "use `Option<&Bound<'_, T>>` instead for this function argument"
)]
pub fn function_arg(&self) {}
}
impl<T> NotAGilRef<T> {
pub fn function_arg(&self) {}
pub fn from_py_with_arg(&self) {}
pub fn is_python(&self) {}
}
impl<T> std::ops::Deref for GilRefs<T> {
type Target = OptionGilRefs<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> std::ops::Deref for OptionGilRefs<T> {
type Target = NotAGilRef<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View File

@ -145,12 +145,8 @@ macro_rules! wrap_pyfunction {
};
($function:path, $py_or_module:expr) => {{
use $function as wrapped_pyfunction;
let check_gil_refs = $crate::impl_::deprecations::GilRefs::new();
let py_or_module =
$crate::impl_::deprecations::inspect_type($py_or_module, &check_gil_refs);
check_gil_refs.is_python();
$crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction(
py_or_module,
$py_or_module,
&wrapped_pyfunction::_PYO3_DEF,
)
}};

View File

@ -20,7 +20,6 @@ fn test_compile_errors() {
t.compile_fail("tests/ui/invalid_pymethod_names.rs");
t.compile_fail("tests/ui/invalid_pymodule_args.rs");
t.compile_fail("tests/ui/reject_generics.rs");
#[cfg(feature = "gil-refs")]
t.compile_fail("tests/ui/deprecations.rs");
t.compile_fail("tests/ui/invalid_closure.rs");
t.compile_fail("tests/ui/pyclass_send.rs");

View File

@ -2,7 +2,6 @@
#![allow(dead_code)]
use pyo3::prelude::*;
use pyo3::types::{PyString, PyType};
#[pyclass]
struct MyClass;
@ -13,114 +12,14 @@ impl MyClass {
fn new() -> Self {
Self
}
#[classmethod]
fn cls_method_gil_ref(_cls: &PyType) {}
#[classmethod]
fn cls_method_bound(_cls: &Bound<'_, PyType>) {}
fn method_gil_ref(_slf: &PyCell<Self>) {}
fn method_bound(_slf: &Bound<'_, Self>) {}
#[staticmethod]
fn static_method_gil_ref(_any: &PyAny) {}
#[setter]
fn set_foo_gil_ref(&self, #[pyo3(from_py_with = "extract_gil_ref")] _value: i32) {}
#[setter]
fn set_foo_bound(&self, #[pyo3(from_py_with = "extract_bound")] _value: i32) {}
#[setter]
fn set_bar_gil_ref(&self, _value: &PyAny) {}
#[setter]
fn set_bar_bound(&self, _value: &Bound<'_, PyAny>) {}
fn __eq__(&self, #[pyo3(from_py_with = "extract_gil_ref")] _other: i32) -> bool {
true
}
fn __contains__(&self, #[pyo3(from_py_with = "extract_bound")] _value: i32) -> bool {
true
}
}
fn main() {}
#[pyfunction]
#[pyo3(pass_module)]
fn pyfunction_with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyString>> {
module.name()
}
#[pyfunction]
#[pyo3(pass_module)]
fn pyfunction_with_module_gil_ref(_module: &PyModule) -> PyResult<&str> {
todo!()
}
#[pyfunction]
fn double(x: usize) -> usize {
x * 2
}
#[pymodule]
fn module_gil_ref(_m: &PyModule) -> PyResult<()> {
Ok(())
}
#[pymodule]
fn module_gil_ref_with_explicit_py_arg(_py: Python<'_>, _m: &PyModule) -> PyResult<()> {
Ok(())
}
#[pymodule]
fn module_bound(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(double, m)?)?;
Ok(())
}
#[pymodule]
fn module_bound_with_explicit_py_arg(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(double, m)?)?;
Ok(())
}
#[pymodule]
fn module_bound_by_value(m: Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(double, &m)?)?;
Ok(())
}
fn extract_gil_ref(obj: &PyAny) -> PyResult<i32> {
obj.extract()
}
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<i32> {
obj.extract()
}
fn extract_options(obj: &Bound<'_, PyAny>) -> PyResult<Option<i32>> {
obj.extract()
}
#[pyfunction]
fn pyfunction_from_py_with(
#[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32,
#[pyo3(from_py_with = "extract_bound")] _bound: i32,
) {
}
#[pyfunction]
fn pyfunction_gil_ref(_any: &PyAny) {}
#[pyfunction]
#[pyo3(signature = (_any))]
fn pyfunction_option_gil_ref(_any: Option<&PyAny>) {}
#[pyfunction]
#[pyo3(signature = (_i, _any=None))]
fn pyfunction_option_1(_i: u32, _any: Option<i32>) {}
@ -139,61 +38,6 @@ fn pyfunction_option_4(
) {
}
#[derive(Debug, FromPyObject)]
pub struct Zap {
#[pyo3(item)]
name: String,
#[pyo3(from_py_with = "PyAny::len", item("my_object"))]
some_object_length: usize,
#[pyo3(from_py_with = "extract_bound")]
some_number: i32,
}
#[derive(Debug, FromPyObject)]
pub struct ZapTuple(
String,
#[pyo3(from_py_with = "PyAny::len")] usize,
#[pyo3(from_py_with = "extract_bound")] i32,
);
#[derive(Debug, FromPyObject, PartialEq, Eq)]
pub enum ZapEnum {
Zip(#[pyo3(from_py_with = "extract_gil_ref")] i32),
Zap(String, #[pyo3(from_py_with = "extract_bound")] i32),
}
#[derive(Debug, FromPyObject, PartialEq, Eq)]
#[pyo3(transparent)]
pub struct TransparentFromPyWithGilRef {
#[pyo3(from_py_with = "extract_gil_ref")]
len: i32,
}
#[derive(Debug, FromPyObject, PartialEq, Eq)]
#[pyo3(transparent)]
pub struct TransparentFromPyWithBound {
#[pyo3(from_py_with = "extract_bound")]
len: i32,
}
fn test_wrap_pyfunction(py: Python<'_>, m: &Bound<'_, PyModule>) {
// should lint
let _ = wrap_pyfunction!(double, py);
// should lint but currently does not
let _ = wrap_pyfunction!(double)(py);
// should not lint
let _ = wrap_pyfunction!(double, m);
let _ = wrap_pyfunction!(double)(m);
let _ = wrap_pyfunction!(double, m.as_gil_ref());
let _ = wrap_pyfunction!(double)(m.as_gil_ref());
let _ = wrap_pyfunction_bound!(double, py);
let _ = wrap_pyfunction_bound!(double)(py);
}
#[pyclass]
pub enum SimpleEnumWithoutEq {
VariamtA,

View File

@ -1,7 +1,7 @@
error: use of deprecated constant `pyo3::deprecations::PYMETHODS_NEW_DEPRECATED_FORM`: use `#[new]` instead of `#[__new__]`
--> tests/ui/deprecations.rs:12:7
--> tests/ui/deprecations.rs:11:7
|
12 | #[__new__]
11 | #[__new__]
| ^^^^^^^
|
note: the lint level is defined here
@ -13,141 +13,31 @@ note: the lint level is defined here
error: use of deprecated constant `__pyfunction_pyfunction_option_2::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
= note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:129:4
|
129 | fn pyfunction_option_2(_i: u32, _any: Option<i32>) {}
| ^^^^^^^^^^^^^^^^^^^
--> tests/ui/deprecations.rs:28:4
|
28 | fn pyfunction_option_2(_i: u32, _any: Option<i32>) {}
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_3::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
= note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None, _foo=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:132:4
|
132 | fn pyfunction_option_3(_i: u32, _any: Option<i32>, _foo: Option<String>) {}
| ^^^^^^^^^^^^^^^^^^^
--> tests/ui/deprecations.rs:31:4
|
31 | fn pyfunction_option_3(_i: u32, _any: Option<i32>, _foo: Option<String>) {}
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_4::SIGNATURE`: this function has implicit defaults for the trailing `Option<T>` arguments
= note: these implicit defaults are being phased out
= help: add `#[pyo3(signature = (_i, _any=None, _foo=None))]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:135:4
|
135 | fn pyfunction_option_4(
| ^^^^^^^^^^^^^^^^^^^
--> tests/ui/deprecations.rs:34:4
|
34 | fn pyfunction_option_4(
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `SimpleEnumWithoutEq::__pyo3__generated____richcmp__::DEPRECATION`: Implicit equality for simple enums is deprecated. Use `#[pyclass(eq, eq_int)` to keep the current behavior.
--> tests/ui/deprecations.rs:197:1
|
197 | #[pyclass]
| ^^^^^^^^^^
|
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)
error: use of deprecated struct `pyo3::PyCell`: `PyCell` was merged into `Bound`, use that instead; see the migration guide for more info
--> tests/ui/deprecations.rs:23:30
--> tests/ui/deprecations.rs:41:1
|
23 | fn method_gil_ref(_slf: &PyCell<Self>) {}
| ^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:42:44
41 | #[pyclass]
| ^^^^^^^^^^
|
42 | fn __eq__(&self, #[pyo3(from_py_with = "extract_gil_ref")] _other: i32) -> bool {
| ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:18:33
|
18 | fn cls_method_gil_ref(_cls: &PyType) {}
| ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:23:29
|
23 | fn method_gil_ref(_slf: &PyCell<Self>) {}
| ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:28:36
|
28 | fn static_method_gil_ref(_any: &PyAny) {}
| ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:31:53
|
31 | fn set_foo_gil_ref(&self, #[pyo3(from_py_with = "extract_gil_ref")] _value: i32) {}
| ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:37:39
|
37 | fn set_bar_gil_ref(&self, _value: &PyAny) {}
| ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:61:44
|
61 | fn pyfunction_with_module_gil_ref(_module: &PyModule) -> PyResult<&str> {
| ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:71:19
|
71 | fn module_gil_ref(_m: &PyModule) -> PyResult<()> {
| ^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:76:57
|
76 | fn module_gil_ref_with_explicit_py_arg(_py: Python<'_>, _m: &PyModule) -> PyResult<()> {
| ^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:112:27
|
112 | #[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32,
| ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:118:29
|
118 | fn pyfunction_gil_ref(_any: &PyAny) {}
| ^
error: use of deprecated method `pyo3::deprecations::OptionGilRefs::<std::option::Option<T>>::function_arg`: use `Option<&Bound<'_, T>>` instead for this function argument
--> tests/ui/deprecations.rs:122:36
|
122 | fn pyfunction_option_gil_ref(_any: Option<&PyAny>) {}
| ^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:147:27
|
147 | #[pyo3(from_py_with = "PyAny::len", item("my_object"))]
| ^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:157:27
|
157 | #[pyo3(from_py_with = "PyAny::len")] usize,
| ^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:163:31
|
163 | Zip(#[pyo3(from_py_with = "extract_gil_ref")] i32),
| ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:170:27
|
170 | #[pyo3(from_py_with = "extract_gil_ref")]
| ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<pyo3::Python<'_>>::is_python`: use `wrap_pyfunction_bound!` instead
--> tests/ui/deprecations.rs:183:13
|
183 | let _ = wrap_pyfunction!(double, py);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `wrap_pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)