@@ -4,16 +4,20 @@ use formality_types::{
4
4
derive_links:: UpcastFrom ,
5
5
fold:: Fold ,
6
6
grammar:: { Binder , InferenceVar , Parameter , Substitution , Variable } ,
7
+ term:: Term ,
7
8
visit:: Visit ,
8
9
} ;
9
10
11
+ use super :: subst:: existential_substitution;
12
+
10
13
#[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Debug , Hash ) ]
11
- pub struct Constraints {
14
+ pub struct Constraints < R : Term = ( ) > {
15
+ result : R ,
12
16
known_true : bool ,
13
17
substitution : Substitution ,
14
18
}
15
19
16
- cast_impl ! ( Constraints ) ;
20
+ cast_impl ! ( impl ( R : Term ) Constraints < R > ) ;
17
21
18
22
impl < A , B > UpcastFrom < ( A , B ) > for Constraints
19
23
where
@@ -24,38 +28,100 @@ where
24
28
Constraints {
25
29
substitution : term. upcast ( ) ,
26
30
known_true : true ,
31
+ result : ( ) ,
27
32
}
28
33
}
29
34
}
30
35
36
+ impl < A , B > FromIterator < ( A , B ) > for Constraints
37
+ where
38
+ A : Upcast < Variable > ,
39
+ B : Upcast < Parameter > ,
40
+ {
41
+ fn from_iter < T : IntoIterator < Item = ( A , B ) > > ( iter : T ) -> Self {
42
+ let substitution = iter. into_iter ( ) . collect ( ) ;
43
+ let c = Constraints {
44
+ substitution,
45
+ known_true : true ,
46
+ result : ( ) ,
47
+ } ;
48
+ c. assert_valid ( ) ;
49
+ c
50
+ }
51
+ }
52
+
31
53
impl Default for Constraints {
32
54
fn default ( ) -> Self {
33
55
Self {
56
+ result : ( ) ,
34
57
known_true : true ,
35
58
substitution : Default :: default ( ) ,
36
59
}
37
60
}
38
61
}
39
62
40
- impl Constraints {
63
+ impl < R : Term > Constraints < R > {
41
64
pub fn substitution ( & self ) -> & Substitution {
42
65
& self . substitution
43
66
}
44
67
45
- pub fn ambiguous ( self ) -> Constraints {
68
+ pub fn ambiguous ( self ) -> Constraints < R > {
46
69
Self {
47
70
known_true : false ,
48
71
..self
49
72
}
50
73
}
74
+
75
+ pub fn map < S : Term > ( self , op : impl FnOnce ( R ) -> S ) -> Constraints < S > {
76
+ let Constraints {
77
+ result,
78
+ known_true,
79
+ substitution,
80
+ } = self ;
81
+ let result = op ( result) ;
82
+ Constraints {
83
+ known_true,
84
+ substitution,
85
+ result,
86
+ }
87
+ }
88
+
89
+ pub fn split_result ( self ) -> ( R , Constraints ) {
90
+ let Constraints {
91
+ result,
92
+ known_true,
93
+ substitution,
94
+ } = self ;
95
+ (
96
+ result,
97
+ Constraints {
98
+ known_true,
99
+ substitution,
100
+ result : ( ) ,
101
+ } ,
102
+ )
103
+ }
51
104
}
52
105
53
- pub fn merge_constraints (
106
+ pub fn instantiate_and_apply_constraints < T : Term , R : Term > (
107
+ c : Binder < Constraints < R > > ,
108
+ term : T ,
109
+ ) -> ( Vec < InferenceVar > , Constraints < R > , T ) {
110
+ let existentials = existential_substitution ( & c, & term) ;
111
+ let c = c. instantiate_with ( & existentials) . unwrap ( ) ;
112
+ let term = c. substitution ( ) . apply ( & term) ;
113
+ ( existentials, c, term)
114
+ }
115
+
116
+ pub fn merge_constraints < R0 : Term , R1 : Term > (
54
117
existentials : impl Upcast < Vec < Variable > > ,
55
- c0 : impl Upcast < Constraints > ,
56
- c1 : Binder < Constraints > ,
57
- ) -> Binder < Constraints > {
58
- let c0: Constraints = c0. upcast ( ) ;
118
+ c0 : impl Upcast < Constraints < R0 > > ,
119
+ c1 : Binder < Constraints < R1 > > ,
120
+ ) -> Binder < Constraints < R1 > >
121
+ where
122
+ R0 : CombineResults < R1 > ,
123
+ {
124
+ let c0: Constraints < R0 > = c0. upcast ( ) ;
59
125
c0. assert_valid ( ) ;
60
126
61
127
let ( c1_bound_vars, c1) = c1. open ( ) ;
@@ -85,20 +151,25 @@ pub fn merge_constraints(
85
151
. collect ( ) ;
86
152
87
153
let known_true = c0. known_true && c1. known_true ;
154
+
155
+ let result = R0 :: combine ( c0. result , c1. result ) ;
156
+
88
157
Binder :: mentioned (
89
158
( c1_bound_vars, existentials) ,
90
159
Constraints {
91
160
known_true,
92
161
substitution,
162
+ result,
93
163
} ,
94
164
)
95
165
}
96
166
97
- impl Fold for Constraints {
167
+ impl < R : Term > Fold for Constraints < R > {
98
168
fn substitute ( & self , substitution_fn : formality_types:: fold:: SubstitutionFn < ' _ > ) -> Self {
99
169
let c = Constraints {
100
170
known_true : self . known_true ,
101
171
substitution : self . substitution . substitute ( substitution_fn) ,
172
+ result : self . result . substitute ( substitution_fn) ,
102
173
} ;
103
174
104
175
// not all substitutions preserve the constraint set invariant
@@ -108,29 +179,50 @@ impl Fold for Constraints {
108
179
}
109
180
}
110
181
111
- impl Visit for Constraints {
182
+ impl < R : Term > Visit for Constraints < R > {
112
183
fn free_variables ( & self ) -> Vec < Variable > {
113
184
let Constraints {
114
185
known_true : _,
115
186
substitution,
187
+ result,
116
188
} = self ;
117
- substitution. free_variables ( )
189
+
190
+ substitution
191
+ . free_variables ( )
192
+ . into_iter ( )
193
+ . chain ( result. free_variables ( ) )
194
+ . collect ( )
118
195
}
119
196
120
197
fn size ( & self ) -> usize {
121
198
let Constraints {
122
199
known_true : _,
123
200
substitution,
201
+ result,
124
202
} = self ;
125
- substitution. size ( )
203
+ substitution. size ( ) + result . size ( )
126
204
}
127
205
128
206
fn assert_valid ( & self ) {
129
- let domain = self . substitution . domain ( ) ;
130
- let range = self . substitution . range ( ) ;
207
+ let Constraints {
208
+ known_true : _,
209
+ substitution,
210
+ result,
211
+ } = self ;
212
+
213
+ let domain = substitution. domain ( ) ;
214
+
215
+ for & v in & domain {
216
+ assert ! ( v. is_free( ) ) ;
217
+ assert ! ( is_valid_binding( v, & substitution[ v] ) ) ;
218
+ }
219
+
220
+ let range = substitution. range ( ) ;
131
221
range
132
222
. iter ( )
133
223
. for_each ( |t| assert ! ( domain. iter( ) . all( |& v| !occurs_in( v, t) ) ) ) ;
224
+
225
+ result. assert_valid ( ) ;
134
226
}
135
227
}
136
228
@@ -139,12 +231,46 @@ pub fn occurs_in(v: impl Upcast<Variable>, t: &impl Visit) -> bool {
139
231
t. free_variables ( ) . contains ( & v)
140
232
}
141
233
234
+ /// True if `t` would be a valid binding for `v`, meaning...
235
+ /// * `v` does not appear in `t`; and,
236
+ /// * all free variables in `t` are within the universe of `v`
237
+ pub fn is_valid_binding ( v : impl Upcast < Variable > , t : & impl Visit ) -> bool {
238
+ let v: Variable = v. upcast ( ) ;
239
+ assert ! ( v. is_free( ) ) ;
240
+
241
+ let v_universe = v. max_universe ( ) ;
242
+ t. free_variables ( )
243
+ . into_iter ( )
244
+ . all ( |fv| fv != v && fv. max_universe ( ) <= v_universe)
245
+ }
246
+
142
247
pub fn constrain ( v : impl Upcast < InferenceVar > , p : impl Upcast < Parameter > ) -> Binder < Constraints > {
143
248
let v: InferenceVar = v. upcast ( ) ;
144
249
let p: Parameter = p. upcast ( ) ;
145
250
Binder :: dummy ( ( v, p) . upcast ( ) )
146
251
}
147
252
148
- pub fn no_constraints ( ) -> Binder < Constraints > {
149
- Binder :: dummy ( ( ) . upcast ( ) )
253
+ pub fn no_constraints < R : Term > ( result : R ) -> Binder < Constraints < R > > {
254
+ Binder :: dummy ( Constraints {
255
+ result,
256
+ known_true : true ,
257
+ substitution : Substitution :: default ( ) ,
258
+ } )
259
+ }
260
+
261
+ pub trait CombineResults < R > {
262
+ fn combine ( r0 : Self , r1 : R ) -> R ;
263
+ }
264
+
265
+ impl < R > CombineResults < R > for ( ) {
266
+ fn combine ( ( ) : ( ) , r1 : R ) -> R {
267
+ r1
268
+ }
269
+ }
270
+
271
+ impl CombineResults < Vec < Parameter > > for Parameter {
272
+ fn combine ( r0 : Self , mut r1 : Vec < Parameter > ) -> Vec < Parameter > {
273
+ r1. push ( r0) ;
274
+ r1
275
+ }
150
276
}
0 commit comments