Merge pull request #1805 from mejrs/proc_macro_hygiene

Test proc macro hygiene for `#[pyclass]` macro.
This commit is contained in:
David Hewitt 2021-08-18 19:08:41 +01:00 committed by GitHub
commit 0613b5a8f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 166 additions and 118 deletions

View File

@ -133,21 +133,21 @@ impl SelfType {
match self {
SelfType::Receiver { mutable: false } => {
quote! {
let _cell = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _cell = _py.from_borrowed_ptr::<::pyo3::PyCell<#cls>>(_slf);
let _ref = _cell.try_borrow()?;
let _slf = &_ref;
}
}
SelfType::Receiver { mutable: true } => {
quote! {
let _cell = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _cell = _py.from_borrowed_ptr::<::pyo3::PyCell<#cls>>(_slf);
let mut _ref = _cell.try_borrow_mut()?;
let _slf = &mut _ref;
}
}
SelfType::TryFromPyCell(span) => {
quote_spanned! { *span =>
let _cell = _py.from_borrowed_ptr::<pyo3::PyCell<#cls>>(_slf);
let _cell = _py.from_borrowed_ptr::<::pyo3::PyCell<#cls>>(_slf);
#[allow(clippy::useless_conversion)] // In case _slf is PyCell<Self>
let _slf = std::convert::TryFrom::try_from(_cell)?;
}

View File

@ -95,7 +95,7 @@ pub(crate) fn impl_method_proto(
};
Ok(quote! {
impl<'p> #module::#proto<'p> for #cls {
impl<'p> ::#module::#proto<'p> for #cls {
#(#impl_types)*
#res_type_def
}

View File

@ -47,7 +47,7 @@ impl Default for PyClassArgs {
freelist: None,
name: None,
module: None,
base: parse_quote! { pyo3::PyAny },
base: parse_quote! { ::pyo3::PyAny },
has_dict: false,
has_weaklist: false,
is_gc: false,
@ -345,22 +345,22 @@ fn impl_methods_inventory(cls: &syn::Ident) -> TokenStream {
quote! {
#[doc(hidden)]
pub struct #inventory_cls {
methods: Vec<pyo3::class::PyMethodDefType>,
methods: ::std::vec::Vec<::pyo3::class::PyMethodDefType>,
}
impl pyo3::class::impl_::PyMethodsInventory for #inventory_cls {
fn new(methods: Vec<pyo3::class::PyMethodDefType>) -> Self {
impl ::pyo3::class::impl_::PyMethodsInventory for #inventory_cls {
fn new(methods: ::std::vec::Vec<::pyo3::class::PyMethodDefType>) -> Self {
Self { methods }
}
fn get(&'static self) -> &'static [pyo3::class::PyMethodDefType] {
fn get(&'static self) -> &'static [::pyo3::class::PyMethodDefType] {
&self.methods
}
}
impl pyo3::class::impl_::HasMethodsInventory for #cls {
impl ::pyo3::class::impl_::HasMethodsInventory for #cls {
type Methods = #inventory_cls;
}
pyo3::inventory::collect!(#inventory_cls);
::pyo3::inventory::collect!(#inventory_cls);
}
}
@ -380,31 +380,31 @@ fn impl_class(
let alloc = attr.freelist.as_ref().map(|freelist| {
quote! {
impl pyo3::class::impl_::PyClassWithFreeList for #cls {
impl ::pyo3::class::impl_::PyClassWithFreeList for #cls {
#[inline]
fn get_free_list(_py: pyo3::Python<'_>) -> &mut pyo3::impl_::freelist::FreeList<*mut pyo3::ffi::PyObject> {
static mut FREELIST: *mut pyo3::impl_::freelist::FreeList<*mut pyo3::ffi::PyObject> = 0 as *mut _;
fn get_free_list(_py: ::pyo3::Python<'_>) -> &mut ::pyo3::impl_::freelist::FreeList<*mut ::pyo3::ffi::PyObject> {
static mut FREELIST: *mut ::pyo3::impl_::freelist::FreeList<*mut ::pyo3::ffi::PyObject> = 0 as *mut _;
unsafe {
if FREELIST.is_null() {
FREELIST = Box::into_raw(Box::new(
pyo3::impl_::freelist::FreeList::with_capacity(#freelist)));
FREELIST = ::std::boxed::Box::into_raw(::std::boxed::Box::new(
::pyo3::impl_::freelist::FreeList::with_capacity(#freelist)));
}
&mut *FREELIST
}
}
}
impl pyo3::class::impl_::PyClassAllocImpl<#cls> for pyo3::class::impl_::PyClassImplCollector<#cls> {
impl ::pyo3::class::impl_::PyClassAllocImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
#[inline]
fn alloc_impl(self) -> Option<pyo3::ffi::allocfunc> {
Some(pyo3::class::impl_::alloc_with_freelist::<#cls>)
fn alloc_impl(self) -> ::std::option::Option<::pyo3::ffi::allocfunc> {
::std::option::Option::Some(::pyo3::class::impl_::alloc_with_freelist::<#cls>)
}
}
impl pyo3::class::impl_::PyClassFreeImpl<#cls> for pyo3::class::impl_::PyClassImplCollector<#cls> {
impl ::pyo3::class::impl_::PyClassFreeImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
#[inline]
fn free_impl(self) -> Option<pyo3::ffi::freefunc> {
Some(pyo3::class::impl_::free_with_freelist::<#cls>)
fn free_impl(self) -> ::std::option::Option<::pyo3::ffi::freefunc> {
::std::option::Option::Some(::pyo3::class::impl_::free_with_freelist::<#cls>)
}
}
}
@ -414,23 +414,23 @@ fn impl_class(
// insert space for weak ref
let weakref = if attr.has_weaklist {
quote! { pyo3::pyclass_slots::PyClassWeakRefSlot }
quote! { ::pyo3::pyclass_slots::PyClassWeakRefSlot }
} else if attr.has_extends {
quote! { <Self::BaseType as pyo3::class::impl_::PyClassBaseType>::WeakRef }
quote! { <Self::BaseType as ::pyo3::class::impl_::PyClassBaseType>::WeakRef }
} else {
quote! { pyo3::pyclass_slots::PyClassDummySlot }
quote! { ::pyo3::pyclass_slots::PyClassDummySlot }
};
let dict = if attr.has_dict {
quote! { pyo3::pyclass_slots::PyClassDictSlot }
quote! { ::pyo3::pyclass_slots::PyClassDictSlot }
} else if attr.has_extends {
quote! { <Self::BaseType as pyo3::class::impl_::PyClassBaseType>::Dict }
quote! { <Self::BaseType as ::pyo3::class::impl_::PyClassBaseType>::Dict }
} else {
quote! { pyo3::pyclass_slots::PyClassDummySlot }
quote! { ::pyo3::pyclass_slots::PyClassDummySlot }
};
let module = if let Some(m) = &attr.module {
quote! { Some(#m) }
quote! { ::std::option::Option::Some(#m) }
} else {
quote! { None }
quote! { ::std::option::Option::None }
};
// Enforce at compile time that PyGCProtocol is implemented
@ -439,9 +439,9 @@ fn impl_class(
let closure_token = syn::Ident::new(&closure_name, Span::call_site());
quote! {
fn #closure_token() {
use pyo3::class;
use ::pyo3::class;
fn _assert_implements_protocol<'p, T: pyo3::class::PyGCProtocol<'p>>() {}
fn _assert_implements_protocol<'p, T: ::pyo3::class::PyGCProtocol<'p>>() {}
_assert_implements_protocol::<#cls>();
}
}
@ -450,12 +450,15 @@ fn impl_class(
};
let (impl_inventory, for_each_py_method) = match methods_type {
PyClassMethodsType::Specialization => (None, quote! { visitor(collector.py_methods()); }),
PyClassMethodsType::Specialization => (
::std::option::Option::None,
quote! { visitor(collector.py_methods()); },
),
PyClassMethodsType::Inventory => (
Some(impl_methods_inventory(cls)),
quote! {
for inventory in pyo3::inventory::iter::<<Self as pyo3::class::impl_::HasMethodsInventory>::Methods>() {
visitor(pyo3::class::impl_::PyMethodsInventory::get(inventory));
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::HasMethodsInventory>::Methods>() {
visitor(::pyo3::class::impl_::PyMethodsInventory::get(inventory));
}
},
),
@ -463,17 +466,17 @@ fn impl_class(
let base = &attr.base;
let base_nativetype = if attr.has_extends {
quote! { <Self::BaseType as pyo3::class::impl_::PyClassBaseType>::BaseNativeType }
quote! { <Self::BaseType as ::pyo3::class::impl_::PyClassBaseType>::BaseNativeType }
} else {
quote! { pyo3::PyAny }
quote! { ::pyo3::PyAny }
};
// If #cls is not extended type, we allow Self->PyObject conversion
let into_pyobject = if !attr.has_extends {
quote! {
impl pyo3::IntoPy<pyo3::PyObject> for #cls {
fn into_py(self, py: pyo3::Python) -> pyo3::PyObject {
pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py)
impl ::pyo3::IntoPy<::pyo3::PyObject> for #cls {
fn into_py(self, py: ::pyo3::Python) -> ::pyo3::PyObject {
::pyo3::IntoPy::into_py(::pyo3::Py::new(py, self).unwrap(), py)
}
}
}
@ -482,13 +485,13 @@ fn impl_class(
};
let thread_checker = if attr.has_unsendable {
quote! { pyo3::class::impl_::ThreadCheckerImpl<#cls> }
quote! { ::pyo3::class::impl_::ThreadCheckerImpl<#cls> }
} else if attr.has_extends {
quote! {
pyo3::class::impl_::ThreadCheckerInherited<#cls, <#cls as pyo3::class::impl_::PyClassImpl>::BaseType>
::pyo3::class::impl_::ThreadCheckerInherited<#cls, <#cls as ::pyo3::class::impl_::PyClassImpl>::BaseType>
}
} else {
quote! { pyo3::class::impl_::ThreadCheckerStub<#cls> }
quote! { ::pyo3::class::impl_::ThreadCheckerStub<#cls> }
};
let is_gc = attr.is_gc;
@ -496,54 +499,54 @@ fn impl_class(
let is_subclass = attr.has_extends;
Ok(quote! {
unsafe impl pyo3::type_object::PyTypeInfo for #cls {
type AsRefTarget = pyo3::PyCell<Self>;
unsafe impl ::pyo3::type_object::PyTypeInfo for #cls {
type AsRefTarget = ::pyo3::PyCell<Self>;
const NAME: &'static str = #cls_name;
const MODULE: Option<&'static str> = #module;
const MODULE: ::std::option::Option<&'static str> = #module;
#[inline]
fn type_object_raw(py: pyo3::Python<'_>) -> *mut pyo3::ffi::PyTypeObject {
fn type_object_raw(py: ::pyo3::Python<'_>) -> *mut ::pyo3::ffi::PyTypeObject {
#deprecations
use pyo3::type_object::LazyStaticType;
use ::pyo3::type_object::LazyStaticType;
static TYPE_OBJECT: LazyStaticType = LazyStaticType::new();
TYPE_OBJECT.get_or_init::<Self>(py)
}
}
impl pyo3::PyClass for #cls {
impl ::pyo3::PyClass for #cls {
type Dict = #dict;
type WeakRef = #weakref;
type BaseNativeType = #base_nativetype;
}
impl<'a> pyo3::derive_utils::ExtractExt<'a> for &'a #cls
impl<'a> ::pyo3::derive_utils::ExtractExt<'a> for &'a #cls
{
type Target = pyo3::PyRef<'a, #cls>;
type Target = ::pyo3::PyRef<'a, #cls>;
}
impl<'a> pyo3::derive_utils::ExtractExt<'a> for &'a mut #cls
impl<'a> ::pyo3::derive_utils::ExtractExt<'a> for &'a mut #cls
{
type Target = pyo3::PyRefMut<'a, #cls>;
type Target = ::pyo3::PyRefMut<'a, #cls>;
}
#into_pyobject
#impl_inventory
impl pyo3::class::impl_::PyClassImpl for #cls {
impl ::pyo3::class::impl_::PyClassImpl for #cls {
const DOC: &'static str = #doc;
const IS_GC: bool = #is_gc;
const IS_BASETYPE: bool = #is_basetype;
const IS_SUBCLASS: bool = #is_subclass;
type Layout = pyo3::PyCell<Self>;
type Layout = ::pyo3::PyCell<Self>;
type BaseType = #base;
type ThreadChecker = #thread_checker;
fn for_each_method_def(visitor: &mut dyn FnMut(&[pyo3::class::PyMethodDefType])) {
use pyo3::class::impl_::*;
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::class::PyMethodDefType])) {
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
#for_each_py_method;
visitor(collector.py_class_descriptors());
@ -554,30 +557,30 @@ fn impl_class(
visitor(collector.mapping_protocol_methods());
visitor(collector.number_protocol_methods());
}
fn get_new() -> Option<pyo3::ffi::newfunc> {
use pyo3::class::impl_::*;
fn get_new() -> ::std::option::Option<::pyo3::ffi::newfunc> {
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
collector.new_impl()
}
fn get_alloc() -> Option<pyo3::ffi::allocfunc> {
use pyo3::class::impl_::*;
fn get_alloc() -> ::std::option::Option<::pyo3::ffi::allocfunc> {
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
collector.alloc_impl()
}
fn get_free() -> Option<pyo3::ffi::freefunc> {
use pyo3::class::impl_::*;
fn get_free() -> ::std::option::Option<::pyo3::ffi::freefunc> {
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
collector.free_impl()
}
fn get_call() -> Option<pyo3::ffi::PyCFunctionWithKeywords> {
use pyo3::class::impl_::*;
fn get_call() -> ::std::option::Option<::pyo3::ffi::PyCFunctionWithKeywords> {
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
collector.call_impl()
}
fn for_each_proto_slot(visitor: &mut dyn FnMut(&[pyo3::ffi::PyType_Slot])) {
fn for_each_proto_slot(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::ffi::PyType_Slot])) {
// Implementation which uses dtolnay specialization to load all slots.
use pyo3::class::impl_::*;
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
visitor(collector.object_protocol_slots());
visitor(collector.number_protocol_slots());
@ -590,8 +593,8 @@ fn impl_class(
visitor(collector.buffer_protocol_slots());
}
fn get_buffer() -> Option<&'static pyo3::class::impl_::PyBufferProcs> {
use pyo3::class::impl_::*;
fn get_buffer() -> ::std::option::Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
use ::pyo3::class::impl_::*;
let collector = PyClassImplCollector::<Self>::new();
collector.buffer_procs()
}
@ -645,11 +648,11 @@ fn impl_descriptors(
.collect::<syn::Result<_>>()?;
Ok(quote! {
impl pyo3::class::impl_::PyClassDescriptors<#cls>
for pyo3::class::impl_::PyClassImplCollector<#cls>
impl ::pyo3::class::impl_::PyClassDescriptors<#cls>
for ::pyo3::class::impl_::PyClassImplCollector<#cls>
{
fn py_class_descriptors(self) -> &'static [pyo3::class::methods::PyMethodDefType] {
static METHODS: &[pyo3::class::methods::PyMethodDefType] = &[#(#py_methods),*];
fn py_class_descriptors(self) -> &'static [::pyo3::class::methods::PyMethodDefType] {
static METHODS: &[::pyo3::class::methods::PyMethodDefType] = &[#(#py_methods),*];
METHODS
}
}

View File

@ -102,7 +102,7 @@ pub fn impl_py_method_def(
};
let methoddef = spec.get_methoddef(quote! {{ #wrapper_def #wrapper_ident }});
Ok(quote! {
pyo3::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags)
::pyo3::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags)
})
}
@ -110,7 +110,7 @@ fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream>
let wrapper_ident = syn::Ident::new("__wrap", Span::call_site());
let wrapper = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
Ok(quote! {
impl pyo3::class::impl_::PyClassNewImpl<#cls> for pyo3::class::impl_::PyClassImplCollector<#cls> {
impl ::pyo3::class::impl_::PyClassNewImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
fn new_impl(self) -> Option<pyo3::ffi::newfunc> {
Some({
#wrapper
@ -125,7 +125,7 @@ fn impl_py_method_def_call(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream
let wrapper_ident = syn::Ident::new("__wrap", Span::call_site());
let wrapper = spec.get_wrapper_function(&wrapper_ident, Some(cls))?;
Ok(quote! {
impl pyo3::class::impl_::PyClassCallImpl<#cls> for pyo3::class::impl_::PyClassImplCollector<#cls> {
impl ::pyo3::class::impl_::PyClassCallImpl<#cls> for ::pyo3::class::impl_::PyClassImplCollector<#cls> {
fn call_impl(self) -> Option<pyo3::ffi::PyCFunctionWithKeywords> {
Some({
#wrapper
@ -141,13 +141,13 @@ fn impl_py_class_attribute(cls: &syn::Type, spec: &FnSpec) -> TokenStream {
let deprecations = &spec.deprecations;
let python_name = spec.null_terminated_python_name();
quote! {
pyo3::class::PyMethodDefType::ClassAttribute({
pyo3::class::PyClassAttributeDef::new(
::pyo3::class::PyMethodDefType::ClassAttribute({
::pyo3::class::PyClassAttributeDef::new(
#python_name,
pyo3::class::methods::PyClassAttributeFactory({
fn __wrap(py: pyo3::Python<'_>) -> pyo3::PyObject {
::pyo3::class::methods::PyClassAttributeFactory({
fn __wrap(py: ::pyo3::Python<'_>) -> ::pyo3::PyObject {
#deprecations
pyo3::IntoPy::into_py(#cls::#name(), py)
::pyo3::IntoPy::into_py(#cls::#name(), py)
}
__wrap
})
@ -206,26 +206,26 @@ pub fn impl_py_setter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
PropertyType::Function { self_type, .. } => self_type.receiver(cls),
};
Ok(quote! {
pyo3::class::PyMethodDefType::Setter({
::pyo3::class::PyMethodDefType::Setter({
#deprecations
pyo3::class::PySetterDef::new(
::pyo3::class::PySetterDef::new(
#python_name,
pyo3::class::methods::PySetter({
::pyo3::class::methods::PySetter({
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject,
_value: *mut pyo3::ffi::PyObject,
_: *mut std::os::raw::c_void
) -> std::os::raw::c_int {
pyo3::callback::handle_panic(|_py| {
_slf: *mut ::pyo3::ffi::PyObject,
_value: *mut ::pyo3::ffi::PyObject,
_: *mut ::std::os::raw::c_void
) -> ::std::os::raw::c_int {
::pyo3::callback::handle_panic(|_py| {
#slf
let _value = _py
.from_borrowed_ptr_or_opt(_value)
.ok_or_else(|| {
pyo3::exceptions::PyAttributeError::new_err("can't delete attribute")
::pyo3::exceptions::PyAttributeError::new_err("can't delete attribute")
})?;
let _val = pyo3::FromPyObject::extract(_value)?;
let _val = ::pyo3::FromPyObject::extract(_value)?;
pyo3::callback::convert(_py, #setter_impl)
::pyo3::callback::convert(_py, #setter_impl)
})
}
__wrap
@ -266,12 +266,13 @@ pub fn impl_py_getter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
..
} => {
// named struct field
quote!(_slf.#ident.clone())
//quote!(_slf.#ident.clone())
quote!(::std::clone::Clone::clone(&(_slf.#ident)))
}
PropertyType::Descriptor { field_index, .. } => {
// tuple struct field
let index = syn::Index::from(field_index);
quote!(_slf.#index.clone())
quote!(::std::clone::Clone::clone(&(_slf.#index)))
}
PropertyType::Function { spec, .. } => impl_call_getter(cls, spec)?,
};
@ -281,18 +282,18 @@ pub fn impl_py_getter_def(cls: &syn::Type, property_type: PropertyType) -> Resul
PropertyType::Function { self_type, .. } => self_type.receiver(cls),
};
Ok(quote! {
pyo3::class::PyMethodDefType::Getter({
::pyo3::class::PyMethodDefType::Getter({
#deprecations
pyo3::class::PyGetterDef::new(
::pyo3::class::PyGetterDef::new(
#python_name,
pyo3::class::methods::PyGetter({
::pyo3::class::methods::PyGetter({
unsafe extern "C" fn __wrap(
_slf: *mut pyo3::ffi::PyObject,
_: *mut std::os::raw::c_void
) -> *mut pyo3::ffi::PyObject {
pyo3::callback::handle_panic(|_py| {
_slf: *mut ::pyo3::ffi::PyObject,
_: *mut ::std::os::raw::c_void
) -> *mut ::pyo3::ffi::PyObject {
::pyo3::callback::handle_panic(|_py| {
#slf
pyo3::callback::convert(_py, #getter_impl)
::pyo3::callback::convert(_py, #getter_impl)
})
}
__wrap

View File

@ -68,7 +68,7 @@ fn impl_proto_impl(
let flags = if m.can_coexist {
// We need METH_COEXIST here to prevent __add__ from overriding __radd__
Some(quote!(pyo3::ffi::METH_COEXIST))
Some(quote!(::pyo3::ffi::METH_COEXIST))
} else {
None
};
@ -106,11 +106,11 @@ fn impl_normal_methods(
let methods_trait = proto.methods_trait();
let methods_trait_methods = proto.methods_trait_methods();
quote! {
impl pyo3::class::impl_::#methods_trait<#ty>
for pyo3::class::impl_::PyClassImplCollector<#ty>
impl ::pyo3::class::impl_::#methods_trait<#ty>
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
{
fn #methods_trait_methods(self) -> &'static [pyo3::class::methods::PyMethodDefType] {
static METHODS: &[pyo3::class::methods::PyMethodDefType] =
fn #methods_trait_methods(self) -> &'static [::pyo3::class::methods::PyMethodDefType] {
static METHODS: &[::pyo3::class::methods::PyMethodDefType] =
&[#(#py_methods),*];
METHODS
}
@ -139,14 +139,14 @@ fn impl_proto_methods(
if build_config.version <= PY39 && proto.name == "Buffer" {
maybe_buffer_methods = Some(quote! {
impl pyo3::class::impl_::PyBufferProtocolProcs<#ty>
for pyo3::class::impl_::PyClassImplCollector<#ty>
impl ::pyo3::class::impl_::PyBufferProtocolProcs<#ty>
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
{
fn buffer_procs(
self
) -> Option<&'static pyo3::class::impl_::PyBufferProcs> {
static PROCS: pyo3::class::impl_::PyBufferProcs
= pyo3::class::impl_::PyBufferProcs {
) -> Option<&'static ::pyo3::class::impl_::PyBufferProcs> {
static PROCS: ::pyo3::class::impl_::PyBufferProcs
= ::pyo3::class::impl_::PyBufferProcs {
bf_getbuffer: Some(pyo3::class::buffer::getbuffer::<#ty>),
bf_releasebuffer: Some(pyo3::class::buffer::releasebuffer::<#ty>),
};
@ -162,9 +162,9 @@ fn impl_proto_methods(
let slot = syn::Ident::new(def.slot, Span::call_site());
let slot_impl = syn::Ident::new(def.slot_impl, Span::call_site());
quote! {{
pyo3::ffi::PyType_Slot {
slot: pyo3::ffi::#slot,
pfunc: #module::#slot_impl::<#ty> as _
::pyo3::ffi::PyType_Slot {
slot: ::pyo3::ffi::#slot,
pfunc: ::#module::#slot_impl::<#ty> as _
}
}}
})
@ -177,10 +177,10 @@ fn impl_proto_methods(
quote! {
#maybe_buffer_methods
impl pyo3::class::impl_::#slots_trait<#ty>
for pyo3::class::impl_::PyClassImplCollector<#ty>
impl ::pyo3::class::impl_::#slots_trait<#ty>
for ::pyo3::class::impl_::PyClassImplCollector<#ty>
{
fn #slots_trait_slots(self) -> &'static [pyo3::ffi::PyType_Slot] {
fn #slots_trait_slots(self) -> &'static [::pyo3::ffi::PyType_Slot] {
&[#(#tokens),*]
}
}

View File

@ -0,0 +1,44 @@
#![no_implicit_prelude]
#[::pyo3::proc_macro::pyclass]
#[derive(::std::clone::Clone)]
pub struct Foo;
#[::pyo3::proc_macro::pyclass]
pub struct Foo2;
#[::pyo3::proc_macro::pyclass(
name = "ActuallyBar",
freelist = 8,
weakref,
unsendable,
gc,
subclass,
extends = ::pyo3::types::PyAny,
module = "Spam"
)]
pub struct Bar {
#[pyo3(get, set)]
a: u8,
#[pyo3(get, set)]
b: Foo,
#[pyo3(get, set)]
c: ::std::option::Option<::pyo3::Py<Foo2>>,
}
#[::pyo3::proc_macro::pyproto]
impl ::pyo3::class::gc::PyGCProtocol for Bar {
fn __traverse__(
&self,
visit: ::pyo3::class::gc::PyVisit,
) -> ::std::result::Result<(), ::pyo3::class::gc::PyTraverseError> {
if let ::std::option::Option::Some(obj) = &self.c {
visit.call(obj)?
}
::std::result::Result::Ok(())
}
fn __clear__(&mut self) {
self.c = ::std::option::Option::None;
}
}