@@ -36,43 +36,6 @@ impl crate::impl_::pyclass::PyClassBaseType for PyList {
3636 crate :: impl_:: pycell:: PyVariableClassObject < T > ;
3737}
3838
39- #[ inline]
40- #[ track_caller]
41- fn try_new_from_iter < ' py > (
42- py : Python < ' py > ,
43- mut elements : impl ExactSizeIterator < Item = PyResult < Bound < ' py , PyAny > > > ,
44- ) -> PyResult < Bound < ' py , PyList > > {
45- unsafe {
46- // PyList_New checks for overflow but has a bad error message, so we check ourselves
47- let len: Py_ssize_t = elements
48- . len ( )
49- . try_into ( )
50- . expect ( "out of range integral type conversion attempted on `elements.len()`" ) ;
51-
52- let ptr = ffi:: PyList_New ( len) ;
53-
54- // We create the `Bound` pointer here for two reasons:
55- // - panics if the ptr is null
56- // - its Drop cleans up the list if user code or the asserts panic.
57- let list = ptr. assume_owned ( py) . cast_into_unchecked ( ) ;
58-
59- let count = ( & mut elements)
60- . take ( len as usize )
61- . try_fold ( 0 , |count, item| {
62- #[ cfg( not( Py_LIMITED_API ) ) ]
63- ffi:: PyList_SET_ITEM ( ptr, count, item?. into_ptr ( ) ) ;
64- #[ cfg( Py_LIMITED_API ) ]
65- ffi:: PyList_SetItem ( ptr, count, item?. into_ptr ( ) ) ;
66- Ok :: < _ , PyErr > ( count + 1 )
67- } ) ?;
68-
69- assert ! ( elements. next( ) . is_none( ) , "Attempted to create PyList but `elements` was larger than reported by its `ExactSizeIterator` implementation." ) ;
70- assert_eq ! ( len, count, "Attempted to create PyList but `elements` was smaller than reported by its `ExactSizeIterator` implementation." ) ;
71-
72- Ok ( list)
73- }
74- }
75-
7639impl PyList {
7740 /// Constructs a new list with the given elements.
7841 ///
@@ -101,16 +64,38 @@ impl PyList {
10164 /// All standard library structures implement this trait correctly, if they do, so calling this
10265 /// function with (for example) [`Vec`]`<T>` or `&[T]` will always succeed.
10366 #[ track_caller]
104- pub fn new < ' py , T , U > (
67+ pub fn new < ' py , T > (
10568 py : Python < ' py > ,
106- elements : impl IntoIterator < Item = T , IntoIter = U > ,
69+ elements : impl IntoIterator < Item = T > ,
10770 ) -> PyResult < Bound < ' py , PyList > >
10871 where
10972 T : IntoPyObject < ' py > ,
110- U : ExactSizeIterator < Item = T > ,
11173 {
112- let iter = elements. into_iter ( ) . map ( |e| e. into_bound_py_any ( py) ) ;
113- try_new_from_iter ( py, iter)
74+ let mut elements = elements. into_iter ( ) . map ( |e| e. into_bound_py_any ( py) ) ;
75+ let ( min_len, _) = elements. size_hint ( ) ;
76+
77+ // PyList_New checks for overflow but has a bad error message, so we check ourselves
78+ let len: Py_ssize_t = min_len
79+ . try_into ( )
80+ . expect ( "out of range integral type conversion attempted on `elements.len()`" ) ;
81+
82+ let list = unsafe { ffi:: PyList_New ( len) . assume_owned ( py) . cast_into_unchecked ( ) } ;
83+
84+ let count = ( & mut elements)
85+ . take ( len as usize )
86+ . try_fold ( 0 , |count, item| unsafe {
87+ #[ cfg( not( Py_LIMITED_API ) ) ]
88+ ffi:: PyList_SET_ITEM ( list. as_ptr ( ) , count, item?. into_ptr ( ) ) ;
89+ #[ cfg( Py_LIMITED_API ) ]
90+ ffi:: PyList_SetItem ( list. as_ptr ( ) , count, item?. into_ptr ( ) ) ;
91+ Ok :: < _ , PyErr > ( count + 1 )
92+ } ) ?;
93+
94+ assert_eq ! ( len, count, "Attempted to create PyList but `elements` was smaller than reported by its `size_hint` implementation." ) ;
95+
96+ elements. try_for_each ( |item| list. append ( item?) ) ?;
97+
98+ Ok ( list)
11499 }
115100
116101 /// Constructs a new empty list.
@@ -1516,6 +1501,10 @@ mod tests {
15161501 fn next ( & mut self ) -> Option < Self :: Item > {
15171502 self . 0 . next ( )
15181503 }
1504+
1505+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1506+ ( self . 1 , Some ( self . 1 ) )
1507+ }
15191508 }
15201509
15211510 impl ExactSizeIterator for FaultyIter {
@@ -1526,18 +1515,7 @@ mod tests {
15261515
15271516 #[ test]
15281517 #[ should_panic(
1529- expected = "Attempted to create PyList but `elements` was larger than reported by its `ExactSizeIterator` implementation."
1530- ) ]
1531- fn too_long_iterator ( ) {
1532- Python :: attach ( |py| {
1533- let iter = FaultyIter ( 0 ..usize:: MAX , 73 ) ;
1534- let _list = PyList :: new ( py, iter) . unwrap ( ) ;
1535- } )
1536- }
1537-
1538- #[ test]
1539- #[ should_panic(
1540- expected = "Attempted to create PyList but `elements` was smaller than reported by its `ExactSizeIterator` implementation."
1518+ expected = "Attempted to create PyList but `elements` was smaller than reported by its `size_hint` implementation."
15411519 ) ]
15421520 fn too_short_iterator ( ) {
15431521 Python :: attach ( |py| {
0 commit comments