summaryrefslogtreecommitdiffstats
path: root/src/test/ui/polymorphization/type_parameters/closures.rs
blob: 07ab1355a47cfe62159c653ae6dcb8d51ef2bd1d (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// build-fail
// compile-flags:-Zpolymorphize=on
#![feature(stmt_expr_attributes, rustc_attrs)]

// This test checks that the polymorphization analysis correctly detects unused type
// parameters in closures.

// Function doesn't have any generic parameters to be unused.
#[rustc_polymorphize_error]
pub fn no_parameters() {
    let _ = || {};
}

// Function has an unused generic parameter in parent and closure.
#[rustc_polymorphize_error]
pub fn unused<T>() -> u32 {
    //~^ ERROR item has unused generic parameters

    let add_one = |x: u32| x + 1;
    //~^ ERROR item has unused generic parameters
    add_one(3)
}

// Function has an unused generic parameter in closure, but not in parent.
#[rustc_polymorphize_error]
pub fn used_parent<T: Default>() -> u32 {
    let _: T = Default::default();
    let add_one = |x: u32| x + 1;
    //~^ ERROR item has unused generic parameters
    add_one(3)
}

// Function uses generic parameter in value of a binding in closure.
#[rustc_polymorphize_error]
pub fn used_binding_value<T: Default>() -> T {
    let x = || {
        let y: T = Default::default();
        y
    };

    x()
}

// Function uses generic parameter in generic of a binding in closure.
#[rustc_polymorphize_error]
pub fn used_binding_generic<T>() -> Option<T> {
    let x = || {
        let y: Option<T> = None;
        y
    };

    x()
}

// Function and closure uses generic parameter in argument.
#[rustc_polymorphize_error]
pub fn used_argument<T>(t: T) -> u32 {
    let x = |_: T| 3;
    x(t)
}

// Closure uses generic parameter in argument.
#[rustc_polymorphize_error]
pub fn used_argument_closure<T: Default>() -> u32 {
    let t: T = Default::default();

    let x = |_: T| 3;
    x(t)
}

// Closure uses generic parameter as upvar.
#[rustc_polymorphize_error]
pub fn used_upvar<T: Default>() -> T {
    let x: T = Default::default();

    let y = || x;
    y()
}

// Closure uses generic parameter in substitutions to another function.
#[rustc_polymorphize_error]
pub fn used_substs<T>() -> u32 {
    let x = || unused::<T>();
    x()
}

struct Foo<F>(F);

impl<F: Default> Foo<F> {
    // Function has an unused generic parameter from impl and fn.
    #[rustc_polymorphize_error]
    pub fn unused_all<G: Default>() -> u32 {
        //~^ ERROR item has unused generic parameters
        let add_one = |x: u32| x + 1;
        //~^ ERROR item has unused generic parameters
        add_one(3)
    }

    // Function uses generic parameter from impl and fn in closure.
    #[rustc_polymorphize_error]
    pub fn used_both<G: Default>() -> u32 {
        let add_one = |x: u32| {
            let _: F = Default::default();
            let _: G = Default::default();
            x + 1
        };

        add_one(3)
    }

    // Function uses generic parameter from fn in closure.
    #[rustc_polymorphize_error]
    pub fn used_fn<G: Default>() -> u32 {
        //~^ ERROR item has unused generic parameters
        let add_one = |x: u32| {
            //~^ ERROR item has unused generic parameters
            let _: G = Default::default();
            x + 1
        };

        add_one(3)
    }

    // Function uses generic parameter from impl in closure.
    #[rustc_polymorphize_error]
    pub fn used_impl<G: Default>() -> u32 {
        //~^ ERROR item has unused generic parameters
        let add_one = |x: u32| {
            //~^ ERROR item has unused generic parameters
            let _: F = Default::default();
            x + 1
        };

        add_one(3)
    }

    // Closure uses generic parameter in substitutions to another function.
    #[rustc_polymorphize_error]
    pub fn used_substs() -> u32 {
        let x = || unused::<F>();
        x()
    }
}

fn main() {
    no_parameters();
    let _ = unused::<u32>();
    let _ = used_parent::<u32>();
    let _ = used_binding_value::<u32>();
    let _ = used_binding_generic::<u32>();
    let _ = used_argument(3u32);
    let _ = used_argument_closure::<u32>();
    let _ = used_upvar::<u32>();
    let _ = used_substs::<u32>();

    let _ = Foo::<u32>::unused_all::<u32>();
    let _ = Foo::<u32>::used_both::<u32>();
    let _ = Foo::<u32>::used_impl::<u32>();
    let _ = Foo::<u32>::used_fn::<u32>();
    let _ = Foo::<u32>::used_substs();
}