@@ -2,7 +2,6 @@ use formality_types::{
2
2
cast:: { Downcast , Upcast } ,
3
3
cast_impl,
4
4
derive_links:: UpcastFrom ,
5
- fold:: Fold ,
6
5
grammar:: { InferenceVar , Parameter , Substitution , Variable } ,
7
6
visit:: Visit ,
8
7
} ;
@@ -11,51 +10,49 @@ use super::env::Env;
11
10
12
11
#[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Debug , Hash ) ]
13
12
pub struct Constraints {
13
+ env : Env ,
14
14
known_true : bool ,
15
15
substitution : Substitution ,
16
16
}
17
17
18
18
cast_impl ! ( Constraints ) ;
19
19
20
- impl < A , B > UpcastFrom < ( A , B ) > for Constraints
20
+ impl < A , B > UpcastFrom < ( Env , ( A , B ) ) > for Constraints
21
21
where
22
22
A : Upcast < Variable > ,
23
23
B : Upcast < Parameter > ,
24
24
{
25
- fn upcast_from ( term : ( A , B ) ) -> Self {
26
- Constraints {
27
- substitution : term. upcast ( ) ,
28
- known_true : true ,
29
- }
25
+ fn upcast_from ( ( env, pair) : ( Env , ( A , B ) ) ) -> Self {
26
+ Constraints :: from ( env, std:: iter:: once ( pair) )
30
27
}
31
28
}
32
29
33
- impl < A , B > FromIterator < ( A , B ) > for Constraints
34
- where
35
- A : Upcast < Variable > ,
36
- B : Upcast < Parameter > ,
37
- {
38
- fn from_iter < T : IntoIterator < Item = ( A , B ) > > ( iter : T ) -> Self {
39
- let substitution = iter. into_iter ( ) . collect ( ) ;
30
+ impl Constraints {
31
+ pub fn none ( env : Env ) -> Self {
32
+ let v: Vec < ( Variable , Parameter ) > = vec ! [ ] ;
33
+ Self :: from ( env, v)
34
+ }
35
+
36
+ pub fn from (
37
+ env : Env ,
38
+ iter : impl IntoIterator < Item = ( impl Upcast < Variable > , impl Upcast < Parameter > ) > ,
39
+ ) -> Self {
40
+ let substitution: Substitution = iter. into_iter ( ) . collect ( ) ;
41
+ env. assert_encloses ( substitution. range ( ) ) ;
42
+ env. assert_encloses ( substitution. domain ( ) ) ;
40
43
let c2 = Constraints {
44
+ env,
41
45
substitution,
42
46
known_true : true ,
43
47
} ;
44
48
c2. assert_valid ( ) ;
45
49
c2
46
50
}
47
- }
48
51
49
- impl Default for Constraints {
50
- fn default ( ) -> Self {
51
- Self {
52
- known_true : true ,
53
- substitution : Default :: default ( ) ,
54
- }
52
+ pub fn env ( & self ) -> & Env {
53
+ & self . env
55
54
}
56
- }
57
55
58
- impl Constraints {
59
56
pub fn substitution ( & self ) -> & Substitution {
60
57
& self . substitution
61
58
}
@@ -78,6 +75,7 @@ impl Constraints {
78
75
79
76
self . assert_valid ( ) ;
80
77
c2. assert_valid ( ) ;
78
+ c2. assert_valid_extension_of ( & self . env ) ;
81
79
82
80
// This substitution should have already been applied to produce
83
81
// `c2`, therefore we don't expect any bindings for *our* variables.
@@ -99,114 +97,93 @@ impl Constraints {
99
97
let c1_substitution = c2. substitution . apply ( & self . substitution ) ;
100
98
101
99
Constraints {
100
+ env : c2. env ,
102
101
known_true : self . known_true && c2. known_true ,
103
102
substitution : c1_substitution. into_iter ( ) . chain ( c2. substitution ) . collect ( ) ,
104
103
}
105
104
}
106
105
107
- pub fn assert_valid_in ( & self , env : & Env ) {
108
- self . assert_valid ( ) ;
109
-
110
- // Each variable `x` is only bound to a term of strictly lower universe.
111
- // This implies that `x` does not appear in `p`.
112
- for ( x, p) in self . substitution . iter ( ) {
113
- let fvs = p. free_variables ( ) ;
114
- fvs. iter ( )
115
- . for_each ( |fv| assert ! ( env. universe( fv) < env. universe( x) ) ) ;
116
- }
117
- }
118
-
119
- pub fn pop_subst < V > ( mut self , mut env : Env , v : & [ V ] ) -> ( Env , Self )
106
+ pub fn pop_subst < V > ( mut self , v : & [ V ] ) -> Self
120
107
where
121
108
V : Upcast < Variable > + Copy ,
122
109
{
123
- self . assert_valid_in ( & env) ;
124
-
125
110
if v. len ( ) == 0 {
126
- return ( env , self ) ;
111
+ return self ;
127
112
}
128
113
129
- let vars = env. pop_vars ( v) ;
114
+ let vars = self . env . pop_vars ( v) ;
130
115
self . substitution -= vars;
131
116
132
- ( env , self )
117
+ self
133
118
}
134
- }
135
-
136
- impl Fold for Constraints {
137
- fn substitute ( & self , substitution_fn : formality_types:: fold:: SubstitutionFn < ' _ > ) -> Self {
138
- let c2 = Constraints {
139
- known_true : self . known_true ,
140
- substitution : self . substitution . substitute ( substitution_fn) ,
141
- } ;
142
119
143
- // not all substitutions preserve the constraint set invariant
144
- c2. assert_valid ( ) ;
145
-
146
- c2
120
+ pub fn assert_valid_extension_of ( & self , env0 : & Env ) {
121
+ self . env . assert_valid_extension_of ( env0)
147
122
}
148
123
}
149
124
150
125
impl Visit for Constraints {
151
126
fn free_variables ( & self ) -> Vec < Variable > {
152
127
let Constraints {
128
+ env,
153
129
known_true : _,
154
130
substitution,
155
131
} = self ;
156
132
157
- substitution. free_variables ( ) . into_iter ( ) . collect ( )
133
+ // Debatable if `env.free_variables()` should be considered
134
+ // free here, env kind of acts as a binder. Don't think it matters.
135
+
136
+ env. free_variables ( )
137
+ . into_iter ( )
138
+ . chain ( substitution. free_variables ( ) )
139
+ . collect ( )
158
140
}
159
141
160
142
fn size ( & self ) -> usize {
161
143
let Constraints {
144
+ env,
162
145
known_true : _,
163
146
substitution,
164
147
} = self ;
165
- substitution. size ( )
148
+ env . size ( ) + substitution. size ( )
166
149
}
167
150
168
151
fn assert_valid ( & self ) {
169
152
let Constraints {
153
+ env,
170
154
known_true : _,
171
155
substitution,
172
156
} = self ;
173
157
174
158
let domain = substitution. domain ( ) ;
159
+ let range = substitution. range ( ) ;
175
160
176
- for & v in & domain {
177
- assert ! ( v. downcast:: <InferenceVar >( ) . is_some( ) ) ;
178
- assert ! ( v. is_free( ) ) ;
179
- assert ! ( is_valid_binding( v, & substitution[ v] ) ) ;
180
- }
161
+ env. assert_encloses ( & domain) ;
162
+ env. assert_encloses ( & range) ;
181
163
182
- let range = substitution. range ( ) ;
164
+ // No variable in the domain appears in any part of the range;
165
+ // this prevents the obvious occurs check violations like `X = Vec<X>`
166
+ // but also indirect ones like `X = Vec<Y>, Y = X`; it also implies that
167
+ // the substitution has been fully applied, so we don't have `X = Vec<Y>, Y = u32`.
183
168
range
184
169
. iter ( )
185
- . for_each ( |t| assert ! ( domain. iter( ) . all( |& v| !occurs_in( v, t) ) ) ) ;
170
+ . for_each ( |p| assert ! ( domain. iter( ) . all( |& v| !occurs_in( v, p) ) ) ) ;
171
+
172
+ // Each variable `x` is only bound to a term of strictly lower universe.
173
+ // This implies that `x` does not appear in `p`.
174
+ for ( x, p) in substitution. iter ( ) {
175
+ assert ! ( x. is_a:: <InferenceVar >( ) ) ;
176
+
177
+ assert ! ( !occurs_in( x, & p) ) ;
178
+
179
+ let fvs = p. free_variables ( ) ;
180
+ fvs. iter ( )
181
+ . for_each ( |fv| assert ! ( env. universe( fv) < env. universe( x) ) ) ;
182
+ }
186
183
}
187
184
}
188
185
189
186
pub fn occurs_in ( v : impl Upcast < Variable > , t : & impl Visit ) -> bool {
190
187
let v: Variable = v. upcast ( ) ;
191
188
t. free_variables ( ) . contains ( & v)
192
189
}
193
-
194
- /// True if `t` would be a valid binding for `v`, meaning...
195
- /// * `v` does not appear in `t`; and,
196
- /// * all free variables in `t` are within the universe of `v`
197
- pub fn is_valid_binding ( v : impl Upcast < Variable > , t : & impl Visit ) -> bool {
198
- let v: Variable = v. upcast ( ) ;
199
- assert ! ( v. is_free( ) ) ;
200
-
201
- let v_universe = v. max_universe ( ) ;
202
- t. free_variables ( )
203
- . into_iter ( )
204
- . all ( |fv| fv != v && fv. max_universe ( ) <= v_universe)
205
- }
206
-
207
- pub fn no_constraints ( ) -> Constraints {
208
- Constraints {
209
- known_true : true ,
210
- substitution : Substitution :: default ( ) ,
211
- }
212
- }
0 commit comments