@@ -19,6 +19,7 @@ mod _collections {
1919 use crossbeam_utils:: atomic:: AtomicCell ;
2020 use itertools:: Itertools ;
2121 use num_traits:: ToPrimitive ;
22+ use std:: cmp:: { max, min} ;
2223 use std:: collections:: VecDeque ;
2324
2425 #[ pyattr]
@@ -240,26 +241,44 @@ mod _collections {
240241 Ok ( ( ) )
241242 }
242243
244+ fn adjust_negative_index ( & self , index : isize ) -> usize {
245+ if index. is_negative ( ) {
246+ max ( index + self . borrow_deque ( ) . len ( ) as isize , 0 ) as usize
247+ } else {
248+ index as usize
249+ }
250+ }
251+
243252 #[ pymethod]
244253 fn index (
245254 & self ,
246255 obj : PyObjectRef ,
247- start : OptionalArg < usize > ,
248- stop : OptionalArg < usize > ,
256+ start : OptionalArg < isize > ,
257+ stop : OptionalArg < isize > ,
249258 vm : & VirtualMachine ,
250259 ) -> PyResult < usize > {
251260 let deque = self . borrow_deque ( ) . clone ( ) ;
252- let start = start. unwrap_or ( 0 ) ;
253261 let start_state = self . state . load ( ) ;
254- let stop = stop. unwrap_or_else ( || deque. len ( ) ) ;
255- for ( i, elem) in deque. iter ( ) . skip ( start) . take ( stop - start) . enumerate ( ) {
262+
263+ let start = self . adjust_negative_index ( start. unwrap_or ( 0 ) ) ;
264+ let stop = min (
265+ self . adjust_negative_index ( stop. unwrap_or_else ( || deque. len ( ) as isize ) ) ,
266+ deque. len ( ) ,
267+ ) ;
268+
269+ for ( i, elem) in deque
270+ . iter ( )
271+ . skip ( start)
272+ . take ( stop. saturating_sub ( start) )
273+ . enumerate ( )
274+ {
256275 let is_element = vm. identical_or_equal ( elem, & obj) ?;
257276
258277 if start_state != self . state . load ( ) {
259278 return Err ( vm. new_runtime_error ( "deque mutated during iteration" . to_owned ( ) ) ) ;
260279 }
261280 if is_element {
262- return Ok ( i) ;
281+ return Ok ( i + start ) ;
263282 }
264283 }
265284 Err ( vm. new_value_error (
0 commit comments