diff --git a/src/callback.rs b/src/callback.rs index ab8e17ee..edeca66c 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -11,6 +11,8 @@ use std::os::raw::c_int; use std::{isize, ptr}; /// Convert the result of callback function into the appropriate return value. +/// +/// Used by PyO3 macros. pub trait CallbackConverter { type Source; type Result: Copy; diff --git a/src/class/iter.rs b/src/class/iter.rs index c6d69361..8d7522e3 100644 --- a/src/class/iter.rs +++ b/src/class/iter.rs @@ -9,8 +9,8 @@ use std::ptr; /// Python Iterator Interface. /// -/// more information -/// `https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter` +/// Check [CPython doc](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter) +/// for more. #[allow(unused_variables)] pub trait PyIterProtocol<'p>: PyClass { fn __iter__(slf: PyRefMut) -> Self::Result diff --git a/src/class/macros.rs b/src/class/macros.rs index 124860d0..7cb9ae7e 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -127,8 +127,7 @@ macro_rules! py_binary_num_func { }}; } -// NOTE(kngwyu): -// Now(2020 2/9) This macro is used only for inplace operation so I used call_mut here. +// NOTE(kngwyu): This macro is used only for inplace operations, so I used call_mut here. #[macro_export] #[doc(hidden)] macro_rules! py_binary_self_func { @@ -399,6 +398,7 @@ macro_rules! _call_impl { }; } +/// Call `slf.try_borrow()?.$fn(...)` macro_rules! call_ref { ($slf: expr, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { match $slf.try_borrow() { @@ -408,6 +408,7 @@ macro_rules! call_ref { }; } +/// Call `slf.try_borrow()?.$fn(...)` and returns the result using the given CallbackConverter macro_rules! call_ref_with_converter { ($slf: expr, $conv: expr, $py: ident, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { match $slf.try_borrow() { @@ -417,6 +418,7 @@ macro_rules! call_ref_with_converter { }; } +/// Call `slf.try_borrow_mut()?.$fn(...)` macro_rules! call_mut { ($slf: expr, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { match $slf.try_borrow_mut() { @@ -426,6 +428,7 @@ macro_rules! call_mut { }; } +/// Call `slf.try_borrow_mut()?.$fn(...)` and returns the result using the given CallbackConverter macro_rules! call_mut_with_converter { ($slf: expr, $conv: expr, $py: ident, $fn: ident $(,$raw_args: expr)* $(; $args: expr)*) => { match $slf.try_borrow_mut() { diff --git a/src/pycell.rs b/src/pycell.rs index 0e7761c5..8dba97d7 100644 --- a/src/pycell.rs +++ b/src/pycell.rs @@ -10,6 +10,8 @@ use std::fmt; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; +/// Base layout of PyCell. +/// This is necessary for sharing BorrowFlag between parents and children. #[doc(hidden)] #[repr(C)] pub struct PyCellBase { @@ -46,7 +48,7 @@ where /// Inner type of `PyCell` without dict slots and reference counter. /// This struct has two usages: /// 1. As an inner type of `PyRef` and `PyRefMut`. -/// 2. As a base class when `#[pyclass(Base)]` is specified. +/// 2. When `#[pyclass(extends=Base)]` is specified, `PyCellInner` is used as a base layout. #[doc(hidden)] #[repr(C)] pub struct PyCellInner { @@ -77,7 +79,7 @@ unsafe impl PyLayout for PyCellInner { } } -// Thes impls ensures `PyCellInner` can be a base type. +// These impls ensures `PyCellInner` can be a base type. impl PySizedLayout for PyCellInner {} unsafe impl PyBorrowFlagLayout for PyCellInner {} @@ -328,8 +330,7 @@ impl PyCell { } /// Allocates new PyCell without initilizing value. - /// Requires `T::BaseLayout: PyBorrowFlagLayout` to ensure that - /// this layout has a borrow flag. + /// Requires `T::BaseLayout: PyBorrowFlagLayout` to ensure `self` has a borrow flag. pub(crate) unsafe fn internal_new(py: Python) -> PyResult<*mut Self> where T::BaseLayout: PyBorrowFlagLayout, diff --git a/src/pyclass.rs b/src/pyclass.rs index fa06336c..a3e0f375 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -73,9 +73,12 @@ pub unsafe fn tp_free_fallback(obj: *mut ffi::PyObject) { pub trait PyClass: PyTypeInfo> + Sized + PyClassAlloc + PyMethodsProtocol { + /// Specify this class has `#[pyclass(dict)]` or not. type Dict: PyClassDict; + /// Specify this class has `#[pyclass(weakref)]` or not. type WeakRef: PyClassWeakRef; - /// The closest native ancestor. + /// The closest native ancestor. This is `PyAny` by default, and when you declare + /// `#[pyclass(extends=PyList)]`, it's `PyList`. type BaseNativeType: PyTypeInfo + PyNativeType; } diff --git a/src/type_object.rs b/src/type_object.rs index 9aac8ed3..799cd723 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -29,8 +29,20 @@ pub unsafe trait PyLayout { /// , in addition that `T` is a concrete representaion of `U`. pub trait PySizedLayout: PyLayout + Sized {} -/// Marker type indicates that `Self` can be a baselayout of PyClass. -/// This trait assumes a certain layout and thus is unsafe. +/// Marker type indicates that `Self` can be a base layout of `PyClass`. +/// +/// # Safety +/// +/// Self should be layouted as follows: +/// ```ignore +/// #[repr(C)] +/// struct Self { +/// obj: ffi::PyObject, +/// borrow_flag: u64, +/// ... +/// } +/// ``` +/// Otherwise, implementing this trait is undefined behavior. pub unsafe trait PyBorrowFlagLayout: PyLayout + Sized {} /// Our custom type flags @@ -53,13 +65,17 @@ pub mod type_flags { } /// Reference abstraction for `PyClass` and `PyNativeType`. Used internaly. -// DEVELOPPER NOTE(kngwyu): -// `&PyCell` is a pointer but `&PyAny` is a pointer of a pointer, so we need -// two different abstraction for them. -// This mismatch eventually should be fixed with https://github.com/PyO3/pyo3/issues/679, -// but now it's not the time. +// NOTE(kngwyu): +// `&PyCell` is a pointer of `ffi::PyObject` but `&PyAny` is a pointer of a pointer, +// so we need abstraction. +// This mismatch eventually should be fixed(e.g., https://github.com/PyO3/pyo3/issues/679). pub unsafe trait PyDowncastImpl { /// Cast `&PyAny` to `&Self` without no type checking. + /// + /// # Safety + /// + /// Unless obj is not an instance of a type corresponding to Self, + /// this method causes undefined behavior. unsafe fn unchecked_downcast(obj: &PyAny) -> &Self; private_decl! {} }