forked from Rust-related/RustPython
Make PyMethodDef construction const (#5117)
* Make PyMethodDef construction const * Remove iter_chain![] Obsolete since arrays now impl IntoIterator
This commit is contained in:
@@ -4,7 +4,7 @@ use crate::util::{
|
||||
ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ExceptionItemMeta, ItemMeta,
|
||||
ItemMetaInner, ItemNursery, SimpleItemMeta, ALL_ALLOWED_NAMES,
|
||||
};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::str::FromStr;
|
||||
@@ -172,14 +172,9 @@ pub(crate) fn impl_pyclass_impl(attr: AttributeArgs, item: Item) -> Result<Token
|
||||
let slots_impl = context.extend_slots_items.validate()?;
|
||||
let class_extensions = &context.class_extensions;
|
||||
|
||||
let extra_methods = iter_chain![
|
||||
let extra_methods = [
|
||||
parse_quote! {
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn __extend_method_def(
|
||||
method_defs: &mut Vec<::rustpython_vm::function::PyMethodDef>,
|
||||
) {
|
||||
#method_def
|
||||
}
|
||||
const __OWN_METHOD_DEFS: &'static [::rustpython_vm::function::PyMethodDef] = &#method_def;
|
||||
},
|
||||
parse_quote! {
|
||||
fn __extend_py_class(
|
||||
@@ -201,6 +196,15 @@ pub(crate) fn impl_pyclass_impl(attr: AttributeArgs, item: Item) -> Result<Token
|
||||
imp.items.extend(extra_methods);
|
||||
let is_main_impl = impl_ty == payload_ty;
|
||||
if is_main_impl {
|
||||
let method_defs = if with_method_defs.is_empty() {
|
||||
quote!(#impl_ty::__OWN_METHOD_DEFS)
|
||||
} else {
|
||||
quote!(
|
||||
rustpython_vm::function::PyMethodDef::__const_concat_arrays::<
|
||||
{ #impl_ty::__OWN_METHOD_DEFS.len() #(+ #with_method_defs.len())* },
|
||||
>(&[#impl_ty::__OWN_METHOD_DEFS, #(#with_method_defs,)*])
|
||||
)
|
||||
};
|
||||
quote! {
|
||||
#imp
|
||||
impl ::rustpython_vm::class::PyClassImpl for #payload_ty {
|
||||
@@ -214,13 +218,7 @@ pub(crate) fn impl_pyclass_impl(attr: AttributeArgs, item: Item) -> Result<Token
|
||||
#with_impl
|
||||
}
|
||||
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn impl_extend_method_def(
|
||||
method_defs: &mut Vec<::rustpython_vm::function::PyMethodDef>,
|
||||
) {
|
||||
#impl_ty::__extend_method_def(method_defs);
|
||||
#with_method_defs
|
||||
}
|
||||
const METHOD_DEFS: &'static [::rustpython_vm::function::PyMethodDef] = &#method_defs;
|
||||
|
||||
fn extend_slots(slots: &mut ::rustpython_vm::types::PyTypeSlots) {
|
||||
#impl_ty::__extend_slots(slots);
|
||||
@@ -268,14 +266,9 @@ pub(crate) fn impl_pyclass_impl(attr: AttributeArgs, item: Item) -> Result<Token
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
let extra_methods = iter_chain![
|
||||
let extra_methods = [
|
||||
parse_quote! {
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn __extend_method_def(
|
||||
method_defs: &mut Vec<::rustpython_vm::function::PyMethodDef>,
|
||||
) {
|
||||
#method_def
|
||||
}
|
||||
const __OWN_METHOD_DEFS: &'static [::rustpython_vm::function::PyMethodDef] = &#method_def;
|
||||
},
|
||||
parse_quote! {
|
||||
fn __extend_py_class(
|
||||
@@ -983,6 +976,7 @@ impl MethodNursery {
|
||||
|
||||
impl ToTokens for MethodNursery {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let mut inner_tokens = TokenStream::new();
|
||||
for item in &self.items {
|
||||
let py_name = &item.py_name;
|
||||
let ident = &item.ident;
|
||||
@@ -1011,16 +1005,18 @@ impl ToTokens for MethodNursery {
|
||||
// } else {
|
||||
// quote_spanned! { ident.span() => #py_name }
|
||||
// };
|
||||
tokens.extend(quote! {
|
||||
inner_tokens.extend(quote! [
|
||||
#(#cfgs)*
|
||||
method_defs.push(rustpython_vm::function::PyMethodDef {
|
||||
name: #py_name,
|
||||
func: rustpython_vm::function::IntoPyNativeFn::into_func(Self::#ident),
|
||||
flags: #flags,
|
||||
doc: #doc,
|
||||
});
|
||||
});
|
||||
rustpython_vm::function::PyMethodDef::new_const(
|
||||
#py_name,
|
||||
Self::#ident,
|
||||
#flags,
|
||||
#doc,
|
||||
),
|
||||
]);
|
||||
}
|
||||
let array: TokenTree = Group::new(Delimiter::Bracket, inner_tokens).into();
|
||||
tokens.extend([array]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1436,7 +1432,7 @@ struct ExtractedImplAttrs {
|
||||
payload: Option<Ident>,
|
||||
flags: TokenStream,
|
||||
with_impl: TokenStream,
|
||||
with_method_defs: TokenStream,
|
||||
with_method_defs: Vec<TokenStream>,
|
||||
with_slots: TokenStream,
|
||||
}
|
||||
|
||||
@@ -1465,18 +1461,18 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
|
||||
let NestedMeta::Meta(Meta::Path(path)) = meta else {
|
||||
bail_span!(meta, "#[pyclass(with(...))] arguments should be paths")
|
||||
};
|
||||
let (extend_class, extend_method_def, extend_slots) =
|
||||
let (extend_class, method_defs, extend_slots) =
|
||||
if path.is_ident("PyRef") || path.is_ident("Py") {
|
||||
// special handling for PyRef
|
||||
(
|
||||
quote!(#path::<Self>::__extend_py_class),
|
||||
quote!(#path::<Self>::__extend_method_def),
|
||||
quote!(#path::<Self>::__OWN_METHOD_DEFS),
|
||||
quote!(#path::<Self>::__extend_slots),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
quote!(<Self as #path>::__extend_py_class),
|
||||
quote!(<Self as #path>::__extend_method_def),
|
||||
quote!(<Self as #path>::__OWN_METHOD_DEFS),
|
||||
quote!(<Self as #path>::__extend_slots),
|
||||
)
|
||||
};
|
||||
@@ -1484,9 +1480,7 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
|
||||
withs.push(quote_spanned! { path.span() =>
|
||||
#extend_class(ctx, class);
|
||||
});
|
||||
with_method_defs.push(quote_spanned! { path.span() =>
|
||||
#extend_method_def(method_defs);
|
||||
});
|
||||
with_method_defs.push(method_defs);
|
||||
with_slots.push(quote_spanned! { item_span =>
|
||||
#extend_slots(slots);
|
||||
});
|
||||
@@ -1530,9 +1524,7 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
|
||||
with_impl: quote! {
|
||||
#(#withs)*
|
||||
},
|
||||
with_method_defs: quote! {
|
||||
#(#with_method_defs)*
|
||||
},
|
||||
with_method_defs,
|
||||
with_slots: quote! {
|
||||
#(#with_slots)*
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::util::{
|
||||
AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery,
|
||||
ModuleItemMeta, SimpleItemMeta, ALL_ALLOWED_NAMES,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use std::{collections::HashSet, str::FromStr};
|
||||
use syn::{parse_quote, spanned::Spanned, Attribute, AttributeArgs, Ident, Item, Result};
|
||||
@@ -110,7 +110,7 @@ pub fn impl_pymodule(attr: AttributeArgs, module_item: Item) -> Result<TokenStre
|
||||
let is_submodule = module_meta.sub()?;
|
||||
let withs = module_meta.with()?;
|
||||
if !is_submodule {
|
||||
items.extend(iter_chain![
|
||||
items.extend([
|
||||
parse_quote! {
|
||||
pub(crate) const MODULE_NAME: &'static str = #module_name;
|
||||
},
|
||||
@@ -122,16 +122,10 @@ pub fn impl_pymodule(attr: AttributeArgs, module_item: Item) -> Result<TokenStre
|
||||
ctx: &::rustpython_vm::Context,
|
||||
) -> &'static ::rustpython_vm::builtins::PyModuleDef {
|
||||
DEF.get_or_init(|| {
|
||||
#[allow(clippy::ptr_arg)]
|
||||
let method_defs = {
|
||||
let mut method_defs = Vec::new();
|
||||
extend_method_def(ctx, &mut method_defs);
|
||||
method_defs
|
||||
};
|
||||
let mut def = ::rustpython_vm::builtins::PyModuleDef {
|
||||
name: ctx.intern_str(MODULE_NAME),
|
||||
doc: DOC.map(|doc| ctx.intern_str(doc)),
|
||||
methods: Box::leak(method_defs.into_boxed_slice()),
|
||||
methods: METHOD_DEFS,
|
||||
slots: Default::default(),
|
||||
};
|
||||
def.slots.exec = Some(extend_module);
|
||||
@@ -161,23 +155,24 @@ pub fn impl_pymodule(attr: AttributeArgs, module_item: Item) -> Result<TokenStre
|
||||
}
|
||||
});
|
||||
}
|
||||
items.extend(iter_chain![
|
||||
let method_defs = if withs.is_empty() {
|
||||
quote!(#function_items)
|
||||
} else {
|
||||
quote!({
|
||||
const OWN_METHODS: &'static [::rustpython_vm::function::PyMethodDef] = &#function_items;
|
||||
rustpython_vm::function::PyMethodDef::__const_concat_arrays::<
|
||||
{ OWN_METHODS.len() #(+ super::#withs::METHOD_DEFS.len())* },
|
||||
>(&[#(super::#withs::METHOD_DEFS,)* OWN_METHODS])
|
||||
})
|
||||
};
|
||||
items.extend([
|
||||
parse_quote! {
|
||||
::rustpython_vm::common::static_cell! {
|
||||
pub(crate) static DEF: ::rustpython_vm::builtins::PyModuleDef;
|
||||
}
|
||||
},
|
||||
parse_quote! {
|
||||
#[allow(clippy::ptr_arg)]
|
||||
pub(crate) fn extend_method_def(
|
||||
ctx: &::rustpython_vm::Context,
|
||||
method_defs: &mut Vec<::rustpython_vm::function::PyMethodDef>,
|
||||
) {
|
||||
#(
|
||||
super::#withs::extend_method_def(ctx, method_defs);
|
||||
)*
|
||||
#function_items
|
||||
}
|
||||
pub(crate) const METHOD_DEFS: &'static [::rustpython_vm::function::PyMethodDef] = &#method_defs;
|
||||
},
|
||||
parse_quote! {
|
||||
pub(crate) fn __init_attributes(
|
||||
@@ -361,26 +356,30 @@ struct ValidatedFunctionNursery(FunctionNursery);
|
||||
|
||||
impl ToTokens for ValidatedFunctionNursery {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let mut inner_tokens = TokenStream::new();
|
||||
let flags = quote! { rustpython_vm::function::PyMethodFlags::empty() };
|
||||
for item in &self.0.items {
|
||||
let ident = &item.ident;
|
||||
let cfgs = &item.cfgs;
|
||||
let cfgs = quote!(#(#cfgs)*);
|
||||
let py_names = &item.py_names;
|
||||
let doc = &item.doc;
|
||||
let flags = quote! { rustpython_vm::function::PyMethodFlags::empty() };
|
||||
let doc = quote!(Some(#doc));
|
||||
|
||||
tokens.extend(quote! {
|
||||
#(#cfgs)*
|
||||
{
|
||||
let doc = Some(#doc);
|
||||
#(method_defs.push(rustpython_vm::function::PyMethodDef::new(
|
||||
(#py_names),
|
||||
inner_tokens.extend(quote![
|
||||
#(
|
||||
#cfgs
|
||||
rustpython_vm::function::PyMethodDef::new_const(
|
||||
#py_names,
|
||||
#ident,
|
||||
#flags,
|
||||
doc,
|
||||
));)*
|
||||
}
|
||||
});
|
||||
#doc,
|
||||
),
|
||||
)*
|
||||
]);
|
||||
}
|
||||
let array: TokenTree = Group::new(Delimiter::Bracket, inner_tokens).into();
|
||||
tokens.extend([array]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -639,13 +639,6 @@ impl ErrorVec for Vec<syn::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! iter_chain {
|
||||
($($it:expr),*$(,)?) => {
|
||||
::std::iter::empty()
|
||||
$(.chain(::std::iter::once($it)))*
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn iter_use_idents<'a, F, R: 'a>(item_use: &'a syn::ItemUse, mut f: F) -> Result<Vec<R>>
|
||||
where
|
||||
F: FnMut(&'a syn::Ident, bool) -> Result<R>,
|
||||
|
||||
Reference in New Issue
Block a user