Skip to content

Commit 34575e6

Browse files
committed
now that we can handle subtyping, fix higher-ranked equality
1 parent 07e21b1 commit 34575e6

File tree

3 files changed

+28
-22
lines changed

3 files changed

+28
-22
lines changed

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -458,19 +458,30 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
458458
self.b_scopes.push(b_scope);
459459
self.a_scopes.push(a_scope);
460460

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);
471480

472481
self.relate(a.skip_binder(), b.skip_binder())?;
473482

483+
self.ambient_variance = variance;
484+
474485
self.b_scopes.pop().unwrap();
475486
self.a_scopes.pop().unwrap();
476487
}
@@ -491,8 +502,14 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
491502
self.a_scopes.push(a_scope);
492503
self.b_scopes.push(b_scope);
493504

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+
494509
self.relate(a.skip_binder(), b.skip_binder())?;
495510

511+
self.ambient_variance = variance;
512+
496513
self.b_scopes.pop().unwrap();
497514
self.a_scopes.pop().unwrap();
498515
}

src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616
// another -- effectively, the single lifetime `'a` is just inferred
1717
// to be the intersection of the two distinct lifetimes.
1818
//
19-
// FIXME: However, we currently reject this example with an error,
20-
// because of how we handle binders and equality in `relate_tys`.
21-
//
19+
// compile-pass
2220
// compile-flags:-Zno-leak-check
2321

2422
#![feature(nll)]
@@ -31,7 +29,6 @@ fn make_cell_aa() -> Cell<for<'a> fn(&'a u32, &'a u32)> {
3129

3230
fn aa_eq_ab() {
3331
let a: Cell<for<'a, 'b> fn(&'a u32, &'b u32)> = make_cell_aa();
34-
//~^ ERROR higher-ranked subtype error
3532
drop(a);
3633
}
3734

src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)