@@ -458,19 +458,30 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
458
458
self . b_scopes . push ( b_scope) ;
459
459
self . a_scopes . push ( a_scope) ;
460
460
461
- // FIXME -- to be fully correct, we would set the ambient
462
- // variance to Covariant here. As is, we will sometimes
463
- // propagate down an ambient variance of Equal -- this in
464
- // turn causes us to report errors in some cases where
465
- // types perhaps *ought* to be equal. See the
466
- // `hr-fn-aau-eq-abu.rs` test for an example. Fixing this
467
- // though is a bit nontrivial: in particular, it would
468
- // require a more involved handling of canonical
469
- // variables, since we would no longer be able to rely on
470
- // having an `==` relationship for canonical variables.
461
+ // Reset the ambient variance to covariant. This is needed
462
+ // to correctly handle cases like
463
+ //
464
+ // for<'a> fn(&'a u32, &'a u3) == for<'b, 'c> fn(&'b u32, &'c u32)
465
+ //
466
+ // Somewhat surprisingly, these two types are actually
467
+ // **equal**, even though the one on the right looks more
468
+ // polymorphic. The reason is due to subtyping. To see it,
469
+ // consider that each function can call the other:
470
+ //
471
+ // - The left function can call the right with `'b` and
472
+ // `'c` both equal to `'a`
473
+ //
474
+ // - The right function can call the left with `'a` set to
475
+ // `{P}`, where P is the point in the CFG where the call
476
+ // itself occurs. Note that `'b` and `'c` must both
477
+ // include P. At the point, the call works because of
478
+ // subtyping (i.e., `&'b u32 <: &{P} u32`).
479
+ let variance = :: std:: mem:: replace ( & mut self . ambient_variance , ty:: Variance :: Covariant ) ;
471
480
472
481
self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?;
473
482
483
+ self . ambient_variance = variance;
484
+
474
485
self . b_scopes . pop ( ) . unwrap ( ) ;
475
486
self . a_scopes . pop ( ) . unwrap ( ) ;
476
487
}
@@ -491,8 +502,14 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
491
502
self . a_scopes . push ( a_scope) ;
492
503
self . b_scopes . push ( b_scope) ;
493
504
505
+ // Reset ambient variance to contravariance. See the
506
+ // covariant case above for an explanation.
507
+ let variance = :: std:: mem:: replace ( & mut self . ambient_variance , ty:: Variance :: Contravariant ) ;
508
+
494
509
self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?;
495
510
511
+ self . ambient_variance = variance;
512
+
496
513
self . b_scopes . pop ( ) . unwrap ( ) ;
497
514
self . a_scopes . pop ( ) . unwrap ( ) ;
498
515
}
0 commit comments