| //@ run-pass | |
| #![allow(dead_code)] | |
| #![allow(unused_assignments)] | |
| #![allow(unused_variables)] | |
| //@ needs-threads | |
| //@ needs-unwind | |
| //@ ignore-backends: gcc | |
| use std::thread; | |
| use std::sync::mpsc::{channel, Sender}; | |
| #[derive(PartialEq, Debug)] | |
| enum Message { | |
| Dropped, | |
| DestructorRan | |
| } | |
| struct SendOnDrop { | |
| sender: Sender<Message> | |
| } | |
| impl Drop for SendOnDrop { | |
| fn drop(&mut self) { | |
| self.sender.send(Message::Dropped).unwrap(); | |
| } | |
| } | |
| enum Foo { | |
| SimpleVariant(Sender<Message>), | |
| NestedVariant(Box<usize>, SendOnDrop, Sender<Message>), | |
| FailingVariant { on_drop: SendOnDrop } | |
| } | |
| impl Drop for Foo { | |
| fn drop(&mut self) { | |
| match self { | |
| &mut Foo::SimpleVariant(ref mut sender) => { | |
| sender.send(Message::DestructorRan).unwrap(); | |
| } | |
| &mut Foo::NestedVariant(_, _, ref mut sender) => { | |
| sender.send(Message::DestructorRan).unwrap(); | |
| } | |
| &mut Foo::FailingVariant { .. } => { | |
| panic!("Failed"); | |
| } | |
| } | |
| } | |
| } | |
| pub fn main() { | |
| let (sender, receiver) = channel(); | |
| { | |
| let v = Foo::SimpleVariant(sender); | |
| } | |
| assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); | |
| assert_eq!(receiver.recv().ok(), None); | |
| let (sender, receiver) = channel(); | |
| { | |
| let v = Foo::NestedVariant(Box::new(42), SendOnDrop { sender: sender.clone() }, sender); | |
| } | |
| assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); | |
| assert_eq!(receiver.recv().unwrap(), Message::Dropped); | |
| assert_eq!(receiver.recv().ok(), None); | |
| let (sender, receiver) = channel(); | |
| let t = thread::spawn(move|| { | |
| let v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } }; | |
| }); | |
| assert_eq!(receiver.recv().unwrap(), Message::Dropped); | |
| assert_eq!(receiver.recv().ok(), None); | |
| drop(t.join()); | |
| let (sender, receiver) = channel(); | |
| let t = { | |
| thread::spawn(move|| { | |
| let mut v = Foo::NestedVariant(Box::new(42), SendOnDrop { | |
| sender: sender.clone() | |
| }, sender.clone()); | |
| v = Foo::NestedVariant(Box::new(42), | |
| SendOnDrop { sender: sender.clone() }, | |
| sender.clone()); | |
| v = Foo::SimpleVariant(sender.clone()); | |
| v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } }; | |
| }) | |
| }; | |
| assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); | |
| assert_eq!(receiver.recv().unwrap(), Message::Dropped); | |
| assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); | |
| assert_eq!(receiver.recv().unwrap(), Message::Dropped); | |
| assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); | |
| assert_eq!(receiver.recv().unwrap(), Message::Dropped); | |
| assert_eq!(receiver.recv().ok(), None); | |
| drop(t.join()); | |
| } |