| #![feature(generators, negative_impls, rustc_attrs)] |
| |
| macro_rules! type_combinations { |
| ( |
| $( $name:ident => { $( $tt:tt )* } );* $(;)? |
| ) => { $( |
| mod $name { |
| $( $tt )* |
| |
| impl !Sync for Client {} |
| impl !Send for Client {} |
| } |
| |
| // Struct update syntax. This fails because the Client used in the update is considered |
| // dropped *after* the yield. |
| { |
| let g = move || match drop($name::Client { ..$name::Client::default() }) { |
| //~^ `significant_drop::Client` which is not `Send` |
| //~| `insignificant_dtor::Client` which is not `Send` |
| //~| `derived_drop::Client` which is not `Send` |
| _ => yield, |
| }; |
| assert_send(g); |
| //~^ ERROR cannot be sent between threads |
| //~| ERROR cannot be sent between threads |
| //~| ERROR cannot be sent between threads |
| } |
| |
| // Simple owned value. This works because the Client is considered moved into `drop`, |
| // even though the temporary expression doesn't end until after the yield. |
| { |
| let g = move || match drop($name::Client::default()) { |
| _ => yield, |
| }; |
| assert_send(g); |
| } |
| )* } |
| } |
| |
| fn assert_send<T: Send>(_thing: T) {} |
| |
| fn main() { |
| type_combinations!( |
| // OK |
| copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; |
| // NOT OK: MIR borrowck thinks that this is used after the yield, even though |
| // this has no `Drop` impl and only the drops of the fields are observable. |
| // FIXME: this should compile. |
| derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; |
| // NOT OK |
| significant_drop => { |
| #[derive(Default)] |
| pub struct Client; |
| impl Drop for Client { |
| fn drop(&mut self) {} |
| } |
| }; |
| // NOT OK (we need to agree with MIR borrowck) |
| insignificant_dtor => { |
| #[derive(Default)] |
| #[rustc_insignificant_dtor] |
| pub struct Client; |
| impl Drop for Client { |
| fn drop(&mut self) {} |
| } |
| }; |
| ); |
| } |