summaryrefslogtreecommitdiffstats
path: root/tests/ui/generator/drop-tracking-parent-expression.rs
blob: d40f1b8f64d4aa587b9df5591f07702b23937d11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// compile-flags: -Zdrop-tracking
#![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) {}
            }
        };
    );
}