Skip to content

Commit c59fe8b

Browse files
committed
Drive-by fix for incorrect variance rule that I noticed.
1 parent 9c9bb9c commit c59fe8b

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

src/librustc_typeck/variance.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,14 +1059,29 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
10591059
}
10601060

10611061
ty::Predicate::Equate(ty::Binder(ref data)) => {
1062-
self.add_constraints_from_ty(generics, data.0, variance);
1063-
self.add_constraints_from_ty(generics, data.1, variance);
1062+
// A == B is only true if A and B are the same
1063+
// types, not subtypes of one another, so this is
1064+
// an invariant position:
1065+
self.add_constraints_from_ty(generics, data.0, self.invariant);
1066+
self.add_constraints_from_ty(generics, data.1, self.invariant);
10641067
}
10651068

10661069
ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
1067-
self.add_constraints_from_ty(generics, data.0, variance);
1070+
// Why contravariant on both? Let's consider:
1071+
//
1072+
// Under what conditions is `(T:'t) <: (U:'u)`,
1073+
// meaning that `(T:'t) => (U:'u)`. The answer is
1074+
// if `U <: T` or `'u <= 't`. Let's see some examples:
1075+
//
1076+
// (T: 'big) => (T: 'small)
1077+
// where 'small <= 'big
1078+
//
1079+
// (&'small Foo: 't) => (&'big Foo: 't)
1080+
// where 'small <= 'big
1081+
// note that &'big Foo <: &'small Foo
10681082

10691083
let variance_r = self.xform(variance, self.contravariant);
1084+
self.add_constraints_from_ty(generics, data.0, variance_r);
10701085
self.add_constraints_from_region(generics, data.1, variance_r);
10711086
}
10721087

@@ -1084,6 +1099,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
10841099
&*data.projection_ty.trait_ref,
10851100
variance);
10861101

1102+
// as the equality predicate above, a binder is a
1103+
// type equality relation, not a subtyping
1104+
// relation
10871105
self.add_constraints_from_ty(generics, data.ty, self.invariant);
10881106
}
10891107
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that `T:'a` is contravariant in T.
12+
13+
#![feature(rustc_attrs)]
14+
15+
#[rustc_variance]
16+
trait Foo: 'static { //~ ERROR types=[[];[-];[]]
17+
}
18+
19+
#[rustc_variance]
20+
trait Bar<T> { //~ ERROR types=[[+];[-];[]]
21+
fn do_it(&self)
22+
where T: 'static;
23+
}
24+
25+
fn main() { }

0 commit comments

Comments
 (0)