@@ -42,8 +42,7 @@ use super::{MiscVariable, TypeTrace};
4242use ty:: { IntType , UintType } ;
4343use ty:: { self , Ty , TyCtxt } ;
4444use ty:: error:: TypeError ;
45- use ty:: fold:: TypeFoldable ;
46- use ty:: relate:: { RelateResult , TypeRelation } ;
45+ use ty:: relate:: { self , Relate , RelateResult , TypeRelation } ;
4746use traits:: PredicateObligations ;
4847
4948use syntax:: ast;
@@ -207,7 +206,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
207206 // `'?2` and `?3` are fresh region/type inference
208207 // variables. (Down below, we will relate `a_ty <: b_ty`,
209208 // adding constraints like `'x: '?2` and `?1 <: ?3`.)
210- let b_ty = self . generalize ( a_ty, b_vid, dir == EqTo ) ?;
209+ let b_ty = self . generalize ( a_ty, b_vid, dir) ?;
211210 debug ! ( "instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})" ,
212211 a_ty, dir, b_vid, b_ty) ;
213212 self . infcx . type_variables . borrow_mut ( ) . instantiate ( b_vid, b_ty) ;
@@ -241,39 +240,77 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
241240 fn generalize ( & self ,
242241 ty : Ty < ' tcx > ,
243242 for_vid : ty:: TyVid ,
244- is_eq_relation : bool )
243+ dir : RelationDir )
245244 -> RelateResult < ' tcx , Ty < ' tcx > >
246245 {
246+ // Determine the ambient variance within which `ty` appears.
247+ // The surrounding equation is:
248+ //
249+ // ty [op] ty2
250+ //
251+ // where `op` is either `==`, `<:`, or `:>`. This maps quite
252+ // naturally.
253+ let ambient_variance = match dir {
254+ RelationDir :: EqTo => ty:: Invariant ,
255+ RelationDir :: SubtypeOf => ty:: Covariant ,
256+ RelationDir :: SupertypeOf => ty:: Contravariant ,
257+ } ;
258+
247259 let mut generalize = Generalizer {
248260 infcx : self . infcx ,
249261 span : self . trace . cause . span ,
250262 for_vid_sub_root : self . infcx . type_variables . borrow_mut ( ) . sub_root_var ( for_vid) ,
251- is_eq_relation : is_eq_relation,
252- cycle_detected : false
263+ ambient_variance : ambient_variance,
253264 } ;
254- let u = ty. fold_with ( & mut generalize) ;
255- if generalize. cycle_detected {
256- Err ( TypeError :: CyclicTy )
257- } else {
258- Ok ( u)
259- }
265+
266+ generalize. relate ( & ty, & ty)
260267 }
261268}
262269
263270struct Generalizer < ' cx , ' gcx : ' cx +' tcx , ' tcx : ' cx > {
264271 infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
265272 span : Span ,
266273 for_vid_sub_root : ty:: TyVid ,
267- is_eq_relation : bool ,
268- cycle_detected : bool ,
274+ ambient_variance : ty:: Variance ,
269275}
270276
271- impl < ' cx , ' gcx , ' tcx > ty :: fold :: TypeFolder < ' gcx , ' tcx > for Generalizer < ' cx , ' gcx , ' tcx > {
272- fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' a , ' gcx , ' tcx > {
277+ impl < ' cx , ' gcx , ' tcx > TypeRelation < ' cx , ' gcx , ' tcx > for Generalizer < ' cx , ' gcx , ' tcx > {
278+ fn tcx ( & self ) -> TyCtxt < ' cx , ' gcx , ' tcx > {
273279 self . infcx . tcx
274280 }
275281
276- fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
282+ fn tag ( & self ) -> & ' static str {
283+ "Generalizer"
284+ }
285+
286+ fn a_is_expected ( & self ) -> bool {
287+ true
288+ }
289+
290+ fn binders < T > ( & mut self , a : & ty:: Binder < T > , b : & ty:: Binder < T > )
291+ -> RelateResult < ' tcx , ty:: Binder < T > >
292+ where T : Relate < ' tcx >
293+ {
294+ Ok ( ty:: Binder ( self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?) )
295+ }
296+
297+ fn relate_with_variance < T : Relate < ' tcx > > ( & mut self ,
298+ variance : ty:: Variance ,
299+ a : & T ,
300+ b : & T )
301+ -> RelateResult < ' tcx , T >
302+ {
303+ let old_ambient_variance = self . ambient_variance ;
304+ self . ambient_variance = self . ambient_variance . xform ( variance) ;
305+
306+ let result = self . relate ( a, b) ;
307+ self . ambient_variance = old_ambient_variance;
308+ result
309+ }
310+
311+ fn tys ( & mut self , t : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
312+ assert_eq ! ( t, t2) ; // we are abusing TypeRelation here; both LHS and RHS ought to be ==
313+
277314 // Check to see whether the type we are genealizing references
278315 // any other type variable related to `vid` via
279316 // subtyping. This is basically our "occurs check", preventing
@@ -286,41 +323,54 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
286323 if sub_vid == self . for_vid_sub_root {
287324 // If sub-roots are equal, then `for_vid` and
288325 // `vid` are related via subtyping.
289- self . cycle_detected = true ;
290- self . tcx ( ) . types . err
326+ return Err ( TypeError :: CyclicTy ) ;
291327 } else {
292328 match variables. probe_root ( vid) {
293329 Some ( u) => {
294330 drop ( variables) ;
295- self . fold_ty ( u)
331+ self . relate ( & u , & u)
296332 }
297333 None => {
298- if !self . is_eq_relation {
299- let origin = variables. origin ( vid) ;
300- let new_var_id = variables. new_var ( false , origin, None ) ;
301- let u = self . tcx ( ) . mk_var ( new_var_id) ;
302- debug ! ( "generalize: replacing original vid={:?} with new={:?}" ,
303- vid, u) ;
304- u
305- } else {
306- t
334+ match self . ambient_variance {
335+ ty:: Invariant => Ok ( t) ,
336+
337+ ty:: Bivariant | ty:: Covariant | ty:: Contravariant => {
338+ let origin = variables. origin ( vid) ;
339+ let new_var_id = variables. new_var ( false , origin, None ) ;
340+ let u = self . tcx ( ) . mk_var ( new_var_id) ;
341+ debug ! ( "generalize: replacing original vid={:?} with new={:?}" ,
342+ vid, u) ;
343+ Ok ( u)
344+ }
307345 }
308346 }
309347 }
310348 }
311349 }
350+ ty:: TyInfer ( ty:: IntVar ( _) ) |
351+ ty:: TyInfer ( ty:: FloatVar ( _) ) => {
352+ // No matter what mode we are in,
353+ // integer/floating-point types must be equal to be
354+ // relatable.
355+ Ok ( t)
356+ }
312357 _ => {
313- t . super_fold_with ( self )
358+ relate :: super_relate_tys ( self , t , t )
314359 }
315360 }
316361 }
317362
318- fn fold_region ( & mut self , r : & ' tcx ty:: Region ) -> & ' tcx ty:: Region {
363+ fn regions ( & mut self , r : & ' tcx ty:: Region , r2 : & ' tcx ty:: Region )
364+ -> RelateResult < ' tcx , & ' tcx ty:: Region > {
365+ assert_eq ! ( r, r2) ; // we are abusing TypeRelation here; both LHS and RHS ought to be ==
366+
319367 match * r {
320368 // Never make variables for regions bound within the type itself,
321369 // nor for erased regions.
322370 ty:: ReLateBound ( ..) |
323- ty:: ReErased => { return r; }
371+ ty:: ReErased => {
372+ return Ok ( r) ;
373+ }
324374
325375 // Early-bound regions should really have been substituted away before
326376 // we get to this point.
@@ -342,15 +392,16 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
342392 ty:: ReScope ( ..) |
343393 ty:: ReVar ( ..) |
344394 ty:: ReFree ( ..) => {
345- if self . is_eq_relation {
346- return r;
395+ match self . ambient_variance {
396+ ty:: Invariant => return Ok ( r) ,
397+ ty:: Bivariant | ty:: Covariant | ty:: Contravariant => ( ) ,
347398 }
348399 }
349400 }
350401
351402 // FIXME: This is non-ideal because we don't give a
352403 // very descriptive origin for this region variable.
353- self . infcx . next_region_var ( MiscVariable ( self . span ) )
404+ Ok ( self . infcx . next_region_var ( MiscVariable ( self . span ) ) )
354405 }
355406}
356407
0 commit comments