Skip to content

Commit 8eb5dc0

Browse files
committed
use associated consts
1 parent 52ade64 commit 8eb5dc0

File tree

10 files changed

+34
-58
lines changed

10 files changed

+34
-58
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ features = ["extension-module"]
7575
**`src/lib.rs`**
7676

7777
```rust
78-
#![feature(proc_macro, specialization)]
78+
#![feature(proc_macro, specialization, associated_consts)]
7979

8080
extern crate pyo3;
8181
use pyo3::{py, PyResult, Python, PyModule};

guide/src/class.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Python class generation is powered by unstable [Procedural Macros](https://doc.r
44
[Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) features, so you need to turn on `proc_macro` and `specialization` features:
55

66
```rust
7-
#![feature(proc_macro, specialization)]
7+
#![feature(proc_macro, specialization, associated_consts)]
88

99
extern crate pyo3;
1010
```

pyo3cls/src/py_class.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
3232
let tokens = impl_class(&ast.ident, &base, token, doc, params);
3333

3434
quote! {
35-
#[feature(specialization)]
3635
#[allow(non_upper_case_globals, unused_attributes,
3736
unused_qualifications, unused_variables, non_camel_case_types)]
3837
const #dummy_const: () = {
@@ -167,6 +166,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
167166
quote! {
168167
impl _pyo3::typeob::PyTypeInfo for #cls {
169168
type Type = #cls;
169+
const NAME: &'static str = #cls_name;
170+
const DESCRIPTION: &'static str = #doc;
170171

171172
#[inline]
172173
fn size() -> usize {
@@ -182,16 +183,10 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
182183
((bs + align - 1) / align * align) as isize
183184
}
184185

185-
fn type_name() -> &'static str { #cls_name }
186-
187-
fn type_description() -> &'static str {
188-
#doc
189-
}
190-
191186
#[inline]
192-
fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
187+
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
193188
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
194-
unsafe { &mut TYPE_OBJECT }
189+
&mut TYPE_OBJECT
195190
}
196191

197192
#[inline]
@@ -206,16 +201,13 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
206201
fn init_type(py: Python) {
207202
static START: std::sync::Once = std::sync::ONCE_INIT;
208203
START.call_once(|| {
209-
let mut ty = <#cls as _pyo3::typeob::PyTypeInfo>::type_object();
204+
let mut ty = unsafe{<#cls as _pyo3::typeob::PyTypeInfo>::type_object()};
210205

211206
if (ty.tp_flags & _pyo3::ffi::Py_TPFLAGS_READY) == 0 {
212207
// automatically initialize the class on-demand
213-
_pyo3::typeob::initialize_type::<#cls>(
214-
py, None, <#cls as _pyo3::typeob::PyTypeInfo>::type_name(),
215-
<#cls as _pyo3::typeob::PyTypeInfo>::type_description(), ty).expect(
208+
_pyo3::typeob::initialize_type::<#cls>(py, None, ty).expect(
216209
format!("An error occurred while initializing class {}",
217-
<#cls as _pyo3::typeob::PyTypeInfo>::type_name())
218-
.as_ref());
210+
<#cls as _pyo3::typeob::PyTypeInfo>::NAME).as_ref());
219211
}
220212
});
221213
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(specialization, const_fn, proc_macro)]
1+
#![feature(specialization, proc_macro, const_fn, associated_consts)]
22

33
//! Rust bindings to the Python interpreter.
44
//!

src/objects/mod.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ macro_rules! pyobject_nativetype(
139139

140140
impl $crate::typeob::PyTypeInfo for $name {
141141
type Type = ();
142+
const NAME: &'static str = stringify!($name);
142143

143144
#[inline]
144145
fn size() -> usize {
@@ -149,12 +150,8 @@ macro_rules! pyobject_nativetype(
149150
0
150151
}
151152
#[inline]
152-
fn type_name() -> &'static str {
153-
stringify!($name)
154-
}
155-
#[inline]
156-
fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
157-
unsafe { &mut $crate::ffi::$typeobject }
153+
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
154+
&mut $crate::ffi::$typeobject
158155
}
159156
#[inline]
160157
fn is_instance(ptr: *mut $crate::ffi::PyObject) -> bool {

src/objects/module.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,23 +109,21 @@ impl PyModule {
109109
pub fn add_class<T>(&self) -> PyResult<()>
110110
where T: ::typeob::PyTypeInfo
111111
{
112-
let mut ty = <T as ::typeob::PyTypeInfo>::type_object();
113-
let type_name = <T as ::typeob::PyTypeInfo>::type_name();
112+
let mut ty = unsafe{<T as ::typeob::PyTypeInfo>::type_object()};
114113

115114
let ty = if (ty.tp_flags & ffi::Py_TPFLAGS_READY) != 0 {
116115
unsafe { PyType::from_type_ptr(self.token(), ty) }
117116
} else {
118117
// automatically initialize the class
119118
let name = self.name()?;
120-
let type_description = <T as ::typeob::PyTypeInfo>::type_description();
121119

122120
::typeob::initialize_type::<T>(
123-
self.token(), Some(name), type_name, type_description, ty)
124-
.expect(format!("An error occurred while initializing class {}",
125-
<T as ::typeob::PyTypeInfo>::type_name()).as_ref());
121+
self.token(), Some(name), ty)
122+
.expect(
123+
format!("An error occurred while initializing class {}", T::NAME).as_ref());
126124
unsafe { PyType::from_type_ptr(self.token(), ty) }
127125
};
128126

129-
self.setattr(type_name, ty)
127+
self.setattr(T::NAME, ty)
130128
}
131129
}

src/typeob.rs

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,19 @@ use class::methods::PyMethodDefType;
2121
pub trait PyTypeInfo {
2222
/// Type of objects to store in PyObject struct
2323
type Type;
24+
/// Class name
25+
const NAME: &'static str;
26+
/// Class doc string
27+
const DESCRIPTION: &'static str = "\0";
2428

2529
/// Size of the PyObject structure
2630
fn size() -> usize;
2731

2832
/// `Type` instance offset inside PyObject structure
2933
fn offset() -> isize;
3034

31-
/// Type name
32-
fn type_name() -> &'static str;
33-
34-
/// Type description
35-
fn type_description() -> &'static str { "\0" }
36-
3735
/// PyTypeObject instance for this type
38-
fn type_object() -> &'static mut ffi::PyTypeObject;
36+
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
3937

4038
/// Check `*mut ffi::PyObject` if it is the same type
4139
fn is_instance(ptr: *mut ffi::PyObject) -> bool;
@@ -45,6 +43,7 @@ pub trait PyTypeInfo {
4543

4644
impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
4745
type Type = T::Type;
46+
const NAME: &'static str = T::NAME;
4847

4948
#[inline]
5049
default fn size() -> usize {
@@ -57,12 +56,7 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
5756
}
5857

5958
#[inline]
60-
default fn type_name() -> &'static str {
61-
<T as PyTypeInfo>::type_name()
62-
}
63-
64-
#[inline]
65-
default fn type_object() -> &'static mut ffi::PyTypeObject {
59+
default unsafe fn type_object() -> &'static mut ffi::PyTypeObject {
6660
<T as PyTypeInfo>::type_object()
6761
}
6862

@@ -140,15 +134,12 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
140134

141135
#[inline]
142136
default fn init_type(py: Python) {
143-
let mut ty = <T as PyTypeInfo>::type_object();
137+
let mut ty = unsafe { <T as PyTypeInfo>::type_object() };
144138

145139
if (ty.tp_flags & ffi::Py_TPFLAGS_READY) == 0 {
146140
// automatically initialize the class on-demand
147-
initialize_type::<T>(
148-
py, None, <T as PyTypeInfo>::type_name(),
149-
<T as PyTypeInfo>::type_description(), ty).expect(
150-
format!("An error occurred while initializing class {}",
151-
<T as PyTypeInfo>::type_name()).as_ref());
141+
initialize_type::<T>(py, None, ty).expect(
142+
format!("An error occurred while initializing class {}", T::NAME).as_ref());
152143
}
153144
}
154145

@@ -163,21 +154,19 @@ impl<T> PyTypeObject for T where T: PyObjectAlloc<T> + PyTypeInfo {
163154

164155
pub fn initialize_type<'p, T>(py: Python<'p>,
165156
module_name: Option<&str>,
166-
type_name: &str,
167-
type_description: &'static str,
168157
type_object: &mut ffi::PyTypeObject) -> PyResult<&'p PyType>
169158
where T: PyObjectAlloc<T> + PyTypeInfo
170159
{
171160
// type name
172161
let name = match module_name {
173-
Some(module_name) => CString::new(format!("{}.{}", module_name, type_name)),
174-
None => CString::new(type_name)
162+
Some(module_name) => CString::new(format!("{}.{}", module_name, T::NAME)),
163+
None => CString::new(T::NAME)
175164
};
176165
let name = name.expect(
177166
"Module name/type name must not contain NUL byte").into_raw();
178167

179168
type_object.tp_name = name;
180-
type_object.tp_doc = type_description.as_ptr() as *const _;
169+
type_object.tp_doc = T::DESCRIPTION.as_ptr() as *const _;
181170

182171
// dealloc
183172
type_object.tp_dealloc = Some(tp_dealloc_callback::<T>);

tests/test_buffer_protocol.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![allow(dead_code, unused_variables)]
2-
#![feature(proc_macro, specialization)]
2+
#![feature(proc_macro, specialization, associated_consts)]
33

44
extern crate pyo3;
55

tests/test_class.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(proc_macro, specialization)]
1+
#![feature(proc_macro, specialization, associated_consts)]
22
#![allow(dead_code, unused_variables)]
33

44
extern crate pyo3;

tests/test_slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(proc_macro, specialization)]
1+
#![feature(proc_macro, specialization, associated_consts)]
22
#![allow(dead_code, unused_variables)]
33

44
extern crate pyo3;

0 commit comments

Comments
 (0)