about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-18 15:12:11 +0000
committerbors <bors@rust-lang.org>2014-10-18 15:12:11 +0000
commitd670919aa43d186317a89a375f4a5b7170fc08a8 (patch)
treec4778d4047ff7d7822f56da5853009a1ca2fe604
parent41a79104a412989b802852f9ee6e589b06391d61 (diff)
parent7876cf9ca915724d1888043a9cbfedd45009e5f2 (diff)
downloadrust-d670919aa43d186317a89a375f4a5b7170fc08a8.tar.gz
rust-d670919aa43d186317a89a375f4a5b7170fc08a8.zip
auto merge of #18105 : nikomatsakis/rust/issue-18055, r=pcwalton
Check object lifetime bounds in coercions, not just trait bounds.  Fixes #18055.

r? @pcwalton 

This is a [breaking change]. Change code like this:

    fn foo(v: &[u8]) -> Box<Clone+'static> { ... }

to make the lifetimes agree:

    // either...
    fn foo(v: &'static[u8]) -> Box<Clone+'static> { box v }

    // or ...
    fn foo<'a>(v: &'a [u8]) -> Box<Clone+'a> { box v }
-rw-r--r--src/librustc/middle/typeck/check/mod.rs7
-rw-r--r--src/test/compile-fail/region-object-lifetime-in-coercion.rs35
2 files changed, 42 insertions, 0 deletions
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index be622bd6855..8c37567bcd7 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1681,10 +1681,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.register_unsize_obligations(span, &**u)
             }
             ty::UnsizeVtable(ref ty_trait, self_ty) => {
+                // If the type is `Foo+'a`, ensures that the type
+                // being cast to `Foo+'a` implements `Foo`:
                 vtable2::register_object_cast_obligations(self,
                                                           span,
                                                           ty_trait,
                                                           self_ty);
+
+                // If the type is `Foo+'a`, ensures that the type
+                // being cast to `Foo+'a` outlives `'a`:
+                let origin = infer::RelateObjectBound(span);
+                self.register_region_obligation(origin, self_ty, ty_trait.bounds.region_bound);
             }
         }
     }
diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
new file mode 100644
index 00000000000..6791b7c5870
--- /dev/null
+++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
@@ -0,0 +1,35 @@
+// 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.
+
+// Test that attempts to implicitly coerce a value into an
+// object respect the lifetime bound on the object type.
+
+fn a(v: &[u8]) -> Box<Clone + 'static> {
+    let x: Box<Clone + 'static> = box v; //~ ERROR does not outlive
+    x
+}
+
+fn b(v: &[u8]) -> Box<Clone + 'static> {
+    box v //~ ERROR does not outlive
+}
+
+fn c(v: &[u8]) -> Box<Clone> {
+    box v // OK thanks to lifetime elision
+}
+
+fn d<'a,'b>(v: &'a [u8]) -> Box<Clone+'b> {
+    box v //~ ERROR does not outlive
+}
+
+fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Clone+'b> {
+    box v // OK, thanks to 'a:'b
+}
+
+fn main() { }