Skip to content

Commit 89913e8

Browse files
committed
use Borrowed::from_ptr methods in extract_argument
1 parent 22f960f commit 89913e8

File tree

3 files changed

+29
-18
lines changed

3 files changed

+29
-18
lines changed

src/impl_/extract_argument.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ where
4848
obj: &'a Bound<'py, PyAny>,
4949
holder: &'a mut Option<&'a Bound<'py, T>>,
5050
) -> PyResult<Self> {
51-
Ok(&*holder.insert(obj.downcast()?))
51+
Ok(holder.insert(obj.downcast()?))
5252
}
5353
}
5454

@@ -261,7 +261,9 @@ impl FunctionDescription {
261261
);
262262

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

286288
// Safety: kwnames is known to be a pointer to a tuple, or null
287-
let kwnames: &'py Option<Bound<'py, PyTuple>> = std::mem::transmute(&kwnames);
288-
if let Some(kwnames) = kwnames.as_ref() {
289-
// Safety: &PyAny has the same memory layout as `*mut ffi::PyObject`
289+
// - we both have the GIL and can borrow this input reference for the `'py` lifetime.
290+
let kwnames: Option<Borrowed<'_, '_, PyTuple>> =
291+
Borrowed::from_ptr_or_opt(py, kwnames).map(|kwnames| kwnames.downcast_unchecked());
292+
if let Some(kwnames) = kwnames {
293+
// Safety: PyArg has the same memory layout as `*mut ffi::PyObject`
290294
let kwargs = ::std::slice::from_raw_parts(
291295
(args as *const PyArg<'py>).offset(nargs),
292296
kwnames.len(),
@@ -322,7 +326,7 @@ impl FunctionDescription {
322326
/// - `kwargs` must be a pointer to a PyDict, or NULL.
323327
pub unsafe fn extract_arguments_tuple_dict<'py, V, K>(
324328
&self,
325-
_py: Python<'py>,
329+
py: Python<'py>,
326330
args: *mut ffi::PyObject,
327331
kwargs: *mut ffi::PyObject,
328332
output: &mut [Option<PyArg<'py>>],
@@ -331,11 +335,14 @@ impl FunctionDescription {
331335
V: VarargsHandler<'py>,
332336
K: VarkeywordsHandler<'py>,
333337
{
334-
// Safety: Bound has the same layout as a raw pointer, and reference is known to be
335-
// borrowed for 'py.
336-
let args: &'py Bound<'py, PyTuple> = std::mem::transmute(&args);
337-
let kwargs: &'py Option<Bound<'py, PyDict>> = std::mem::transmute(&kwargs);
338-
let kwargs = kwargs.as_ref();
338+
// Safety:
339+
// - `args` is known to be a tuple
340+
// - `kwargs` is known to be a dict or null
341+
// - we both have the GIL and can borrow these input references for the `'py` lifetime.
342+
let args: Borrowed<'py, 'py, PyTuple> =
343+
Borrowed::from_ptr(py, args).downcast_unchecked::<PyTuple>();
344+
let kwargs: Option<Borrowed<'py, 'py, PyDict>> =
345+
Borrowed::from_ptr_or_opt(py, kwargs).map(|kwargs| kwargs.downcast_unchecked());
339346

340347
let num_positional_parameters = self.positional_parameter_names.len();
341348

@@ -356,7 +363,7 @@ impl FunctionDescription {
356363
}
357364

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

361368
// Handle keyword arguments
362369
let mut varkeywords = K::Varkeywords::default();

src/types/dict.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,12 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {
517517
}
518518
}
519519

520-
impl<'py> Bound<'py, PyDict> {
520+
impl<'a, 'py> Borrowed<'a, 'py, PyDict> {
521521
/// Iterates over the contents of this dictionary without incrementing reference counts.
522522
///
523523
/// # Safety
524524
/// It must be known that this dictionary will not be modified during iteration.
525-
pub(crate) unsafe fn iter_borrowed<'a>(&'a self) -> BorrowedDictIter<'a, 'py> {
525+
pub(crate) unsafe fn iter_borrowed(self) -> BorrowedDictIter<'a, 'py> {
526526
BorrowedDictIter::new(self)
527527
}
528528
}
@@ -672,7 +672,7 @@ mod borrowed_iter {
672672
/// without incrementing reference counts. This is only safe if it's known
673673
/// that the dictionary will not be modified during iteration.
674674
pub struct BorrowedDictIter<'a, 'py> {
675-
dict: &'a Bound<'py, PyDict>,
675+
dict: Borrowed<'a, 'py, PyDict>,
676676
ppos: ffi::Py_ssize_t,
677677
len: ffi::Py_ssize_t,
678678
}
@@ -710,8 +710,8 @@ mod borrowed_iter {
710710
}
711711

712712
impl<'a, 'py> BorrowedDictIter<'a, 'py> {
713-
pub(super) fn new(dict: &'a Bound<'py, PyDict>) -> Self {
714-
let len = dict_len(dict);
713+
pub(super) fn new(dict: Borrowed<'a, 'py, PyDict>) -> Self {
714+
let len = dict_len(&dict);
715715
BorrowedDictIter { dict, ppos: 0, len }
716716
}
717717
}

src/types/tuple.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
412412
}
413413

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

418418
fn to_list(&self) -> Bound<'py, PyList> {
@@ -434,6 +434,10 @@ impl<'a, 'py> Borrowed<'a, 'py, PyTuple> {
434434
unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> {
435435
ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t).assume_borrowed(self.py())
436436
}
437+
438+
pub(crate) fn iter_borrowed(self) -> BorrowedTupleIterator<'a, 'py> {
439+
BorrowedTupleIterator::new(self)
440+
}
437441
}
438442

439443
/// Used by `PyTuple::iter()`.

0 commit comments

Comments
 (0)