@@ -3,12 +3,12 @@ use formality_types::{
3
3
cast_impl,
4
4
derive_links:: UpcastFrom ,
5
5
fold:: Fold ,
6
- grammar:: { Binder , InferenceVar , Parameter , Substitution , Variable } ,
6
+ grammar:: { Parameter , Substitution , Variable } ,
7
7
term:: Term ,
8
8
visit:: Visit ,
9
9
} ;
10
10
11
- use super :: subst :: existential_substitution ;
11
+ use super :: env :: Env ;
12
12
13
13
#[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Debug , Hash ) ]
14
14
pub struct Constraints < R : Term = ( ) > {
@@ -40,13 +40,13 @@ where
40
40
{
41
41
fn from_iter < T : IntoIterator < Item = ( A , B ) > > ( iter : T ) -> Self {
42
42
let substitution = iter. into_iter ( ) . collect ( ) ;
43
- let c = Constraints {
43
+ let c2 = Constraints {
44
44
substitution,
45
45
known_true : true ,
46
46
result : ( ) ,
47
47
} ;
48
- c . assert_valid ( ) ;
49
- c
48
+ c2 . assert_valid ( ) ;
49
+ c2
50
50
}
51
51
}
52
52
@@ -72,110 +72,88 @@ impl<R: Term> Constraints<R> {
72
72
}
73
73
}
74
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) ;
75
+ /// Given constraings from solving the subparts of `(A /\ B)`, yield combined constraints.
76
+ ///
77
+ /// # Parameters
78
+ ///
79
+ /// * `self` -- the constraints from solving `A`
80
+ /// * `c2` -- the constraints from solving `B` (after applying substitution from `self` to `B`)
81
+ pub fn seq < R2 : Term > ( & self , c2 : impl Upcast < Constraints < R2 > > ) -> Constraints < R2 >
82
+ where
83
+ R : CombineResults < R2 > ,
84
+ {
85
+ let c2: Constraints < R2 > = c2. upcast ( ) ;
86
+
87
+ self . assert_valid ( ) ;
88
+ c2. assert_valid ( ) ;
89
+
90
+ // This substitution should have already been applied to produce
91
+ // `c2`, therefore we don't expect any bindings for *our* variables.
92
+ assert ! ( self
93
+ . substitution
94
+ . domain( )
95
+ . is_disjoint( & c2. substitution. domain( ) ) ) ;
96
+
97
+ // Similarly, we don't expect any references to variables that we have
98
+ // defined.
99
+ assert ! ( self
100
+ . substitution
101
+ . domain( )
102
+ . iter( )
103
+ . all( |v| !occurs_in( v, & c2. substitution) ) ) ;
104
+
105
+ // Apply c2's substitution to our substitution (since it may have bound
106
+ // existential variables that we reference)
107
+ let c1_substitution = c2. substitution . apply ( & self . substitution ) ;
108
+
82
109
Constraints {
83
- known_true,
84
- substitution ,
85
- result ,
110
+ known_true : self . known_true && c2 . known_true ,
111
+ result : R :: combine ( & self . result , c2 . result ) ,
112
+ substitution : c1_substitution . into_iter ( ) . chain ( c2 . substitution ) . collect ( ) ,
86
113
}
87
114
}
88
115
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
- }
104
- }
116
+ pub fn assert_valid_in ( & self , env : & Env ) {
117
+ self . assert_valid ( ) ;
105
118
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
- }
119
+ // Each variable `x` is only bound to a term of strictly lower universe.
120
+ // This implies that `x` does not appear in `p`.
121
+ for ( x, p) in self . substitution . iter ( ) {
122
+ let fvs = p. free_variables ( ) ;
123
+ fvs. iter ( )
124
+ . for_each ( |fv| assert ! ( env. universe( fv) < env. universe( x) ) ) ;
125
+ }
126
+ }
115
127
116
- pub fn merge_constraints < R0 : Term , R1 : Term > (
117
- existentials : impl Upcast < Vec < Variable > > ,
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 ( ) ;
125
- c0. assert_valid ( ) ;
126
-
127
- let ( c1_bound_vars, c1) = c1. open ( ) ;
128
- c1. assert_valid ( ) ;
129
-
130
- assert ! ( c0
131
- . substitution
132
- . domain( )
133
- . is_disjoint( & c1. substitution. domain( ) ) ) ;
134
- assert ! ( !c0
135
- . substitution
136
- . domain( )
137
- . iter( )
138
- . any( |v| occurs_in( v, & c1. substitution) ) ) ;
139
-
140
- let existentials: Vec < Variable > = existentials. upcast ( ) ;
141
-
142
- let c0 = c1. substitution . apply ( & c0) ;
143
-
144
- // Drop any bindings `X := P` from the subst that appear in the `variables` set;
145
- // those are existentials that we temporarily introduced and no longer need.
146
- let substitution = c0
147
- . substitution
148
- . into_iter ( )
149
- . chain ( c1. substitution )
150
- . filter ( |( v, _) | !existentials. contains ( & v. upcast ( ) ) )
151
- . collect ( ) ;
128
+ pub fn pop_subst < V > ( mut self , mut env : Env , v : & [ V ] ) -> ( Env , Constraints < R > )
129
+ where
130
+ V : Upcast < Variable > + Copy ,
131
+ {
132
+ self . assert_valid_in ( & env) ;
152
133
153
- let known_true = c0. known_true && c1. known_true ;
134
+ if v. len ( ) == 0 {
135
+ return ( env, self ) ;
136
+ }
154
137
155
- let result = R0 :: combine ( c0. result , c1. result ) ;
138
+ let vars = env. pop_vars ( v) ;
139
+ self . substitution -= vars;
156
140
157
- Binder :: mentioned (
158
- ( c1_bound_vars, existentials) ,
159
- Constraints {
160
- known_true,
161
- substitution,
162
- result,
163
- } ,
164
- )
141
+ ( env, self )
142
+ }
165
143
}
166
144
167
145
impl < R : Term > Fold for Constraints < R > {
168
146
fn substitute ( & self , substitution_fn : formality_types:: fold:: SubstitutionFn < ' _ > ) -> Self {
169
- let c = Constraints {
147
+ let c2 = Constraints {
170
148
known_true : self . known_true ,
171
149
substitution : self . substitution . substitute ( substitution_fn) ,
172
150
result : self . result . substitute ( substitution_fn) ,
173
151
} ;
174
152
175
153
// not all substitutions preserve the constraint set invariant
176
- c . assert_valid ( ) ;
154
+ c2 . assert_valid ( ) ;
177
155
178
- c
156
+ c2
179
157
}
180
158
}
181
159
@@ -244,33 +222,27 @@ pub fn is_valid_binding(v: impl Upcast<Variable>, t: &impl Visit) -> bool {
244
222
. all ( |fv| fv != v && fv. max_universe ( ) <= v_universe)
245
223
}
246
224
247
- pub fn constrain ( v : impl Upcast < InferenceVar > , p : impl Upcast < Parameter > ) -> Binder < Constraints > {
248
- let v: InferenceVar = v. upcast ( ) ;
249
- let p: Parameter = p. upcast ( ) ;
250
- Binder :: dummy ( ( v, p) . upcast ( ) )
251
- }
252
-
253
- pub fn no_constraints < R : Term > ( result : R ) -> Binder < Constraints < R > > {
254
- Binder :: dummy ( Constraints {
255
- result,
225
+ pub fn no_constraints ( ) -> Constraints {
226
+ Constraints {
227
+ result : ( ) ,
256
228
known_true : true ,
257
229
substitution : Substitution :: default ( ) ,
258
- } )
230
+ }
259
231
}
260
232
261
233
pub trait CombineResults < R > {
262
- fn combine ( r0 : Self , r1 : R ) -> R ;
234
+ fn combine ( r0 : & Self , r1 : R ) -> R ;
263
235
}
264
236
265
237
impl < R > CombineResults < R > for ( ) {
266
- fn combine ( ( ) : ( ) , r1 : R ) -> R {
238
+ fn combine ( ( ) : & ( ) , r1 : R ) -> R {
267
239
r1
268
240
}
269
241
}
270
242
271
243
impl CombineResults < Vec < Parameter > > for Parameter {
272
- fn combine ( r0 : Self , mut r1 : Vec < Parameter > ) -> Vec < Parameter > {
273
- r1. push ( r0) ;
244
+ fn combine ( r0 : & Self , mut r1 : Vec < Parameter > ) -> Vec < Parameter > {
245
+ r1. push ( r0. clone ( ) ) ;
274
246
r1
275
247
}
276
248
}
0 commit comments