@@ -260,6 +260,10 @@ impl PyDictRef {
260
260
let key = key. into_pyobject ( vm) . unwrap ( ) ;
261
261
self . entries . borrow ( ) . contains ( vm, & key) . unwrap ( )
262
262
}
263
+
264
+ pub fn size ( & self ) -> dictdatatype:: DictSize {
265
+ self . entries . borrow ( ) . size ( )
266
+ }
263
267
}
264
268
265
269
impl ItemProtocol for PyDictRef {
@@ -315,11 +319,8 @@ impl Iterator for DictIter {
315
319
type Item = ( PyObjectRef , PyObjectRef ) ;
316
320
317
321
fn next ( & mut self ) -> Option < Self :: Item > {
318
- match self . dict . entries . borrow ( ) . next_entry ( self . position ) {
319
- Some ( ( new_position, key, value) ) => {
320
- self . position = new_position;
321
- Some ( ( key. clone ( ) , value. clone ( ) ) )
322
- }
322
+ match self . dict . entries . borrow ( ) . next_entry ( & mut self . position ) {
323
+ Some ( ( key, value) ) => Some ( ( key. clone ( ) , value. clone ( ) ) ) ,
323
324
None => None ,
324
325
}
325
326
}
@@ -360,6 +361,7 @@ macro_rules! dict_iterator {
360
361
#[ derive( Debug ) ]
361
362
struct $iter_name {
362
363
pub dict: PyDictRef ,
364
+ pub size: dictdatatype:: DictSize ,
363
365
pub position: Cell <usize >,
364
366
}
365
367
@@ -368,15 +370,24 @@ macro_rules! dict_iterator {
368
370
fn new( dict: PyDictRef ) -> Self {
369
371
$iter_name {
370
372
position: Cell :: new( 0 ) ,
373
+ size: dict. size( ) ,
371
374
dict,
372
375
}
373
376
}
374
377
375
378
#[ pymethod( name = "__next__" ) ]
376
379
fn next( & self , vm: & VirtualMachine ) -> PyResult {
377
- match self . dict. entries. borrow( ) . next_entry( self . position. get( ) ) {
378
- Some ( ( new_position, key, value) ) => {
379
- self . position. set( new_position) ;
380
+ let mut position = self . position. get( ) ;
381
+ let dict = self . dict. entries. borrow( ) ;
382
+ if dict. has_changed_size( & self . size) {
383
+ return Err ( vm. new_exception(
384
+ vm. ctx. exceptions. runtime_error. clone( ) ,
385
+ "dictionary changed size during iteration" . to_string( ) ,
386
+ ) ) ;
387
+ }
388
+ match dict. next_entry( & mut position) {
389
+ Some ( ( key, value) ) => {
390
+ self . position. set( position) ;
380
391
Ok ( $result_fn( vm, key, value) )
381
392
}
382
393
None => Err ( objiter:: new_stop_iteration( vm) ) ,
0 commit comments