@@ -105,6 +105,8 @@ impl<'t> Unifier<'t> {
105
105
) ;
106
106
107
107
match ( a, b) {
108
+ // Unifying two inference variables: unify them in the underlying
109
+ // ena table.
108
110
( & Ty :: InferenceVar ( var1) , & Ty :: InferenceVar ( var2) ) => {
109
111
debug ! ( "unify_ty_ty: unify_var_var({:?}, {:?})" , var1, var2) ;
110
112
let var1 = EnaVariable :: from ( var1) ;
@@ -116,35 +118,71 @@ impl<'t> Unifier<'t> {
116
118
. expect ( "unification of two unbound variables cannot fail" ) )
117
119
}
118
120
121
+ // Unifying an inference variables with a non-inference variable.
119
122
( & Ty :: InferenceVar ( var) , ty @ & Ty :: Apply ( _) )
120
123
| ( ty @ & Ty :: Apply ( _) , & Ty :: InferenceVar ( var) )
124
+ | ( & Ty :: InferenceVar ( var) , ty @ & Ty :: Opaque ( _) )
125
+ | ( ty @ Ty :: Opaque ( _) , & Ty :: InferenceVar ( var) )
126
+ | ( & Ty :: InferenceVar ( var) , ty @ & Ty :: Dyn ( _) )
127
+ | ( ty @ & Ty :: Dyn ( _) , & Ty :: InferenceVar ( var) )
121
128
| ( & Ty :: InferenceVar ( var) , ty @ & Ty :: ForAll ( _) )
122
129
| ( ty @ & Ty :: ForAll ( _) , & Ty :: InferenceVar ( var) ) => self . unify_var_ty ( var, ty) ,
123
130
131
+ // Unifying `forall<X> { T }` with some other forall type `forall<X> { U }`
124
132
( & Ty :: ForAll ( ref quantified_ty1) , & Ty :: ForAll ( ref quantified_ty2) ) => {
125
133
self . unify_forall_tys ( quantified_ty1, quantified_ty2)
126
134
}
127
135
128
- ( & Ty :: ForAll ( ref quantified_ty) , apply_ty @ & Ty :: Apply ( _) )
129
- | ( apply_ty @ & Ty :: Apply ( _) , & Ty :: ForAll ( ref quantified_ty) ) => {
130
- self . unify_forall_apply ( quantified_ty, apply_ty)
136
+ // Unifying `forall<X> { T }` with some other type `U`
137
+ ( & Ty :: ForAll ( ref quantified_ty) , other_ty @ & Ty :: Apply ( _) )
138
+ | ( & Ty :: ForAll ( ref quantified_ty) , other_ty @ & Ty :: Dyn ( _) )
139
+ | ( & Ty :: ForAll ( ref quantified_ty) , other_ty @ & Ty :: Opaque ( _) )
140
+ | ( other_ty @ & Ty :: Apply ( _) , & Ty :: ForAll ( ref quantified_ty) )
141
+ | ( other_ty @ & Ty :: Dyn ( _) , & Ty :: ForAll ( ref quantified_ty) )
142
+ | ( other_ty @ & Ty :: Opaque ( _) , & Ty :: ForAll ( ref quantified_ty) ) => {
143
+ self . unify_forall_other ( quantified_ty, other_ty)
131
144
}
132
145
133
146
( & Ty :: Apply ( ref apply1) , & Ty :: Apply ( ref apply2) ) => {
147
+ // Cannot unify (e.g.) some struct type `Foo` and some struct type `Bar`
134
148
if apply1. name != apply2. name {
135
149
return Err ( NoSolution ) ;
136
150
}
137
151
138
152
Zip :: zip_with ( self , & apply1. parameters , & apply2. parameters )
139
153
}
140
154
155
+ // Cannot unify (e.g.) some struct type `Foo` and an `impl Trait` type
156
+ ( & Ty :: Apply ( _) , & Ty :: Opaque ( _) ) | ( & Ty :: Opaque ( _) , & Ty :: Apply ( _) ) => {
157
+ return Err ( NoSolution ) ;
158
+ }
159
+
160
+ // Cannot unify (e.g.) some struct type `Foo` and a `dyn Trait` type
161
+ ( & Ty :: Apply ( _) , & Ty :: Dyn ( _) ) | ( & Ty :: Dyn ( _) , & Ty :: Apply ( _) ) => {
162
+ return Err ( NoSolution ) ;
163
+ }
164
+
165
+ // Cannot unify (e.g.) some `dyn Trait` and some `impl Trait` type
166
+ ( & Ty :: Dyn ( ..) , & Ty :: Opaque ( ..) ) | ( & Ty :: Opaque ( ..) , & Ty :: Dyn ( ..) ) => {
167
+ return Err ( NoSolution ) ;
168
+ }
169
+
170
+ ( & Ty :: Opaque ( ref qwc1) , & Ty :: Opaque ( ref qwc2) )
171
+ | ( & Ty :: Dyn ( ref qwc1) , & Ty :: Dyn ( ref qwc2) ) => Zip :: zip_with ( self , qwc1, qwc2) ,
172
+
173
+ // Unifying an associated type projection `<T as
174
+ // Trait>::Item` with some other type `U`.
141
175
( ty @ & Ty :: Apply ( _) , & Ty :: Projection ( ref proj) )
142
176
| ( ty @ & Ty :: ForAll ( _) , & Ty :: Projection ( ref proj) )
143
177
| ( ty @ & Ty :: InferenceVar ( _) , & Ty :: Projection ( ref proj) )
178
+ | ( ty @ & Ty :: Dyn ( _) , & Ty :: Projection ( ref proj) )
179
+ | ( ty @ & Ty :: Opaque ( _) , & Ty :: Projection ( ref proj) )
144
180
| ( & Ty :: Projection ( ref proj) , ty @ & Ty :: Projection ( _) )
145
181
| ( & Ty :: Projection ( ref proj) , ty @ & Ty :: Apply ( _) )
146
182
| ( & Ty :: Projection ( ref proj) , ty @ & Ty :: ForAll ( _) )
147
- | ( & Ty :: Projection ( ref proj) , ty @ & Ty :: InferenceVar ( _) ) => {
183
+ | ( & Ty :: Projection ( ref proj) , ty @ & Ty :: InferenceVar ( _) )
184
+ | ( & Ty :: Projection ( ref proj) , ty @ & Ty :: Dyn ( _) )
185
+ | ( & Ty :: Projection ( ref proj) , ty @ & Ty :: Opaque ( _) ) => {
148
186
self . unify_projection_ty ( proj, ty)
149
187
}
150
188
@@ -186,6 +224,12 @@ impl<'t> Unifier<'t> {
186
224
self . sub_unify ( ty1, ty2)
187
225
}
188
226
227
+ /// Unify an associated type projection `proj` like `<T as Trait>::Item` with some other
228
+ /// type `ty` (which might also be a projection). Creates a goal like
229
+ ///
230
+ /// ```notrust
231
+ /// ProjectionEq(<T as Trait>::Item = U)
232
+ /// ```
189
233
fn unify_projection_ty ( & mut self , proj : & ProjectionTy , ty : & Ty ) -> Fallible < ( ) > {
190
234
Ok ( self . goals . push ( InEnvironment :: new (
191
235
self . environment ,
@@ -197,7 +241,11 @@ impl<'t> Unifier<'t> {
197
241
) ) )
198
242
}
199
243
200
- fn unify_forall_apply ( & mut self , ty1 : & QuantifiedTy , ty2 : & Ty ) -> Fallible < ( ) > {
244
+ /// Unifying `forall<X> { T }` with some other type `U` --
245
+ /// to do so, we create a fresh placeholder `P` for `X` and
246
+ /// see if `[X/Px] T` can be unified with `U`. This should
247
+ /// almost never be true, actually, unless `X` is unused.
248
+ fn unify_forall_other ( & mut self , ty1 : & QuantifiedTy , ty2 : & Ty ) -> Fallible < ( ) > {
201
249
let ui = self . table . new_universe ( ) ;
202
250
let lifetimes1: Vec < _ > = ( 0 ..ty1. num_binders )
203
251
. map ( |idx| Lifetime :: Placeholder ( PlaceholderIndex { ui, idx } ) . cast ( ) )
@@ -209,6 +257,12 @@ impl<'t> Unifier<'t> {
209
257
self . sub_unify ( ty1, ty2)
210
258
}
211
259
260
+ /// Unify an inference variable `var` with some non-inference
261
+ /// variable `ty`, just bind `var` to `ty`. But we must enforce two conditions:
262
+ ///
263
+ /// - `var` does not appear inside of `ty` (the standard `OccursCheck`)
264
+ /// - `ty` does not reference anything in a lifetime that could not be named in `var`
265
+ /// (the extended `OccursCheck` created to handle universes)
212
266
fn unify_var_ty ( & mut self , var : InferenceVar , ty : & Ty ) -> Fallible < ( ) > {
213
267
debug ! ( "unify_var_ty(var={:?}, ty={:?})" , var, ty) ;
214
268
0 commit comments