@@ -1351,24 +1351,85 @@ fn test_try_reserve_exact() {
1351
1351
}
1352
1352
1353
1353
#[ test]
1354
- fn test_stable_push_pop ( ) {
1354
+ fn test_stable_pointers ( ) {
1355
+ /// Pull an element from the iterator, then drop it.
1356
+ /// Useful to cover both the `next` and `drop` paths of an iterator.
1357
+ fn next_then_drop < I : Iterator > ( mut i : I ) {
1358
+ i. next ( ) . unwrap ( ) ;
1359
+ drop ( i) ;
1360
+ }
1361
+
1355
1362
// Test that, if we reserved enough space, adding and removing elements does not
1356
1363
// invalidate references into the vector (such as `v0`). This test also
1357
1364
// runs in Miri, which would detect such problems.
1358
- let mut v = Vec :: with_capacity ( 10 ) ;
1365
+ let mut v = Vec :: with_capacity ( 128 ) ;
1359
1366
v. push ( 13 ) ;
1360
1367
1361
- // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
1362
- let v0 = unsafe { & * ( & v[ 0 ] as * const _ ) } ;
1363
-
1368
+ // Laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
1369
+ let v0 = & mut v[ 0 ] ;
1370
+ let v0 = unsafe { & mut * ( v0 as * mut _ ) } ;
1364
1371
// Now do a bunch of things and occasionally use `v0` again to assert it is still valid.
1372
+
1373
+ // Pushing/inserting and popping/removing
1365
1374
v. push ( 1 ) ;
1366
1375
v. push ( 2 ) ;
1367
1376
v. insert ( 1 , 1 ) ;
1368
1377
assert_eq ! ( * v0, 13 ) ;
1369
1378
v. remove ( 1 ) ;
1370
1379
v. pop ( ) . unwrap ( ) ;
1371
1380
assert_eq ! ( * v0, 13 ) ;
1381
+ v. push ( 1 ) ;
1382
+ v. swap_remove ( 1 ) ;
1383
+ assert_eq ! ( v. len( ) , 2 ) ;
1384
+ v. swap_remove ( 1 ) ; // swap_remove the last element
1385
+ assert_eq ! ( * v0, 13 ) ;
1386
+
1387
+ // Appending
1388
+ v. append ( & mut vec ! [ 27 , 19 ] ) ;
1389
+ assert_eq ! ( * v0, 13 ) ;
1390
+
1391
+ // Extending
1392
+ v. extend_from_slice ( & [ 1 , 2 ] ) ;
1393
+ v. extend ( & [ 1 , 2 ] ) ; // `slice::Iter` (with `T: Copy`) specialization
1394
+ v. extend ( vec ! [ 2 , 3 ] ) ; // `vec::IntoIter` specialization
1395
+ v. extend ( std:: iter:: once ( 3 ) ) ; // `TrustedLen` specialization
1396
+ v. extend ( std:: iter:: empty :: < i32 > ( ) ) ; // `TrustedLen` specialization with empty iterator
1397
+ v. extend ( std:: iter:: once ( 3 ) . filter ( |_| true ) ) ; // base case
1398
+ v. extend ( std:: iter:: once ( & 3 ) ) ; // `cloned` specialization
1399
+ assert_eq ! ( * v0, 13 ) ;
1400
+
1401
+ // Truncation
1402
+ v. truncate ( 2 ) ;
1403
+ assert_eq ! ( * v0, 13 ) ;
1404
+
1405
+ // Resizing
1406
+ v. resize_with ( v. len ( ) + 10 , || 42 ) ;
1407
+ assert_eq ! ( * v0, 13 ) ;
1408
+ v. resize_with ( 2 , || panic ! ( ) ) ;
1409
+ assert_eq ! ( * v0, 13 ) ;
1410
+
1411
+ // No-op reservation
1412
+ v. reserve ( 32 ) ;
1413
+ v. reserve_exact ( 32 ) ;
1414
+ assert_eq ! ( * v0, 13 ) ;
1415
+
1416
+ // Partial draining
1417
+ v. resize_with ( 10 , || 42 ) ;
1418
+ next_then_drop ( v. drain ( 5 ..) ) ;
1419
+ assert_eq ! ( * v0, 13 ) ;
1420
+
1421
+ // Splicing
1422
+ v. resize_with ( 10 , || 42 ) ;
1423
+ next_then_drop ( v. splice ( 5 .., vec ! [ 1 , 2 , 3 , 4 , 5 ] ) ) ; // empty tail after range
1424
+ assert_eq ! ( * v0, 13 ) ;
1425
+ next_then_drop ( v. splice ( 5 ..8 , vec ! [ 1 ] ) ) ; // replacement is smaller than original range
1426
+ assert_eq ! ( * v0, 13 ) ;
1427
+ next_then_drop ( v. splice ( 5 ..6 , vec ! [ 1 ; 10 ] . into_iter ( ) . filter ( |_| true ) ) ) ; // lower bound not exact
1428
+ assert_eq ! ( * v0, 13 ) ;
1429
+
1430
+ // Smoke test that would fire even outside Miri if an actual relocation happened.
1431
+ * v0 -= 13 ;
1432
+ assert_eq ! ( v[ 0 ] , 0 ) ;
1372
1433
}
1373
1434
1374
1435
// https://github.com/rust-lang/rust/pull/49496 introduced specialization based on:
0 commit comments