| //@ run-pass |
| #![feature(coroutines, stmt_expr_attributes)] |
| #![feature(coroutine_trait)] |
| use std::cell::Cell; |
| use std::mem; |
| use std::ops::Coroutine; |
| use std::pin::Pin; |
| |
| struct Aligned<'a> { |
| drop_count: &'a Cell<usize>, |
| } |
| |
| #[inline(never)] |
| fn check_align(ptr: *const Aligned) { |
| assert_eq!(ptr as usize % mem::align_of::<Aligned>(), 0); |
| } |
| |
| impl<'a> Drop for Aligned<'a> { |
| fn drop(&mut self) { |
| check_align(self); |
| self.drop_count.set(self.drop_count.get() + 1); |
| } |
| } |
| |
| #[repr(transparent)] |
| struct NotCopy(u8); |
| |
| #[repr(packed)] |
| struct Packed<'a>(NotCopy, Aligned<'a>); |
| |
| fn main() { |
| let drop_count = &Cell::new(0); |
| { |
| let mut p = Packed(NotCopy(0), Aligned { drop_count }); |
| p.1 = Aligned { drop_count }; |
| assert_eq!(drop_count.get(), 1); |
| } |
| assert_eq!(drop_count.get(), 2); |
| |
| let drop_count = &Cell::new(0); |
| let mut g = #[coroutine] |
| || { |
| let mut p = Packed(NotCopy(0), Aligned { drop_count }); |
| let _ = &p; |
| p.1 = Aligned { drop_count }; |
| assert_eq!(drop_count.get(), 1); |
| // Test that a coroutine drop function moves a value from a packed |
| // struct to a separate local before dropping it. We move out the |
| // first field to generate and open drop for the second field. |
| drop(p.0); |
| yield; |
| }; |
| Pin::new(&mut g).resume(()); |
| assert_eq!(drop_count.get(), 1); |
| drop(g); |
| assert_eq!(drop_count.get(), 2); |
| } |