Drive-by fix for incorrect variance rule that I noticed.

This commit is contained in:
Niko Matsakis 2015-03-25 10:42:38 -04:00
parent 9c9bb9ce1d
commit c59fe8bde2
2 changed files with 46 additions and 3 deletions

View File

@ -1059,14 +1059,29 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
ty::Predicate::Equate(ty::Binder(ref data)) => {
self.add_constraints_from_ty(generics, data.0, variance);
self.add_constraints_from_ty(generics, data.1, variance);
// A == B is only true if A and B are the same
// types, not subtypes of one another, so this is
// an invariant position:
self.add_constraints_from_ty(generics, data.0, self.invariant);
self.add_constraints_from_ty(generics, data.1, self.invariant);
}
ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
self.add_constraints_from_ty(generics, data.0, variance);
// Why contravariant on both? Let's consider:
//
// Under what conditions is `(T:'t) <: (U:'u)`,
// meaning that `(T:'t) => (U:'u)`. The answer is
// if `U <: T` or `'u <= 't`. Let's see some examples:
//
// (T: 'big) => (T: 'small)
// where 'small <= 'big
//
// (&'small Foo: 't) => (&'big Foo: 't)
// where 'small <= 'big
// note that &'big Foo <: &'small Foo
let variance_r = self.xform(variance, self.contravariant);
self.add_constraints_from_ty(generics, data.0, variance_r);
self.add_constraints_from_region(generics, data.1, variance_r);
}
@ -1084,6 +1099,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
&*data.projection_ty.trait_ref,
variance);
// as the equality predicate above, a binder is a
// type equality relation, not a subtyping
// relation
self.add_constraints_from_ty(generics, data.ty, self.invariant);
}
}

View File

@ -0,0 +1,25 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that `T:'a` is contravariant in T.
#![feature(rustc_attrs)]
#[rustc_variance]
trait Foo: 'static { //~ ERROR types=[[];[-];[]]
}
#[rustc_variance]
trait Bar<T> { //~ ERROR types=[[+];[-];[]]
fn do_it(&self)
where T: 'static;
}
fn main() { }