@@ -16,42 +16,54 @@ fn function_implement_fn_traits() {
16
16
trait Fn <Args > where Self : FnMut <Args > { }
17
17
}
18
18
19
+ // Simple test: make sure a fully monomorphic type implements FnOnce
19
20
goal {
20
21
fn ( u8 ) : FnOnce <( u8 , ) >
21
22
} yields {
22
23
"Unique; substitution [], lifetime constraints []"
23
24
}
24
25
26
+ // Same as above, but for FnMut
25
27
goal {
26
28
fn ( u8 ) : FnMut <( u8 , ) >
27
29
} yields {
28
30
"Unique; substitution [], lifetime constraints []"
29
31
}
30
32
33
+ // Same as above, but for Fn
31
34
goal {
32
35
fn ( u8 ) : Fn <( u8 , ) >
33
36
} yields {
34
37
"Unique; substitution [], lifetime constraints []"
35
38
}
36
39
40
+ // Function pointres implicity return `()` when no return
41
+ // type is specified - make sure that normalization understands
42
+ // this
37
43
goal {
38
44
Normalize ( <fn ( u8 ) as FnOnce <( u8 , ) >>:: Output -> ( ) )
39
45
} yields {
40
46
"Unique; substitution [], lifetime constraints []"
41
47
}
42
48
49
+ // Tests normalizing when an explicit return type is used
43
50
goal {
44
51
Normalize ( <fn ( u8 ) -> bool as FnOnce <( u8 , ) >>:: Output -> bool )
45
52
} yields {
46
53
"Unique; substitution [], lifetime constraints []"
47
54
}
48
55
56
+ // Tests that we fail to normalize when there's a mismatch with
57
+ // fully monomorphic types.
49
58
goal {
50
59
Normalize ( <fn ( u8 ) -> bool as FnOnce <( u8 , ) >>:: Output -> u8 )
51
60
} yields {
52
61
"No possible solution"
53
62
}
54
63
64
+ // Ensures that we don't find a solution when doing so would
65
+ // require us to conclude that two different universally quantified
66
+ // types (T and V) are equal.
55
67
goal {
56
68
forall<T , V > {
57
69
Normalize ( <fn ( u8 , V ) -> T as FnOnce <( u8 , V ) >>:: Output -> V )
@@ -60,6 +72,7 @@ fn function_implement_fn_traits() {
60
72
"No possible solution"
61
73
}
62
74
75
+ // Tests that we can normalize a generic function pointer type
63
76
goal {
64
77
forall<T , V > {
65
78
exists<U > {
@@ -70,18 +83,25 @@ fn function_implement_fn_traits() {
70
83
"Unique; substitution [?0 := !1_0], lifetime constraints []"
71
84
}
72
85
86
+ // Tests that we properly tuple function arguments when constrcting
87
+ // the `FnOnce` impl
73
88
goal {
74
89
fn ( u8 , u32 ) : FnOnce <( u8 , u32 ) >
75
90
} yields {
76
91
"Unique; substitution [], lifetime constraints []"
77
92
}
78
93
94
+ // Tests that we don't find a solution when fully monomorphic
95
+ // types are mismatched
79
96
goal {
80
97
fn ( i32 ) : FnOnce <( bool , ) >
81
98
} yields {
82
99
"No possible solution"
83
100
}
84
101
102
+ // Tests function pointer types that use the function's binder
103
+ // Universally quantified lifetimes that differ only in their
104
+ // name ('a vs 'b) should be considered equivalent here
85
105
goal {
86
106
forall<' a> {
87
107
for <' b> fn ( & ' b u8 ) : FnOnce <( & ' a u8 , ) >
@@ -90,6 +110,10 @@ fn function_implement_fn_traits() {
90
110
"Unique; substitution [], lifetime constraints []"
91
111
}
92
112
113
+ // Tests that a 'stricter' function (requires lifetimes to be the same)
114
+ // can implement `FnOnce` for a 'less strict' signature (dose not require
115
+ // lifetimes to be the same), provided that the lifetimes are *actually*
116
+ // the same.
93
117
goal {
94
118
forall<' a, ' b> {
95
119
for <' c> fn ( & ' c u8 , & ' c i32 ) : FnOnce <( & ' a u8 , & ' b i32 ) >
@@ -98,6 +122,22 @@ fn function_implement_fn_traits() {
98
122
"Unique; substitution [], lifetime constraints [InEnvironment { environment: Env([]), goal: '!1_0: '!1_1 }, InEnvironment { environment: Env([]), goal: '!1_1: '!1_0 }]"
99
123
}
100
124
125
+ // Tests the opposite case as the previous test: a 'less strict' function
126
+ // (does not require lifetimes to be the same) can implement `FnOnce` for
127
+ // a 'stricter' signature (requires lifetimes to be the same) without
128
+ // any additional requirements
129
+ goal {
130
+ forall<' a> {
131
+ for <' b, ' c> fn ( & ' b u8 , & ' c i32 ) : FnOnce <( & ' a u8 , & ' a i32 ) >
132
+ }
133
+ } yields {
134
+ "Unique; substitution [], lifetime constraints []"
135
+ }
136
+
137
+ // Similiar to the above test, but for types instead of lifetimes:
138
+ // a 'stricter' function (requires types to be the same) can never
139
+ // implement `FnOnce` for a 'less strict' signature (does not require
140
+ // types to be the same)
101
141
goal {
102
142
forall<T , U > {
103
143
fn ( T , T ) : FnOnce <( T , U ) >
@@ -106,6 +146,9 @@ fn function_implement_fn_traits() {
106
146
"No possible solution"
107
147
}
108
148
149
+ // Tests the opposite case as a previous test: a 'less strict'
150
+ // function can never implement 'FnOnce' for a 'more strict' signature
151
+ // (does not require types to bthe same)
109
152
goal {
110
153
forall<T , U > {
111
154
fn ( T , U ) : FnOnce <( T , T ) >
0 commit comments