Add support for Rust stable.
All functions that depend on PyObject having the same memory layout as *mut ffi::PyObject should now be hidden behind #[cfg(feature="nightly")].
This commit is contained in:
parent
ad7f43efc7
commit
d705620502
|
@ -5,6 +5,7 @@ python:
|
|||
- "3.4"
|
||||
- "3.5"
|
||||
env:
|
||||
- RUST_VERSION=1.7
|
||||
- RUST_VERSION=nightly
|
||||
sudo: false
|
||||
install:
|
||||
|
|
3
Makefile
3
Makefile
|
@ -34,7 +34,10 @@ build:
|
|||
|
||||
test: build
|
||||
cargo test $(CARGO_FLAGS)
|
||||
ifeq ($(NIGHTLY),1)
|
||||
# ast-json output is only supported on nightly
|
||||
python$(PY) tests/check_symbols.py
|
||||
endif
|
||||
|
||||
doc: build
|
||||
cargo doc --no-deps $(CARGO_FLAGS)
|
||||
|
|
|
@ -13,7 +13,7 @@ py_module_initializer!(hello, inithello, PyInit_hello, |py, m| {
|
|||
|
||||
fn run(py: Python, args: &PyTuple, kwargs: Option<&PyDict>) -> PyResult<PyObject> {
|
||||
println!("Rust says: Hello Python!");
|
||||
for arg in args.as_slice() {
|
||||
for arg in args.iter(py) {
|
||||
println!("Rust got {}", arg);
|
||||
}
|
||||
if let Some(kwargs) = kwargs {
|
||||
|
|
|
@ -199,7 +199,7 @@ impl PyErr {
|
|||
Err(_) =>
|
||||
match self.ptype.cast_as::<PyClass>(py) {
|
||||
Ok(_) => py.get_type::<PyClass>(),
|
||||
Err(_) => py.None().get_type().clone_ref(py)
|
||||
Err(_) => py.None().get_type(py)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ impl PyErr {
|
|||
pub fn get_type(&self, py: Python) -> PyType {
|
||||
match self.ptype.cast_as::<PyType>(py) {
|
||||
Ok(t) => t.clone_ref(py),
|
||||
Err(_) => py.None().get_type().clone_ref(py)
|
||||
Err(_) => py.None().get_type(py)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,20 +59,27 @@ macro_rules! py_fn_wrap {
|
|||
let _guard = $crate::_detail::PanicGuard::with_message(
|
||||
concat!("Rust panic in py_fn!(", stringify!($f), ")"));
|
||||
let $py: $crate::Python = $crate::_detail::bounded_assume_gil_acquired(&args);
|
||||
let $args: &$crate::PyTuple = $crate::PyObject::borrow_from_ptr(&args).unchecked_cast_as();
|
||||
let $kwargs: Option<&$crate::PyDict> = $crate::_detail::get_kwargs(&kwargs);
|
||||
let args: $crate::PyTuple = $crate::PyObject::from_borrowed_ptr($py, args).unchecked_cast_into();
|
||||
let kwargs: Option<$crate::PyDict> = $crate::_detail::get_kwargs($py, kwargs);
|
||||
let ret = {
|
||||
let $args = &args;
|
||||
let $kwargs = kwargs.as_ref();
|
||||
$crate::_detail::result_to_ptr($py, $body)
|
||||
};
|
||||
$crate::PyDrop::release_ref(args, $py);
|
||||
$crate::PyDrop::release_ref(kwargs, $py);
|
||||
ret
|
||||
}
|
||||
wrap::<()>
|
||||
}};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn get_kwargs(ptr: &*mut ffi::PyObject) -> Option<&PyDict> {
|
||||
pub unsafe fn get_kwargs(py: Python, ptr: *mut ffi::PyObject) -> Option<PyDict> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObject::borrow_from_ptr(ptr).unchecked_cast_as())
|
||||
Some(PyObject::from_borrowed_ptr(py, ptr).unchecked_cast_into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#![feature(unsafe_no_drop_flag)] // crucial so that PyObject<'p> is binary compatible with *mut ffi::PyObject
|
||||
#![feature(filling_drop)] // necessary to avoid segfault with unsafe_no_drop_flag (#5016)
|
||||
#![cfg_attr(feature="nightly", feature(
|
||||
unsafe_no_drop_flag, filling_drop, // (#5016)
|
||||
// ^ These two are crucial so that PyObject<'p> is binary compatible with
|
||||
// `*mut ffi::PyObject`, which we use for efficient slice access and in
|
||||
// some other cases.
|
||||
|
||||
const_fn, // for GILProtected::new (#24111)
|
||||
shared, // for std::ptr::Shared (#27730)
|
||||
))]
|
||||
|
|
|
@ -42,8 +42,8 @@ use err::PyResult;
|
|||
/// on `PyObject` to convert to more specific object types.
|
||||
///
|
||||
/// Most of the interesting methods are provided by the [ObjectProtocol trait](trait.ObjectProtocol.html).
|
||||
#[unsafe_no_drop_flag]
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature="nightly", unsafe_no_drop_flag)]
|
||||
#[cfg_attr(feature="nightly", repr(C))]
|
||||
pub struct PyObject {
|
||||
// PyObject owns one reference to the *PyObject
|
||||
// ptr is not null
|
||||
|
@ -60,6 +60,7 @@ unsafe impl Sync for PyObject {}
|
|||
/// Dropping a `PyObject` decrements the reference count on the object by 1.
|
||||
impl Drop for PyObject {
|
||||
#[inline]
|
||||
#[cfg(feature="nightly")]
|
||||
fn drop(&mut self) {
|
||||
// TODO: remove `if` when #[unsafe_no_drop_flag] disappears
|
||||
if unpack_shared(self.ptr) as usize != mem::POST_DROP_USIZE {
|
||||
|
@ -67,6 +68,14 @@ impl Drop for PyObject {
|
|||
unsafe { ffi::Py_DECREF(unpack_shared(self.ptr)); }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(feature="nightly"))]
|
||||
fn drop(&mut self) {
|
||||
let _gil_guard = Python::acquire_gil();
|
||||
unsafe { ffi::Py_DECREF(unpack_shared(self.ptr)); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -198,6 +207,7 @@ impl PyObject {
|
|||
/// Transmutes an FFI pointer to `&PyObject`.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
#[cfg(feature="nightly")] // needs unsafe_no_drop_flag
|
||||
pub unsafe fn borrow_from_ptr<'a>(ptr : &'a *mut ffi::PyObject) -> &'a PyObject {
|
||||
debug_assert!(!ptr.is_null());
|
||||
mem::transmute(ptr)
|
||||
|
@ -206,6 +216,7 @@ impl PyObject {
|
|||
/// Transmutes a slice of owned FFI pointers to `&[PyObject]`.
|
||||
/// Undefined behavior if any pointer in the slice is NULL or invalid.
|
||||
#[inline]
|
||||
#[cfg(feature="nightly")] // needs unsafe_no_drop_flag
|
||||
pub unsafe fn borrow_from_owned_ptr_slice<'a>(ptr : &'a [*mut ffi::PyObject]) -> &'a [PyObject] {
|
||||
mem::transmute(ptr)
|
||||
}
|
||||
|
@ -217,12 +228,9 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Gets the Python type object for this object's type.
|
||||
#[inline]
|
||||
pub fn get_type(&self) -> &PyType {
|
||||
pub fn get_type(&self, py: Python) -> PyType {
|
||||
unsafe {
|
||||
let t : &*mut ffi::PyTypeObject = &(*self.as_ptr()).ob_type;
|
||||
let t : &*mut ffi::PyObject = mem::transmute(t);
|
||||
PyObject::borrow_from_ptr(t).unchecked_cast_as()
|
||||
PyType::from_type_ptr(py, (*self.as_ptr()).ob_type)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,6 +299,7 @@ impl PartialEq for PyObject {
|
|||
impl Eq for PyObject { }
|
||||
|
||||
#[test]
|
||||
#[cfg(feature="nightly")] // needs unsafe_no_drop_flag
|
||||
fn test_sizeof() {
|
||||
// should be a static_assert, but size_of is not a compile-time const
|
||||
// these are necessary for the transmutes in this module
|
||||
|
|
|
@ -72,6 +72,7 @@ impl PyTuple {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature="nightly")] // needs unsafe_no_drop_flag
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [PyObject] {
|
||||
// This is safe because PyObject has the same memory layout as *mut ffi::PyObject,
|
||||
// and because tuples are immutable.
|
||||
|
@ -97,6 +98,7 @@ impl PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="nightly")] // needs unsafe_no_drop_flag
|
||||
impl ::std::ops::Index<usize> for PyTuple {
|
||||
type Output = PyObject;
|
||||
|
||||
|
@ -106,6 +108,7 @@ impl ::std::ops::Index<usize> for PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="nightly")] // needs unsafe_no_drop_flag
|
||||
impl <'a> IntoIterator for &'a PyTuple {
|
||||
type Item = &'a PyObject;
|
||||
type IntoIter = slice::Iter<'a, PyObject>;
|
||||
|
|
|
@ -38,10 +38,19 @@ macro_rules! py_method_wrap {
|
|||
let _guard = $crate::_detail::PanicGuard::with_message(
|
||||
concat!("Rust panic in py_method!(", stringify!($f), ")"));
|
||||
let $py: $crate::Python = $crate::_detail::bounded_assume_gil_acquired(&args);
|
||||
let $slf: &$crate::PyObject = $crate::PyObject::borrow_from_ptr(&slf);
|
||||
let $args: &$crate::PyTuple = $crate::PyObject::borrow_from_ptr(&args).unchecked_cast_as();
|
||||
let $kwargs: Option<&$crate::PyDict> = $crate::_detail::get_kwargs(&kwargs);
|
||||
let slf: $crate::PyObject = $crate::PyObject::from_borrowed_ptr($py, slf);
|
||||
let args: $crate::PyTuple = $crate::PyObject::from_borrowed_ptr($py, args).unchecked_cast_into();
|
||||
let kwargs: Option<$crate::PyDict> = $crate::_detail::get_kwargs($py, kwargs);
|
||||
let ret = {
|
||||
let $slf = &slf;
|
||||
let $args = &args;
|
||||
let $kwargs = kwargs.as_ref();
|
||||
$crate::_detail::result_to_ptr($py, $body)
|
||||
};
|
||||
$crate::PyDrop::release_ref(slf, $py);
|
||||
$crate::PyDrop::release_ref(args, $py);
|
||||
$crate::PyDrop::release_ref(kwargs, $py);
|
||||
ret
|
||||
}
|
||||
wrap::<()>
|
||||
}};
|
||||
|
@ -211,10 +220,19 @@ macro_rules! py_class_method_wrap {
|
|||
let _guard = $crate::_detail::PanicGuard::with_message(
|
||||
concat!("Rust panic in py_class_method!(", stringify!($f), ")"));
|
||||
let $py: $crate::Python = $crate::_detail::bounded_assume_gil_acquired(&args);
|
||||
let $slf: &$crate::PyType = $crate::PyObject::borrow_from_ptr(&slf).unchecked_cast_as();
|
||||
let $args: &$crate::PyTuple = $crate::PyObject::borrow_from_ptr(&args).unchecked_cast_as();
|
||||
let $kwargs: Option<&$crate::PyDict> = $crate::_detail::get_kwargs(&kwargs);
|
||||
let slf: $crate::PyType = $crate::PyObject::from_borrowed_ptr($py, slf).unchecked_cast_into();
|
||||
let args: $crate::PyTuple = $crate::PyObject::from_borrowed_ptr($py, args).unchecked_cast_into();
|
||||
let kwargs: Option<$crate::PyDict> = $crate::_detail::get_kwargs($py, kwargs);
|
||||
let ret = {
|
||||
let $slf = &slf;
|
||||
let $args = &args;
|
||||
let $kwargs = kwargs.as_ref();
|
||||
$crate::_detail::result_to_ptr($py, $body)
|
||||
};
|
||||
$crate::PyDrop::release_ref(slf, $py);
|
||||
$crate::PyDrop::release_ref(args, $py);
|
||||
$crate::PyDrop::release_ref(kwargs, $py);
|
||||
ret
|
||||
}
|
||||
wrap::<()>
|
||||
}};
|
||||
|
|
|
@ -140,8 +140,15 @@ impl <T, B> PythonBaseObject for PyRustObject<T, B> where T: 'static + Send, B:
|
|||
}
|
||||
|
||||
unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
|
||||
// drop_in_place() isn't available in 1.7 stable;
|
||||
// it'll be stabilized in 1.8
|
||||
#[cfg(not(feature="nightly"))]
|
||||
use std::ptr::read as drop_ptr_target;
|
||||
#[cfg(feature="nightly")]
|
||||
use std::ptr::drop_in_place as drop_ptr_target;
|
||||
|
||||
let offset = PyRustObject::<T, B>::offset() as isize;
|
||||
ptr::read_and_drop((obj as *mut u8).offset(offset) as *mut T);
|
||||
drop_ptr_target((obj as *mut u8).offset(offset) as *mut T);
|
||||
B::dealloc(py, obj)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue