@@ -41,7 +41,7 @@ impl Allocator {
4141 data : RefCell :: new ( vec ! [ ] )
4242 }
4343 }
44- fn alloc ( & self ) -> Ptr {
44+ fn alloc ( & self ) -> Ptr < ' _ > {
4545 self . cur_ops . set ( self . cur_ops . get ( ) + 1 ) ;
4646
4747 if self . cur_ops . get ( ) == self . failing_op {
@@ -53,6 +53,20 @@ impl Allocator {
5353 data. push ( true ) ;
5454 Ptr ( addr, self )
5555 }
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+ }
5670}
5771
5872struct Ptr < ' a > ( usize , & ' a Allocator ) ;
@@ -255,6 +269,72 @@ fn subslice_pattern_reassign(a: &Allocator) {
255269 let [ _, _y..] = ar;
256270}
257271
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+
258338fn run_test < F > ( mut f : F )
259339 where F : FnMut ( & Allocator )
260340{
@@ -342,5 +422,15 @@ fn main() {
342422 run_test ( |a| slice_pattern_reassign ( a) ) ;
343423 run_test ( |a| subslice_pattern_reassign ( a) ) ;
344424
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+
345435 run_test_nopanic ( |a| union1 ( a) ) ;
346436}
0 commit comments