Skip to content

Commit

Permalink
use Borrowed::from_ptr methods in extract_argument
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Feb 20, 2024
1 parent 22f960f commit 31616ed
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 18 deletions.
32 changes: 20 additions & 12 deletions src/impl_/extract_argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ where
obj: &'a Bound<'py, PyAny>,
holder: &'a mut Option<&'a Bound<'py, T>>,
) -> PyResult<Self> {
Ok(&*holder.insert(obj.downcast()?))
Ok(holder.insert(obj.downcast()?))
}
}

Expand Down Expand Up @@ -261,7 +261,9 @@ impl FunctionDescription {
);

// Handle positional arguments
// Safety: Option<PyArg> has the same memory layout as `*mut ffi::PyObject`
// Safety:
// - Option<PyArg> has the same memory layout as `*mut ffi::PyObject`
// - we both have the GIL and can borrow these input references for the `'py` lifetime.
let args: *const Option<PyArg<'py>> = args.cast();
let positional_args_provided = nargs as usize;
let remaining_positional_args = if args.is_null() {
Expand All @@ -284,9 +286,12 @@ impl FunctionDescription {
let mut varkeywords = K::Varkeywords::default();

// Safety: kwnames is known to be a pointer to a tuple, or null
let kwnames: &'py Option<Bound<'py, PyTuple>> = std::mem::transmute(&kwnames);
if let Some(kwnames) = kwnames.as_ref() {
// Safety: &PyAny has the same memory layout as `*mut ffi::PyObject`
// - we both have the GIL and can borrow this input reference for the `'py` lifetime.
let kwnames = Borrowed::from_ptr_or_opt(py, kwnames);
if let Some(kwnames) = kwnames {
// Safety: kwnames is known to be a PyTuple from the Python interpreter
let kwnames = kwnames.downcast_unchecked::<PyTuple>();
// Safety: PyArg has the same memory layout as `*mut ffi::PyObject`
let kwargs = ::std::slice::from_raw_parts(
(args as *const PyArg<'py>).offset(nargs),
kwnames.len(),
Expand Down Expand Up @@ -322,7 +327,7 @@ impl FunctionDescription {
/// - `kwargs` must be a pointer to a PyDict, or NULL.
pub unsafe fn extract_arguments_tuple_dict<'py, V, K>(
&self,
_py: Python<'py>,
py: Python<'py>,
args: *mut ffi::PyObject,
kwargs: *mut ffi::PyObject,
output: &mut [Option<PyArg<'py>>],
Expand All @@ -331,11 +336,14 @@ impl FunctionDescription {
V: VarargsHandler<'py>,
K: VarkeywordsHandler<'py>,
{
// Safety: Bound has the same layout as a raw pointer, and reference is known to be
// borrowed for 'py.
let args: &'py Bound<'py, PyTuple> = std::mem::transmute(&args);
let kwargs: &'py Option<Bound<'py, PyDict>> = std::mem::transmute(&kwargs);
let kwargs = kwargs.as_ref();
// Safety:
// - `args` is known to be a tuple
// - `kwargs` is known to be a dict or null
// - we both have the GIL and can borrow these input references for the `'py` lifetime.
let args: Borrowed<'py, 'py, PyTuple> =
Borrowed::from_ptr(py, args).downcast_unchecked::<PyTuple>();
let kwargs: Option<Borrowed<'py, 'py, PyDict>> =
Borrowed::from_ptr_or_opt(py, kwargs).map(|kwargs| kwargs.downcast_unchecked());

let num_positional_parameters = self.positional_parameter_names.len();

Expand All @@ -356,7 +364,7 @@ impl FunctionDescription {
}

// If any arguments remain, push them to varargs (if possible) or error
let varargs = V::handle_varargs_tuple(args, self)?;
let varargs = V::handle_varargs_tuple(&args, self)?;

// Handle keyword arguments
let mut varkeywords = K::Varkeywords::default();
Expand Down
10 changes: 5 additions & 5 deletions src/types/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,12 +517,12 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {
}
}

impl<'py> Bound<'py, PyDict> {
impl<'a, 'py> Borrowed<'a, 'py, PyDict> {
/// Iterates over the contents of this dictionary without incrementing reference counts.
///
/// # Safety
/// It must be known that this dictionary will not be modified during iteration.
pub(crate) unsafe fn iter_borrowed<'a>(&'a self) -> BorrowedDictIter<'a, 'py> {
pub(crate) unsafe fn iter_borrowed(self) -> BorrowedDictIter<'a, 'py> {
BorrowedDictIter::new(self)
}
}
Expand Down Expand Up @@ -672,7 +672,7 @@ mod borrowed_iter {
/// without incrementing reference counts. This is only safe if it's known
/// that the dictionary will not be modified during iteration.
pub struct BorrowedDictIter<'a, 'py> {
dict: &'a Bound<'py, PyDict>,
dict: Borrowed<'a, 'py, PyDict>,
ppos: ffi::Py_ssize_t,
len: ffi::Py_ssize_t,
}
Expand Down Expand Up @@ -710,8 +710,8 @@ mod borrowed_iter {
}

impl<'a, 'py> BorrowedDictIter<'a, 'py> {
pub(super) fn new(dict: &'a Bound<'py, PyDict>) -> Self {
let len = dict_len(dict);
pub(super) fn new(dict: Borrowed<'a, 'py, PyDict>) -> Self {
let len = dict_len(&dict);
BorrowedDictIter { dict, ppos: 0, len }
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/types/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
}

fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> {
BorrowedTupleIterator::new(self.as_borrowed())
self.as_borrowed().iter_borrowed()
}

fn to_list(&self) -> Bound<'py, PyList> {
Expand All @@ -434,6 +434,10 @@ impl<'a, 'py> Borrowed<'a, 'py, PyTuple> {
unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> {
ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t).assume_borrowed(self.py())
}

pub(crate) fn iter_borrowed(self) -> BorrowedTupleIterator<'a, 'py> {
BorrowedTupleIterator::new(self)
}
}

/// Used by `PyTuple::iter()`.
Expand Down

0 comments on commit 31616ed

Please sign in to comment.