@@ -41,7 +41,7 @@ impl Allocator {
41
41
data : RefCell :: new ( vec ! [ ] )
42
42
}
43
43
}
44
- fn alloc ( & self ) -> Ptr {
44
+ fn alloc ( & self ) -> Ptr < ' _ > {
45
45
self . cur_ops . set ( self . cur_ops . get ( ) + 1 ) ;
46
46
47
47
if self . cur_ops . get ( ) == self . failing_op {
@@ -53,6 +53,20 @@ impl Allocator {
53
53
data. push ( true ) ;
54
54
Ptr ( addr, self )
55
55
}
56
+ // FIXME(#47949) Any use of this indicates a bug in rustc: we should never
57
+ // be leaking values in the cases here.
58
+ //
59
+ // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the
60
+ // `failing_op` is in the list of exception.
61
+ fn alloc_leaked ( & self , exceptions : Vec < usize > ) -> Ptr < ' _ > {
62
+ let ptr = self . alloc ( ) ;
63
+
64
+ if exceptions. iter ( ) . any ( |operation| * operation == self . failing_op ) {
65
+ let mut data = self . data . borrow_mut ( ) ;
66
+ data[ ptr. 0 ] = false ;
67
+ }
68
+ ptr
69
+ }
56
70
}
57
71
58
72
struct Ptr < ' a > ( usize , & ' a Allocator ) ;
@@ -255,6 +269,72 @@ fn subslice_pattern_reassign(a: &Allocator) {
255
269
let [ _, _y..] = ar;
256
270
}
257
271
272
+ fn panic_after_return ( a : & Allocator ) -> Ptr < ' _ > {
273
+ // Panic in the drop of `p` or `q` can leak
274
+ let exceptions = vec ! [ 8 , 9 ] ;
275
+ a. alloc ( ) ;
276
+ let p = a. alloc ( ) ;
277
+ {
278
+ a. alloc ( ) ;
279
+ let p = a. alloc ( ) ;
280
+ // FIXME (#47949) We leak values when we panic in a destructor after
281
+ // evaluating an expression with `rustc_mir::build::Builder::into`.
282
+ a. alloc_leaked ( exceptions)
283
+ }
284
+ }
285
+
286
+ fn panic_after_return_expr ( a : & Allocator ) -> Ptr < ' _ > {
287
+ // Panic in the drop of `p` or `q` can leak
288
+ let exceptions = vec ! [ 8 , 9 ] ;
289
+ a. alloc ( ) ;
290
+ let p = a. alloc ( ) ;
291
+ {
292
+ a. alloc ( ) ;
293
+ let q = a. alloc ( ) ;
294
+ // FIXME (#47949)
295
+ return a. alloc_leaked ( exceptions) ;
296
+ }
297
+ }
298
+
299
+ fn panic_after_init ( a : & Allocator ) {
300
+ // Panic in the drop of `r` can leak
301
+ let exceptions = vec ! [ 8 ] ;
302
+ a. alloc ( ) ;
303
+ let p = a. alloc ( ) ;
304
+ let q = {
305
+ a. alloc ( ) ;
306
+ let r = a. alloc ( ) ;
307
+ // FIXME (#47949)
308
+ a. alloc_leaked ( exceptions)
309
+ } ;
310
+ }
311
+
312
+ fn panic_after_init_temp ( a : & Allocator ) {
313
+ // Panic in the drop of `r` can leak
314
+ let exceptions = vec ! [ 8 ] ;
315
+ a. alloc ( ) ;
316
+ let p = a. alloc ( ) ;
317
+ {
318
+ a. alloc ( ) ;
319
+ let r = a. alloc ( ) ;
320
+ // FIXME (#47949)
321
+ a. alloc_leaked ( exceptions)
322
+ } ;
323
+ }
324
+
325
+ fn panic_after_init_by_loop ( a : & Allocator ) {
326
+ // Panic in the drop of `r` can leak
327
+ let exceptions = vec ! [ 8 ] ;
328
+ a. alloc ( ) ;
329
+ let p = a. alloc ( ) ;
330
+ let q = loop {
331
+ a. alloc ( ) ;
332
+ let r = a. alloc ( ) ;
333
+ // FIXME (#47949)
334
+ break a. alloc_leaked ( exceptions) ;
335
+ } ;
336
+ }
337
+
258
338
fn run_test < F > ( mut f : F )
259
339
where F : FnMut ( & Allocator )
260
340
{
@@ -342,5 +422,15 @@ fn main() {
342
422
run_test ( |a| slice_pattern_reassign ( a) ) ;
343
423
run_test ( |a| subslice_pattern_reassign ( a) ) ;
344
424
425
+ run_test ( |a| {
426
+ panic_after_return ( a) ;
427
+ } ) ;
428
+ run_test ( |a| {
429
+ panic_after_return_expr ( a) ;
430
+ } ) ;
431
+ run_test ( |a| panic_after_init ( a) ) ;
432
+ run_test ( |a| panic_after_init_temp ( a) ) ;
433
+ run_test ( |a| panic_after_init_by_loop ( a) ) ;
434
+
345
435
run_test_nopanic ( |a| union1 ( a) ) ;
346
436
}
0 commit comments