@@ -292,7 +292,11 @@ impl<T: Clone> Dict<T> {
292292 // The dict was changed since we did lookup. Let's try again.
293293 }
294294 } else {
295- // New key:
295+ // New key - validate slot is still what lookup found
296+ if inner. indices . get ( index_index) != Some ( & entry_index) {
297+ // Dict was resized since lookup, retry
298+ continue ;
299+ }
296300 inner. unchecked_push ( index_index, hash, key. to_pyobject ( vm) , value, entry_index) ;
297301 break None ;
298302 }
@@ -431,6 +435,9 @@ impl<T: Clone> Dict<T> {
431435 }
432436 } else {
433437 let mut inner = self . write ( ) ;
438+ if inner. indices . get ( index_index) != Some ( & entry) {
439+ continue ;
440+ }
434441 inner. unchecked_push ( index_index, hash, key. to_owned ( ) , value, entry) ;
435442 break None ;
436443 }
@@ -444,31 +451,32 @@ impl<T: Clone> Dict<T> {
444451 F : FnOnce ( ) -> T ,
445452 {
446453 let hash = key. key_hash ( vm) ?;
447- let res = loop {
448- let lookup = self . lookup ( vm , key , hash , None ) ? ;
449- let ( index_entry, index_index) = lookup;
454+ let mut default = Some ( default ) ;
455+ loop {
456+ let ( index_entry, index_index) = self . lookup ( vm , key , hash , None ) ? ;
450457 if let Some ( index) = index_entry. index ( ) {
451458 let inner = self . read ( ) ;
452459 if let Some ( entry) = inner. get_entry_checked ( index, index_index) {
453- break entry. value . clone ( ) ;
454- } else {
455- // The dict was changed since we did lookup, let's try again.
456- continue ;
460+ return Ok ( entry. value . clone ( ) ) ;
457461 }
458- } else {
459- let value = default ( ) ;
460- let mut inner = self . write ( ) ;
461- inner. unchecked_push (
462- index_index,
463- hash,
464- key. to_pyobject ( vm) ,
465- value. clone ( ) ,
466- index_entry,
467- ) ;
468- break value;
462+ continue ;
469463 }
470- } ;
471- Ok ( res)
464+ let mut inner = self . write ( ) ;
465+ if inner. indices . get ( index_index) != Some ( & index_entry) {
466+ continue ;
467+ }
468+ let value = default
469+ . take ( )
470+ . expect ( "default must only be computed on insertion" ) ( ) ;
471+ inner. unchecked_push (
472+ index_index,
473+ hash,
474+ key. to_pyobject ( vm) ,
475+ value. clone ( ) ,
476+ index_entry,
477+ ) ;
478+ return Ok ( value) ;
479+ }
472480 }
473481
474482 #[ allow( dead_code) ]
@@ -483,27 +491,28 @@ impl<T: Clone> Dict<T> {
483491 F : FnOnce ( ) -> T ,
484492 {
485493 let hash = key. key_hash ( vm) ?;
486- let res = loop {
487- let lookup = self . lookup ( vm , key , hash , None ) ? ;
488- let ( index_entry, index_index) = lookup;
494+ let mut default = Some ( default ) ;
495+ loop {
496+ let ( index_entry, index_index) = self . lookup ( vm , key , hash , None ) ? ;
489497 if let Some ( index) = index_entry. index ( ) {
490498 let inner = self . read ( ) ;
491499 if let Some ( entry) = inner. get_entry_checked ( index, index_index) {
492- break ( entry. key . clone ( ) , entry. value . clone ( ) ) ;
493- } else {
494- // The dict was changed since we did lookup, let's try again.
495- continue ;
500+ return Ok ( ( entry. key . clone ( ) , entry. value . clone ( ) ) ) ;
496501 }
497- } else {
498- let value = default ( ) ;
499- let key = key. to_pyobject ( vm) ;
500- let mut inner = self . write ( ) ;
501- let ret = ( key. clone ( ) , value. clone ( ) ) ;
502- inner. unchecked_push ( index_index, hash, key, value, index_entry) ;
503- break ret;
502+ continue ;
504503 }
505- } ;
506- Ok ( res)
504+ let mut inner = self . write ( ) ;
505+ if inner. indices . get ( index_index) != Some ( & index_entry) {
506+ continue ;
507+ }
508+ let value = default
509+ . take ( )
510+ . expect ( "default must only be computed on insertion" ) ( ) ;
511+ let key_obj = key. to_pyobject ( vm) ;
512+ let ret = ( key_obj. clone ( ) , value. clone ( ) ) ;
513+ inner. unchecked_push ( index_index, hash, key_obj, value, index_entry) ;
514+ return Ok ( ret) ;
515+ }
507516 }
508517
509518 pub fn len ( & self ) -> usize {
0 commit comments