@@ -288,75 +288,64 @@ fn test_retain() {
288
288
}
289
289
290
290
#[ test]
291
- fn test_retain_pred_panic ( ) {
292
- use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
293
-
294
- struct Wrap < ' a > ( & ' a AtomicU64 , u64 , bool ) ;
295
-
296
- impl Drop for Wrap < ' _ > {
297
- fn drop ( & mut self ) {
298
- self . 0 . fetch_or ( self . 1 , Ordering :: SeqCst ) ;
299
- }
300
- }
301
-
302
- let dropped = AtomicU64 :: new ( 0 ) ;
291
+ fn test_retain_pred_panic_with_hole ( ) {
292
+ let v = ( 0 ..5 ) . map ( Rc :: new) . collect :: < Vec < _ > > ( ) ;
293
+ catch_unwind ( AssertUnwindSafe ( || {
294
+ let mut v = v. clone ( ) ;
295
+ v. retain ( |r| match * * r {
296
+ 0 => true ,
297
+ 1 => false ,
298
+ 2 => true ,
299
+ _ => panic ! ( ) ,
300
+ } ) ;
301
+ } ) )
302
+ . unwrap_err ( ) ;
303
+ // Everything is dropped when predicate panicked.
304
+ assert ! ( v. iter( ) . all( |r| Rc :: strong_count( r) == 1 ) ) ;
305
+ }
303
306
304
- let ret = std:: panic:: catch_unwind ( || {
305
- let mut v = vec ! [
306
- Wrap ( & dropped, 1 , false ) ,
307
- Wrap ( & dropped, 2 , false ) ,
308
- Wrap ( & dropped, 4 , false ) ,
309
- Wrap ( & dropped, 8 , false ) ,
310
- Wrap ( & dropped, 16 , false ) ,
311
- ] ;
312
- v. retain ( |w| match w. 1 {
313
- 1 => true ,
314
- 2 => false ,
315
- 4 => true ,
307
+ #[ test]
308
+ fn test_retain_pred_panic_no_hole ( ) {
309
+ let v = ( 0 ..5 ) . map ( Rc :: new) . collect :: < Vec < _ > > ( ) ;
310
+ catch_unwind ( AssertUnwindSafe ( || {
311
+ let mut v = v. clone ( ) ;
312
+ v. retain ( |r| match * * r {
313
+ 0 | 1 | 2 => true ,
316
314
_ => panic ! ( ) ,
317
315
} ) ;
318
- } ) ;
319
- assert ! ( ret . is_err ( ) ) ;
316
+ } ) )
317
+ . unwrap_err ( ) ;
320
318
// Everything is dropped when predicate panicked.
321
- assert_eq ! ( dropped . load ( Ordering :: SeqCst ) , 1 | 2 | 4 | 8 | 16 ) ;
319
+ assert ! ( v . iter ( ) . all ( |r| Rc :: strong_count ( r ) == 1 ) ) ;
322
320
}
323
321
324
322
#[ test]
325
323
fn test_retain_drop_panic ( ) {
326
- use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
327
-
328
- struct Wrap < ' a > ( & ' a AtomicU64 , u64 ) ;
324
+ struct Wrap ( Rc < i32 > ) ;
329
325
330
- impl Drop for Wrap < ' _ > {
326
+ impl Drop for Wrap {
331
327
fn drop ( & mut self ) {
332
- if self . 1 == 8 {
328
+ if * self . 0 == 3 {
333
329
panic ! ( ) ;
334
330
}
335
- self . 0 . fetch_or ( self . 1 , Ordering :: SeqCst ) ;
336
331
}
337
332
}
338
333
339
- let dropped = AtomicU64 :: new ( 0 ) ;
340
-
341
- let ret = std:: panic:: catch_unwind ( || {
342
- let mut v = vec ! [
343
- Wrap ( & dropped, 1 ) ,
344
- Wrap ( & dropped, 2 ) ,
345
- Wrap ( & dropped, 4 ) ,
346
- Wrap ( & dropped, 8 ) ,
347
- Wrap ( & dropped, 16 ) ,
348
- ] ;
349
- v. retain ( |w| match w. 1 {
350
- 1 => true ,
351
- 2 => false ,
352
- 4 => true ,
353
- 8 => false ,
334
+ let v = ( 0 ..5 ) . map ( |x| Rc :: new ( x) ) . collect :: < Vec < _ > > ( ) ;
335
+ catch_unwind ( AssertUnwindSafe ( || {
336
+ let mut v = v. iter ( ) . map ( |r| Wrap ( r. clone ( ) ) ) . collect :: < Vec < _ > > ( ) ;
337
+ v. retain ( |w| match * w. 0 {
338
+ 0 => true ,
339
+ 1 => false ,
340
+ 2 => true ,
341
+ 3 => false , // Drop panic.
354
342
_ => true ,
355
343
} ) ;
356
- } ) ;
357
- assert ! ( ret . is_err ( ) ) ;
344
+ } ) )
345
+ . unwrap_err ( ) ;
358
346
// Other elements are dropped when `drop` of one element panicked.
359
- assert_eq ! ( dropped. load( Ordering :: SeqCst ) , 1 | 2 | 4 | 16 ) ;
347
+ // The panicked wrapper also has its Rc dropped.
348
+ assert ! ( v. iter( ) . all( |r| Rc :: strong_count( r) == 1 ) ) ;
360
349
}
361
350
362
351
#[ test]
0 commit comments