| //@ run-pass |
| #![allow(unreachable_code)] |
| // More thorough regression test for Issues #30018 and #30822. This |
| // attempts to explore different ways that array element construction |
| // (for both scratch arrays and non-scratch ones) interacts with |
| // breaks in the control-flow, in terms of the order of evaluation of |
| // the destructors (which may change; see RFC Issue 744) and the |
| // number of times that the destructor evaluates for each value (which |
| // should never exceed 1; this latter case is what #30822 is about). |
| |
| use std::cell::RefCell; |
| |
| struct D<'a>(&'a RefCell<Vec<i32>>, i32); |
| |
| impl<'a> Drop for D<'a> { |
| fn drop(&mut self) { |
| println!("Dropping D({})", self.1); |
| (self.0).borrow_mut().push(self.1); |
| } |
| } |
| |
| fn main() { |
| println!("Start"); |
| break_during_elem(); |
| break_after_whole(); |
| println!("Finis"); |
| } |
| |
| fn break_during_elem() { |
| let log = &RefCell::new(Vec::new()); |
| |
| // CASE 1: Fixed-size array itself is stored in _r slot. |
| loop { |
| let _r = [D(log, 10), |
| D(log, 11), |
| { D(log, 12); break; }, |
| D(log, 13)]; |
| } |
| assert_eq!(&log.borrow()[..], &[12, 11, 10]); |
| log.borrow_mut().clear(); |
| |
| // CASE 2: Slice (borrow of array) is stored in _r slot. |
| // This is the case that is actually being reported in #30018. |
| loop { |
| let _r = &[D(log, 20), |
| D(log, 21), |
| { D(log, 22); break; }, |
| D(log, 23)]; |
| } |
| assert_eq!(&log.borrow()[..], &[22, 21, 20]); |
| log.borrow_mut().clear(); |
| |
| // CASE 3: (Borrow of) slice-index of array is stored in _r slot. |
| loop { |
| let _r = &[D(log, 30), |
| D(log, 31), |
| { D(log, 32); break; }, |
| D(log, 33)][..]; |
| } |
| assert_eq!(&log.borrow()[..], &[32, 31, 30]); |
| log.borrow_mut().clear(); |
| } |
| |
| // The purpose of these functions is to test what happens when we |
| // panic after an array has been constructed in its entirety. |
| // |
| // It is meant to act as proof that we still need to continue |
| // scheduling the destruction of an array even after we've scheduling |
| // drop for its elements during construction; the latter is tested by |
| // `fn break_during_elem()`. |
| fn break_after_whole() { |
| let log = &RefCell::new(Vec::new()); |
| |
| // CASE 1: Fixed-size array itself is stored in _r slot. |
| loop { |
| let _r = [D(log, 10), |
| D(log, 11), |
| D(log, 12)]; |
| break; |
| } |
| assert_eq!(&log.borrow()[..], &[10, 11, 12]); |
| log.borrow_mut().clear(); |
| |
| // CASE 2: Slice (borrow of array) is stored in _r slot. |
| loop { |
| let _r = &[D(log, 20), |
| D(log, 21), |
| D(log, 22)]; |
| break; |
| } |
| assert_eq!(&log.borrow()[..], &[20, 21, 22]); |
| log.borrow_mut().clear(); |
| |
| // CASE 3: (Borrow of) slice-index of array is stored in _r slot. |
| loop { |
| let _r = &[D(log, 30), |
| D(log, 31), |
| D(log, 32)][..]; |
| break; |
| } |
| assert_eq!(&log.borrow()[..], &[30, 31, 32]); |
| log.borrow_mut().clear(); |
| } |