about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-10-27 14:03:25 -0400
committerNiko Matsakis <niko@alum.mit.edu>2014-10-31 17:39:41 -0400
commit9a5e7ba4c7eefb2f40389966c562fbadcc778625 (patch)
tree220c90e9520b9444375a18a2a57ab8c7b1dc1219
parent5e834243b6837a2386d623e1d546a3d25057b8f5 (diff)
Teach variance checker about the lifetime bounds that appear in trait object types.
-rw-r--r--src/librustc/middle/typeck/variance.rs6
-rw-r--r--src/test/compile-fail/variance-trait-object-bound.rs26
-rw-r--r--src/test/run-pass/issue-16668.rs2
3 files changed, 32 insertions, 2 deletions
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 5e62a8e9451..9a90381854a 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -778,7 +778,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     variance);
             }
 
-            ty::ty_trait(box ty::TyTrait { def_id, ref substs, .. }) => {
+            ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => {
                 let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
                 let generics = &trait_def.generics;
 
@@ -796,6 +796,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 assert!(generics.types.is_empty_in(subst::FnSpace));
                 assert!(generics.regions.is_empty_in(subst::FnSpace));
 
+                // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
+                let contra = self.contravariant(variance);
+                self.add_constraints_from_region(bounds.region_bound, contra);
+
                 self.add_constraints_from_substs(
                     def_id,
                     generics.types.get_slice(subst::TypeSpace),
diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs
new file mode 100644
index 00000000000..c61f2ff79c0
--- /dev/null
+++ b/src/test/compile-fail/variance-trait-object-bound.rs
@@ -0,0 +1,26 @@
+// 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.
+
+// Checks that regions which appear in a trait object type are
+// observed by the variance inference algorithm (and hence
+// `TOption` is contavariant w/r/t `'a` and not bivariant).
+//
+// Issue #18262.
+
+use std::mem;
+
+trait T { fn foo(); }
+
+#[rustc_variance]
+struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
+    v: Option<Box<T + 'a>>,
+}
+
+fn main() { }
diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs
index b66fb4306d0..92f8030a0dc 100644
--- a/src/test/run-pass/issue-16668.rs
+++ b/src/test/run-pass/issue-16668.rs
@@ -17,7 +17,7 @@ struct Parser<'a, I, O> {
 }
 
 impl<'a, I, O: 'a> Parser<'a, I, O> {
-    fn compose<K: 'a>(mut self, mut rhs: Parser<O, K>) -> Parser<'a, I, K> {
+    fn compose<K: 'a>(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> {
         Parser {
             parse: box move |&mut: x: I| {
                 match self.parse.call_mut((x,)) {