Use local variables to extend lifetime of holder references.

This commit is contained in:
Adam Reichold 2023-05-06 12:42:27 +02:00
parent 1dca87972a
commit 27019b5523
1 changed files with 26 additions and 8 deletions

View File

@ -35,16 +35,18 @@ pub fn impl_arg_params(
if !fastcall && is_forwarded_args(&spec.signature) {
// In the varargs convention, we can just pass though if the signature
// is (*args, **kwds).
let mut holders = Vec::new();
let arg_convert = spec
.signature
.arguments
.iter()
.map(|arg| impl_arg_param(arg, &mut 0, &args_array))
.map(|arg| impl_arg_param(arg, &mut 0, &args_array, &mut holders))
.collect::<Result<_>>()?;
return Ok((
quote! {
let _args = py.from_borrowed_ptr::<_pyo3::types::PyTuple>(_args);
let _kwargs: ::std::option::Option<&_pyo3::types::PyDict> = py.from_borrowed_ptr_or_opt(_kwargs);
#( #holders )*
},
arg_convert,
));
@ -73,11 +75,12 @@ pub fn impl_arg_params(
let num_params = positional_parameter_names.len() + keyword_only_parameters.len();
let mut option_pos = 0;
let mut holders = Vec::new();
let param_conversion = spec
.signature
.arguments
.iter()
.map(|arg| impl_arg_param(arg, &mut option_pos, &args_array))
.map(|arg| impl_arg_param(arg, &mut option_pos, &args_array, &mut holders))
.collect::<Result<_>>()?;
let args_handler = if spec.signature.python_signature.varargs.is_some() {
@ -130,8 +133,8 @@ pub fn impl_arg_params(
required_positional_parameters: #required_positional_parameters,
keyword_only_parameters: &[#(#keyword_only_parameters),*],
};
let mut #args_array = [::std::option::Option::None; #num_params];
#( #holders )*
let (_args, _kwargs) = #extract_expression;
},
param_conversion,
@ -144,6 +147,7 @@ fn impl_arg_param(
arg: &FnArg<'_>,
option_pos: &mut usize,
args_array: &syn::Ident,
holders: &mut Vec<TokenStream>,
) -> Result<TokenStream> {
// Use this macro inside this function, to ensure that all code generated here is associated
// with the function argument
@ -162,15 +166,25 @@ fn impl_arg_param(
let name = arg.name;
let name_str = name.to_string();
let mut push_holder = || {
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), arg.ty.span());
holders.push(quote_arg_span! {
#[allow(clippy::let_unit_value)]
let mut #holder = _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT;
});
holder
};
if arg.is_varargs {
ensure_spanned!(
arg.optional.is_none(),
arg.name.span() => "args cannot be optional"
);
let holder = push_holder();
return Ok(quote_arg_span! {
_pyo3::impl_::extract_argument::extract_argument(
_args,
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
&mut #holder,
#name_str
)?
});
@ -179,10 +193,11 @@ fn impl_arg_param(
arg.optional.is_some(),
arg.name.span() => "kwargs must be Option<_>"
);
let holder = push_holder();
return Ok(quote_arg_span! {
_pyo3::impl_::extract_argument::extract_optional_argument(
_kwargs.map(::std::convert::AsRef::as_ref),
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
&mut #holder,
#name_str,
|| ::std::option::Option::None
)?
@ -221,30 +236,33 @@ fn impl_arg_param(
}
}
} else if arg.optional.is_some() {
let holder = push_holder();
quote_arg_span! {
#[allow(clippy::redundant_closure)]
_pyo3::impl_::extract_argument::extract_optional_argument(
#arg_value,
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
&mut #holder,
#name_str,
|| #default
)?
}
} else if let Some(default) = default {
let holder = push_holder();
quote_arg_span! {
#[allow(clippy::redundant_closure)]
_pyo3::impl_::extract_argument::extract_argument_with_default(
#arg_value,
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
&mut #holder,
#name_str,
|| #default
)?
}
} else {
let holder = push_holder();
quote_arg_span! {
_pyo3::impl_::extract_argument::extract_argument(
_pyo3::impl_::extract_argument::unwrap_required_argument(#arg_value),
&mut { _pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT },
&mut #holder,
#name_str
)?
}