Skip to content

Commit ff7c5e5

Browse files
Fail PyTuple::new on wrong sizehint when compiling for RustPython (#6154)
1 parent 681d738 commit ff7c5e5

1 file changed

Lines changed: 23 additions & 17 deletions

File tree

src/types/tuple.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ fn try_new_from_iter<'py>(
3535
py: Python<'py>,
3636
mut elements: impl ExactSizeIterator<Item = PyResult<Bound<'py, PyAny>>>,
3737
) -> PyResult<Bound<'py, PyTuple>> {
38-
#[cfg(not(RustPython))]
39-
unsafe {
40-
// PyTuple_New checks for overflow but has a bad error message, so we check ourselves
41-
let len: Py_ssize_t = elements
42-
.len()
43-
.try_into()
44-
.expect("out of range integral type conversion attempted on `elements.len()`");
38+
// PyTuple_New checks for overflow but has a bad error message, so we check ourselves
39+
let len: Py_ssize_t = elements
40+
.len()
41+
.try_into()
42+
.expect("out of range integral type conversion attempted on `elements.len()`");
4543

44+
#[cfg(not(RustPython))]
45+
let (tup, counter) = unsafe {
4646
let ptr = ffi::PyTuple_New(len);
4747

4848
// - Panics if the ptr is null
@@ -59,20 +59,26 @@ fn try_new_from_iter<'py>(
5959
counter += 1;
6060
}
6161

62-
assert!(elements.next().is_none(), "Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation.");
63-
assert_eq!(len, counter, "Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation.");
64-
65-
Ok(tup)
66-
}
62+
(tup, counter)
63+
};
6764

6865
#[cfg(RustPython)]
69-
unsafe {
70-
let elements = elements.collect::<PyResult<Vec<_>>>()?;
66+
let (tup, counter) = unsafe {
67+
let elements = (&mut elements)
68+
.take(len as _)
69+
.collect::<PyResult<Vec<_>>>()?;
7170
// SAFETY: list is layout compatible with *const *mut crate::PyObject
72-
ffi::PyTuple_FromArray(elements.as_ptr().cast(), elements.len() as _)
71+
let tup = ffi::PyTuple_FromArray(elements.as_ptr().cast(), elements.len() as _)
7372
.assume_owned_or_err(py)
74-
.cast_into_unchecked()
75-
}
73+
.cast_into_unchecked()?;
74+
75+
(tup, elements.len() as Py_ssize_t)
76+
};
77+
78+
assert!(elements.next().is_none(), "Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation.");
79+
assert_eq!(len, counter, "Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation.");
80+
81+
Ok(tup)
7682
}
7783

7884
/// Represents a Python `tuple` object.

0 commit comments

Comments
 (0)