]> git.lizzy.rs Git - rust.git/commitdiff
improve "Doesn't live long enough" error
authorMikhail Modin <mikhailm1@gmail.com>
Fri, 14 Oct 2016 15:55:45 +0000 (18:55 +0300)
committerMikhail Modin <mikhailm1@gmail.com>
Thu, 20 Oct 2016 19:51:51 +0000 (22:51 +0300)
68 files changed:
src/librustc_borrowck/borrowck/mod.rs
src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs
src/test/compile-fail-fulldeps/dropck_tarena_unsound_drop.rs
src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs [deleted file]
src/test/compile-fail/dropck-object-cycle.rs [deleted file]
src/test/compile-fail/dropck_arr_cycle_checked.rs [deleted file]
src/test/compile-fail/dropck_direct_cycle_with_drop.rs [deleted file]
src/test/compile-fail/dropck_misc_variants.rs [deleted file]
src/test/compile-fail/dropck_vec_cycle_checked.rs [deleted file]
src/test/compile-fail/impl-trait/loan-extend.rs [deleted file]
src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs [deleted file]
src/test/compile-fail/issue-24805-dropck-child-has-items-via-parent.rs [deleted file]
src/test/compile-fail/issue-24805-dropck-trait-has-items.rs [deleted file]
src/test/compile-fail/issue-24895-copy-clone-dropck.rs [deleted file]
src/test/compile-fail/issue-25199.rs [deleted file]
src/test/compile-fail/issue-26656.rs [deleted file]
src/test/compile-fail/issue-29106.rs [deleted file]
src/test/compile-fail/issue28498-reject-ex1.rs [deleted file]
src/test/compile-fail/issue28498-reject-lifetime-param.rs [deleted file]
src/test/compile-fail/issue28498-reject-passed-to-fn.rs [deleted file]
src/test/compile-fail/issue28498-reject-trait-bound.rs [deleted file]
src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs [deleted file]
src/test/compile-fail/vec_refs_data_with_early_death.rs [deleted file]
src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr
src/test/ui/dropck/dropck-eyepatch-reorder.stderr
src/test/ui/dropck/dropck-eyepatch.stderr
src/test/ui/span/borrowck-let-suggestion-suffixes.rs [new file with mode: 0644]
src/test/ui/span/borrowck-let-suggestion-suffixes.stderr [new file with mode: 0644]
src/test/ui/span/dropck-object-cycle.rs [new file with mode: 0644]
src/test/ui/span/dropck-object-cycle.stderr [new file with mode: 0644]
src/test/ui/span/dropck_arr_cycle_checked.rs [new file with mode: 0644]
src/test/ui/span/dropck_arr_cycle_checked.stderr [new file with mode: 0644]
src/test/ui/span/dropck_direct_cycle_with_drop.rs [new file with mode: 0644]
src/test/ui/span/dropck_direct_cycle_with_drop.stderr [new file with mode: 0644]
src/test/ui/span/dropck_misc_variants.rs [new file with mode: 0644]
src/test/ui/span/dropck_misc_variants.stderr [new file with mode: 0644]
src/test/ui/span/dropck_vec_cycle_checked.rs [new file with mode: 0644]
src/test/ui/span/dropck_vec_cycle_checked.stderr [new file with mode: 0644]
src/test/ui/span/issue-23338-locals-die-before-temps-of-body.rs [new file with mode: 0644]
src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr [new file with mode: 0644]
src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.rs [new file with mode: 0644]
src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr [new file with mode: 0644]
src/test/ui/span/issue-24805-dropck-trait-has-items.rs [new file with mode: 0644]
src/test/ui/span/issue-24805-dropck-trait-has-items.stderr [new file with mode: 0644]
src/test/ui/span/issue-24895-copy-clone-dropck.rs [new file with mode: 0644]
src/test/ui/span/issue-24895-copy-clone-dropck.stderr [new file with mode: 0644]
src/test/ui/span/issue-25199.rs [new file with mode: 0644]
src/test/ui/span/issue-25199.stderr [new file with mode: 0644]
src/test/ui/span/issue-26656.rs [new file with mode: 0644]
src/test/ui/span/issue-26656.stderr [new file with mode: 0644]
src/test/ui/span/issue-29106.rs [new file with mode: 0644]
src/test/ui/span/issue-29106.stderr [new file with mode: 0644]
src/test/ui/span/issue-36537.rs [new file with mode: 0644]
src/test/ui/span/issue-36537.stderr [new file with mode: 0644]
src/test/ui/span/issue28498-reject-ex1.rs [new file with mode: 0644]
src/test/ui/span/issue28498-reject-ex1.stderr [new file with mode: 0644]
src/test/ui/span/issue28498-reject-lifetime-param.rs [new file with mode: 0644]
src/test/ui/span/issue28498-reject-lifetime-param.stderr [new file with mode: 0644]
src/test/ui/span/issue28498-reject-passed-to-fn.rs [new file with mode: 0644]
src/test/ui/span/issue28498-reject-passed-to-fn.stderr [new file with mode: 0644]
src/test/ui/span/issue28498-reject-trait-bound.rs [new file with mode: 0644]
src/test/ui/span/issue28498-reject-trait-bound.stderr [new file with mode: 0644]
src/test/ui/span/loan-extend.rs [new file with mode: 0644]
src/test/ui/span/loan-extend.stderr [new file with mode: 0644]
src/test/ui/span/vec-must-not-hide-type-from-dropck.rs [new file with mode: 0644]
src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr [new file with mode: 0644]
src/test/ui/span/vec_refs_data_with_early_death.rs [new file with mode: 0644]
src/test/ui/span/vec_refs_data_with_early_death.stderr [new file with mode: 0644]

index 5d62629b648109d638d92c93a90a112f982453a3..89b12e76c3c182e8b4f0d1d95747d898021effcc 100644 (file)
@@ -1024,13 +1024,14 @@ pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<
             }
 
             err_out_of_scope(super_scope, sub_scope, cause) => {
-                let (value_kind, value_msg) = match err.cmt.cat {
+                let (value_kind, value_msg, is_temporary) = match err.cmt.cat {
                     mc::Categorization::Rvalue(_) =>
-                        ("temporary value", "temporary value created here"),
+                        ("temporary value", "temporary value created here", true),
                     _ =>
-                        ("borrowed value", "does not live long enough")
+                        ("borrowed value", "does not live long enough", false)
                 };
-                match cause {
+
+                let is_closure = match cause {
                     euv::ClosureCapture(s) => {
                         // The primary span starts out as the closure creation point.
                         // Change the primary span here to highlight the use of the variable
@@ -1041,21 +1042,36 @@ pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<
                                 db.span = MultiSpan::from_span(s);
                                 db.span_label(primary, &format!("capture occurs here"));
                                 db.span_label(s, &value_msg);
+                                true
                             }
-                            None => ()
+                            None => false
                         }
                     }
                     _ => {
                         db.span_label(error_span, &value_msg);
+                        false
                     }
-                }
+                };
 
                 let sub_span = self.region_end_span(sub_scope);
                 let super_span = self.region_end_span(super_scope);
 
                 match (sub_span, super_span) {
                     (Some(s1), Some(s2)) if s1 == s2 => {
-                        db.span_label(s1, &format!("{} dropped before borrower", value_kind));
+                        if !is_temporary && !is_closure {
+                            db.span = MultiSpan::from_span(s1);
+                            db.span_label(error_span, &format!("borrow occurs here"));
+                            let msg = match opt_loan_path(&err.cmt) {
+                                None => "borrowed value".to_string(),
+                                Some(lp) => {
+                                    format!("`{}`", self.loan_path_to_string(&lp))
+                                }
+                            };
+                            db.span_label(s1,
+                                          &format!("{} dropped here while still borrowed", msg));
+                        } else {
+                            db.span_label(s1, &format!("{} dropped before borrower", value_kind));
+                        }
                         db.note("values in a scope are dropped in the opposite order \
                                 they are created");
                     }
index d36293a484d4e3cb638ac934da2bb2fe39fd4435..bbdc59c84317288c6192bbdb125812b6af3dedef 100644 (file)
@@ -123,5 +123,5 @@ fn f<'a>(arena: &'a TypedArena<C<'a>>) {
 
 fn main() {
     let arena = TypedArena::new();
-    f(&arena); //~ ERROR `arena` does not live long enough
-}
+    f(&arena);
+} //~ ERROR `arena` does not live long enough
index 6cbed34c7ad94053179eec6f7959ab9ff55cf226..46cb76055745ad97946435443da6d26013bf1a02 100644 (file)
@@ -46,5 +46,6 @@ fn f<'a>(_arena: &'a TypedArena<C<'a>>) {}
 
 fn main() {
     let arena: TypedArena<C> = TypedArena::new();
-    f(&arena); //~ ERROR `arena` does not live long enough
-}
+    f(&arena);
+} //~ ERROR `arena` does not live long enough
+
diff --git a/src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs b/src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs
deleted file mode 100644 (file)
index 95c7434..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 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.
-
-fn f() {
-    let old = ['o'];         // statement 0
-    let mut v1 = Vec::new(); // statement 1
-
-    let mut v2 = Vec::new(); // statement 2
-
-    let young = ['y'];       // statement 3
-
-    v2.push(&young[0]);      // statement 4
-    //~^ ERROR `young[..]` does not live long enough
-    //~| NOTE does not live long enough
-    //~| NOTE values in a scope are dropped in the opposite order they are created
-
-    let mut v3 = Vec::new(); // statement 5
-
-    v3.push(&'x');           // statement 6
-    //~^ ERROR borrowed value does not live long enough
-    //~| NOTE temporary value created here
-    //~| NOTE temporary value only lives until here
-    //~| NOTE consider using a `let` binding to increase its lifetime
-
-    {
-
-        let mut v4 = Vec::new(); // (sub) statement 0
-
-        v4.push(&'y');
-        //~^ ERROR borrowed value does not live long enough
-        //~| NOTE temporary value created here
-        //~| NOTE temporary value only lives until here
-        //~| NOTE consider using a `let` binding to increase its lifetime
-
-    }                       // (statement 7)
-    //~^ NOTE temporary value needs to live until here
-
-    let mut v5 = Vec::new(); // statement 8
-
-    v5.push(&'z');
-    //~^ ERROR borrowed value does not live long enough
-    //~| NOTE temporary value created here
-    //~| NOTE temporary value only lives until here
-    //~| NOTE consider using a `let` binding to increase its lifetime
-
-    v1.push(&old[0]);
-}
-//~^ NOTE borrowed value dropped before borrower
-//~| NOTE temporary value needs to live until here
-//~| NOTE temporary value needs to live until here
-
-fn main() {
-    f();
-}
diff --git a/src/test/compile-fail/dropck-object-cycle.rs b/src/test/compile-fail/dropck-object-cycle.rs
deleted file mode 100644 (file)
index 5432cbf..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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.
-
-// This test used to be part of a run-pass test, but revised outlives
-// rule means that it no longer compiles.
-
-#![allow(unused_variables)]
-
-trait Trait<'a> {
-    fn long(&'a self) -> isize;
-    fn short<'b>(&'b self) -> isize;
-}
-
-fn object_invoke1<'d>(x: &'d Trait<'d>) -> (isize, isize) { loop { } }
-
-trait MakerTrait {
-    fn mk() -> Self;
-}
-
-fn make_val<T:MakerTrait>() -> T {
-    MakerTrait::mk()
-}
-
-impl<'t> MakerTrait for Box<Trait<'t>+'static> {
-    fn mk() -> Box<Trait<'t>+'static> { loop { } }
-}
-
-pub fn main() {
-    let m : Box<Trait+'static> = make_val();
-    assert_eq!(object_invoke1(&*m), (4,5));
-    //~^ ERROR `*m` does not live long enough
-
-    // the problem here is that the full type of `m` is
-    //
-    //   Box<Trait<'m>+'static>
-    //
-    // Here `'m` must be exactly the lifetime of the variable `m`.
-    // This is because of two requirements:
-    // 1. First, the basic type rules require that the
-    //    type of `m`'s value outlives the lifetime of `m`. This puts a lower
-    //    bound `'m`.
-    //
-    // 2. Meanwhile, the signature of `object_invoke1` requires that
-    //    we create a reference of type `&'d Trait<'d>` for some `'d`.
-    //    `'d` cannot outlive `'m`, so that forces the lifetime to be `'m`.
-    //
-    // This then conflicts with the dropck rules, which require that
-    // the type of `m` *strictly outlives* `'m`. Hence we get an
-    // error.
-}
diff --git a/src/test/compile-fail/dropck_arr_cycle_checked.rs b/src/test/compile-fail/dropck_arr_cycle_checked.rs
deleted file mode 100644 (file)
index 9cfeaca..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2015 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.
-
-// Reject mixing cyclic structure and Drop when using fixed length
-// arrays.
-//
-// (Compare against compile-fail/dropck_vec_cycle_checked.rs)
-
-#![feature(const_fn)]
-
-use std::cell::Cell;
-use id::Id;
-
-mod s {
-    use std::sync::atomic::{AtomicUsize, Ordering};
-
-    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
-
-    pub fn next_count() -> usize {
-        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
-    }
-}
-
-mod id {
-    use s;
-    #[derive(Debug)]
-    pub struct Id {
-        orig_count: usize,
-        count: usize,
-    }
-
-    impl Id {
-        pub fn new() -> Id {
-            let c = s::next_count();
-            println!("building Id {}", c);
-            Id { orig_count: c, count: c }
-        }
-        pub fn count(&self) -> usize {
-            println!("Id::count on {} returns {}", self.orig_count, self.count);
-            self.count
-        }
-    }
-
-    impl Drop for Id {
-        fn drop(&mut self) {
-            println!("dropping Id {}", self.count);
-            self.count = 0;
-        }
-    }
-}
-
-trait HasId {
-    fn count(&self) -> usize;
-}
-
-#[derive(Debug)]
-struct CheckId<T:HasId> {
-    v: T
-}
-
-#[allow(non_snake_case)]
-fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
-
-impl<T:HasId> Drop for CheckId<T> {
-    fn drop(&mut self) {
-        assert!(self.v.count() > 0);
-    }
-}
-
-#[derive(Debug)]
-struct B<'a> {
-    id: Id,
-    a: [CheckId<Cell<Option<&'a B<'a>>>>; 2]
-}
-
-impl<'a> HasId for Cell<Option<&'a B<'a>>> {
-    fn count(&self) -> usize {
-        match self.get() {
-            None => 1,
-            Some(b) => b.id.count(),
-        }
-    }
-}
-
-impl<'a> B<'a> {
-    fn new() -> B<'a> {
-        B { id: Id::new(), a: [CheckId(Cell::new(None)), CheckId(Cell::new(None))] }
-    }
-}
-
-fn f() {
-    let (b1, b2, b3);
-    b1 = B::new();
-    b2 = B::new();
-    b3 = B::new();
-    b1.a[0].v.set(Some(&b2)); //~ ERROR `b2` does not live long enough
-    b1.a[1].v.set(Some(&b3)); //~ ERROR `b3` does not live long enough
-    b2.a[0].v.set(Some(&b2)); //~ ERROR `b2` does not live long enough
-    b2.a[1].v.set(Some(&b3)); //~ ERROR `b3` does not live long enough
-    b3.a[0].v.set(Some(&b1)); //~ ERROR `b1` does not live long enough
-    b3.a[1].v.set(Some(&b2)); //~ ERROR `b2` does not live long enough
-}
-
-fn main() {
-    f();
-}
diff --git a/src/test/compile-fail/dropck_direct_cycle_with_drop.rs b/src/test/compile-fail/dropck_direct_cycle_with_drop.rs
deleted file mode 100644 (file)
index 5db2372..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 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.
-
-// A simple example of an unsound mixing of cyclic structure and Drop.
-//
-// Each `D` has a name and an optional reference to another `D`
-// sibling, but also implements a drop method that prints out its own
-// name as well as the name of its sibling.
-//
-// By setting up a cyclic structure, the drop code cannot possibly
-// work. Therefore this code must be rejected.
-//
-// (As it turns out, essentially any attempt to install a sibling here
-//  will be rejected, regardless of whether it forms a cyclic
-//  structure or not. This is because the use of the same lifetime
-//  `'a` in `&'a D<'a>` cannot be satisfied when `D<'a>` implements
-//  `Drop`.)
-
-use std::cell::Cell;
-
-struct D<'a> {
-    name: String,
-    p: Cell<Option<&'a D<'a>>>,
-}
-
-impl<'a> D<'a> {
-    fn new(name: String) -> D<'a> { D { name: name, p: Cell::new(None) } }
-}
-
-impl<'a> Drop for D<'a> {
-    fn drop(&mut self) {
-        println!("dropping {} whose sibling is {:?}",
-                 self.name, self.p.get().map(|d| &d.name));
-    }
-}
-
-fn g() {
-    let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2")));
-    d1.p.set(Some(&d2)); //~ ERROR `d2` does not live long enough
-    d2.p.set(Some(&d1)); //~ ERROR `d1` does not live long enough
-}
-
-fn main() {
-    g();
-}
diff --git a/src/test/compile-fail/dropck_misc_variants.rs b/src/test/compile-fail/dropck_misc_variants.rs
deleted file mode 100644 (file)
index ee957f2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 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 dropck does the right thing with misc. Ty variants
-
-use std::fmt;
-struct NoisyDrop<T: fmt::Debug>(T);
-impl<T: fmt::Debug> Drop for NoisyDrop<T> {
-    fn drop(&mut self) {
-        let _ = vec!["0wned"];
-        println!("dropping {:?}", self.0)
-    }
-}
-
-trait Associator {
-    type As;
-}
-impl<T: fmt::Debug> Associator for T {
-    type As = NoisyDrop<T>;
-}
-struct Wrap<A: Associator>(<A as Associator>::As);
-
-fn projection() {
-    let (_w, bomb);
-    bomb = vec![""];
-    _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
-    //~^ ERROR `bomb` does not live long enough
-}
-
-fn closure() {
-    let (_w,v);
-    v = vec![""];
-    _w = {
-        let u = NoisyDrop(&v);
-        //~^ ERROR `v` does not live long enough
-        move || u.0.len()
-    };
-}
-
-fn main() { closure(); projection() }
diff --git a/src/test/compile-fail/dropck_vec_cycle_checked.rs b/src/test/compile-fail/dropck_vec_cycle_checked.rs
deleted file mode 100644 (file)
index caf25e6..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015 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.
-
-// Reject mixing cyclic structure and Drop when using Vec.
-//
-// (Compare against compile-fail/dropck_arr_cycle_checked.rs)
-
-#![feature(const_fn)]
-
-use std::cell::Cell;
-use id::Id;
-
-mod s {
-    use std::sync::atomic::{AtomicUsize, Ordering};
-
-    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
-
-    pub fn next_count() -> usize {
-        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
-    }
-}
-
-mod id {
-    use s;
-    #[derive(Debug)]
-    pub struct Id {
-        orig_count: usize,
-        count: usize,
-    }
-
-    impl Id {
-        pub fn new() -> Id {
-            let c = s::next_count();
-            println!("building Id {}", c);
-            Id { orig_count: c, count: c }
-        }
-        pub fn count(&self) -> usize {
-            println!("Id::count on {} returns {}", self.orig_count, self.count);
-            self.count
-        }
-    }
-
-    impl Drop for Id {
-        fn drop(&mut self) {
-            println!("dropping Id {}", self.count);
-            self.count = 0;
-        }
-    }
-}
-
-trait HasId {
-    fn count(&self) -> usize;
-}
-
-#[derive(Debug)]
-struct CheckId<T:HasId> {
-    v: T
-}
-
-#[allow(non_snake_case)]
-fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
-
-impl<T:HasId> Drop for CheckId<T> {
-    fn drop(&mut self) {
-        assert!(self.v.count() > 0);
-    }
-}
-
-#[derive(Debug)]
-struct C<'a> {
-    id: Id,
-    v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>,
-}
-
-impl<'a> HasId for Cell<Option<&'a C<'a>>> {
-    fn count(&self) -> usize {
-        match self.get() {
-            None => 1,
-            Some(c) => c.id.count(),
-        }
-    }
-}
-
-impl<'a> C<'a> {
-    fn new() -> C<'a> {
-        C { id: Id::new(), v: Vec::new() }
-    }
-}
-
-fn f() {
-    let (mut c1, mut c2, mut c3);
-    c1 = C::new();
-    c2 = C::new();
-    c3 = C::new();
-
-    c1.v.push(CheckId(Cell::new(None)));
-    c1.v.push(CheckId(Cell::new(None)));
-    c2.v.push(CheckId(Cell::new(None)));
-    c2.v.push(CheckId(Cell::new(None)));
-    c3.v.push(CheckId(Cell::new(None)));
-    c3.v.push(CheckId(Cell::new(None)));
-
-    c1.v[0].v.set(Some(&c2)); //~ ERROR `c2` does not live long enough
-    c1.v[1].v.set(Some(&c3)); //~ ERROR `c3` does not live long enough
-    c2.v[0].v.set(Some(&c2)); //~ ERROR `c2` does not live long enough
-    c2.v[1].v.set(Some(&c3)); //~ ERROR `c3` does not live long enough
-    c3.v[0].v.set(Some(&c1)); //~ ERROR `c1` does not live long enough
-    c3.v[1].v.set(Some(&c2)); //~ ERROR `c2` does not live long enough
-}
-
-fn main() {
-    f();
-}
diff --git a/src/test/compile-fail/impl-trait/loan-extend.rs b/src/test/compile-fail/impl-trait/loan-extend.rs
deleted file mode 100644 (file)
index 8dfcb08..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 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.
-
-#![feature(conservative_impl_trait)]
-
-// Helper creating a fake borrow, captured by the impl Trait.
-fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () }
-
-fn main() {
-    let long;
-    let mut short = 0;
-    long = borrow(&mut short);
-    //~^ ERROR `short` does not live long enough
-    //~| NOTE does not live long enough
-    //~| NOTE values in a scope are dropped in the opposite order they are created
-} //~ borrowed value dropped before borrower
diff --git a/src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs b/src/test/compile-fail/issue-23338-locals-die-before-temps-of-body.rs
deleted file mode 100644 (file)
index 9938934..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 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.
-
-// This is just checking that we still reject code where temp values
-// are borrowing values for longer than they will be around.
-//
-// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs
-
-use std::cell::RefCell;
-
-fn foo(x: RefCell<String>) -> String {
-    let y = x;
-    y.borrow().clone() //~ ERROR `y` does not live long enough
-}
-
-fn foo2(x: RefCell<String>) -> String {
-    let ret = {
-        let y = x;
-        y.borrow().clone() //~ ERROR `y` does not live long enough
-    };
-    ret
-}
-
-fn main() {
-    let r = RefCell::new(format!("data"));
-    assert_eq!(foo(r), "data");
-    let r = RefCell::new(format!("data"));
-    assert_eq!(foo2(r), "data");
-}
diff --git a/src/test/compile-fail/issue-24805-dropck-child-has-items-via-parent.rs b/src/test/compile-fail/issue-24805-dropck-child-has-items-via-parent.rs
deleted file mode 100644 (file)
index 37ef81e..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 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 child trait who only has items via its *parent* trait
-// does cause dropck to inject extra region constraints.
-
-#![allow(non_camel_case_types)]
-
-trait Parent { fn foo(&self); }
-trait Child: Parent { }
-
-impl Parent for i32 { fn foo(&self) { } }
-impl<'a> Parent for &'a D_Child<i32> {
-    fn foo(&self) {
-        println!("accessing child value: {}", self.0);
-    }
-}
-
-impl Child for i32 { }
-impl<'a> Child for &'a D_Child<i32> { }
-
-struct D_Child<T:Child>(T);
-impl <T:Child> Drop for D_Child<T> { fn drop(&mut self) { self.0.foo() } }
-
-fn f_child() {
-    // `_d` and `d1` are assigned the *same* lifetime by region inference ...
-    let (_d, d1);
-
-    d1 = D_Child(1);
-    // ... we store a reference to `d1` within `_d` ...
-    _d = D_Child(&d1); //~ ERROR `d1` does not live long enough
-
-    // ... dropck *should* complain, because Drop of _d could (and
-    // does) access the already dropped `d1` via the `foo` method.
-}
-
-fn main() {
-    f_child();
-}
diff --git a/src/test/compile-fail/issue-24805-dropck-trait-has-items.rs b/src/test/compile-fail/issue-24805-dropck-trait-has-items.rs
deleted file mode 100644 (file)
index 0da1b9f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2015 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 traits with various kinds of associated items cause
-// dropck to inject extra region constraints.
-
-#![allow(non_camel_case_types)]
-
-trait HasSelfMethod { fn m1(&self) { } }
-trait HasMethodWithSelfArg { fn m2(x: &Self) { } }
-trait HasType { type Something; }
-
-impl HasSelfMethod for i32 { }
-impl HasMethodWithSelfArg for i32 { }
-impl HasType for i32 { type Something = (); }
-
-impl<'a,T> HasSelfMethod for &'a T { }
-impl<'a,T> HasMethodWithSelfArg for &'a T { }
-impl<'a,T> HasType for &'a T { type Something = (); }
-
-// e.g. `impl_drop!(Send, D_Send)` expands to:
-//   ```rust
-//   struct D_Send<T:Send>(T);
-//   impl<T:Send> Drop for D_Send<T> { fn drop(&mut self) { } }
-//   ```
-macro_rules! impl_drop {
-    ($Bound:ident, $Id:ident) => {
-        struct $Id<T:$Bound>(T);
-        impl <T:$Bound> Drop for $Id<T> { fn drop(&mut self) { } }
-    }
-}
-
-impl_drop!{HasSelfMethod,        D_HasSelfMethod}
-impl_drop!{HasMethodWithSelfArg, D_HasMethodWithSelfArg}
-impl_drop!{HasType,              D_HasType}
-
-fn f_sm() {
-    let (_d, d1);
-    d1 = D_HasSelfMethod(1);
-    _d = D_HasSelfMethod(&d1); //~ ERROR `d1` does not live long enough
-}
-fn f_mwsa() {
-    let (_d, d1);
-    d1 = D_HasMethodWithSelfArg(1);
-    _d = D_HasMethodWithSelfArg(&d1); //~ ERROR `d1` does not live long enough
-}
-fn f_t() {
-    let (_d, d1);
-    d1 = D_HasType(1);
-    _d = D_HasType(&d1); //~ ERROR `d1` does not live long enough
-}
-
-fn main() {
-    f_sm();
-    f_mwsa();
-    f_t();
-}
diff --git a/src/test/compile-fail/issue-24895-copy-clone-dropck.rs b/src/test/compile-fail/issue-24895-copy-clone-dropck.rs
deleted file mode 100644 (file)
index 2883511..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 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 one cannot subvert Drop Check rule via a user-defined
-// Clone implementation.
-
-#![allow(unused_variables, unused_assignments)]
-
-struct D<T:Copy>(T, &'static str);
-
-#[derive(Copy)]
-struct S<'a>(&'a D<i32>, &'static str);
-impl<'a> Clone for S<'a> {
-    fn clone(&self) -> S<'a> {
-        println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0);
-        S(self.0, self.1)
-    }
-}
-
-impl<T:Copy> Drop for D<T> {
-    fn drop(&mut self) {
-        println!("calling Drop for {}", self.1);
-        let _call = self.0.clone();
-    }
-}
-
-fn main() {
-    let (d2, d1);
-    d1 = D(34, "d1");
-    d2 = D(S(&d1, "inner"), "d2"); //~ ERROR `d1` does not live long enough
-}
diff --git a/src/test/compile-fail/issue-25199.rs b/src/test/compile-fail/issue-25199.rs
deleted file mode 100644 (file)
index 74ea1ca..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2015 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.
-
-// Regression test for Issue 25199: Check that one cannot hide a
-// destructor's access to borrowed data behind a boxed trait object.
-//
-// Prior to fixing Issue 25199, this example was able to be compiled
-// with rustc, and thus when you ran it, you would see the `Drop` impl
-// for `Test` accessing state that had already been dropping (which is
-// marked explicitly here with checking code within the `Drop` impl
-// for `VecHolder`, but in the general case could just do unsound
-// things like accessing memory that has been freed).
-//
-// Note that I would have liked to encode my go-to example of cyclic
-// structure that accesses its neighbors in drop (and thus is
-// fundamentally unsound) via this trick, but the closest I was able
-// to come was dropck_trait_cycle_checked.rs, which is not quite as
-// "good" as this regression test because the encoding of that example
-// was forced to attach a lifetime to the trait definition itself
-// (`trait Obj<'a>`) while *this* example is solely
-
-use std::cell::RefCell;
-
-trait Obj { }
-
-struct VecHolder {
-    v: Vec<(bool, &'static str)>,
-}
-
-impl Drop for VecHolder {
-    fn drop(&mut self) {
-        println!("Dropping Vec");
-        self.v[30].0 = false;
-        self.v[30].1 = "invalid access: VecHolder dropped already";
-    }
-}
-
-struct Container<'a> {
-    v: VecHolder,
-    d: RefCell<Vec<Box<Obj+'a>>>,
-}
-
-impl<'a> Container<'a> {
-    fn new() -> Container<'a> {
-        Container {
-            d: RefCell::new(Vec::new()),
-            v: VecHolder {
-                v: vec![(true, "valid"); 100]
-            }
-        }
-    }
-
-    fn store<T: Obj+'a>(&'a self, val: T) {
-        self.d.borrow_mut().push(Box::new(val));
-    }
-}
-
-struct Test<'a> {
-    test: &'a Container<'a>,
-}
-
-impl<'a> Obj for Test<'a> { }
-impl<'a> Drop for Test<'a> {
-    fn drop(&mut self) {
-        for e in &self.test.v.v {
-            assert!(e.0, e.1);
-        }
-    }
-}
-
-fn main() {
-    let container = Container::new();
-    let test = Test{test: &container}; //~ ERROR `container` does not live long enough
-    println!("container.v[30]: {:?}", container.v.v[30]);
-    container.store(test); //~ ERROR `container` does not live long enough
-}
diff --git a/src/test/compile-fail/issue-26656.rs b/src/test/compile-fail/issue-26656.rs
deleted file mode 100644 (file)
index e5fa654..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 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.
-
-// Issue #26656: Verify that trait objects cannot bypass dropck.
-
-// Using this instead of Fn etc. to take HRTB out of the equation.
-trait Trigger<B> { fn fire(&self, b: &mut B); }
-impl<B: Button> Trigger<B> for () {
-    fn fire(&self, b: &mut B) {
-        b.push();
-    }
-}
-
-// Still unsound Zook
-trait Button { fn push(&self); }
-struct Zook<B> { button: B, trigger: Box<Trigger<B>+'static> }
-
-impl<B> Drop for Zook<B> {
-    fn drop(&mut self) {
-        self.trigger.fire(&mut self.button);
-    }
-}
-
-// AND
-struct Bomb { usable: bool }
-impl Drop for Bomb { fn drop(&mut self) { self.usable = false; } }
-impl Bomb { fn activate(&self) { assert!(self.usable) } }
-
-enum B<'a> { HarmlessButton, BigRedButton(&'a Bomb) }
-impl<'a> Button for B<'a> {
-    fn push(&self) {
-        if let B::BigRedButton(borrowed) = *self {
-            borrowed.activate();
-        }
-    }
-}
-
-fn main() {
-    let (mut zook, ticking);
-    zook = Zook { button: B::HarmlessButton,
-                  trigger: Box::new(()) };
-    ticking = Bomb { usable: true };
-    zook.button = B::BigRedButton(&ticking);
-    //~^ ERROR `ticking` does not live long enough
-}
diff --git a/src/test/compile-fail/issue-29106.rs b/src/test/compile-fail/issue-29106.rs
deleted file mode 100644 (file)
index 1872c62..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 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.
-
-use std::rc::Rc;
-use std::sync::Arc;
-
-struct Foo<'a>(&'a String);
-
-impl<'a> Drop for Foo<'a> {
-    fn drop(&mut self) {
-        println!("{:?}", self.0);
-    }
-}
-
-fn main() {
-    {
-        let (y, x);
-        x = "alive".to_string();
-        y = Arc::new(Foo(&x)); //~ ERROR `x` does not live long enough
-    }
-
-    {
-        let (y, x);
-        x = "alive".to_string();
-        y = Rc::new(Foo(&x)); //~ ERROR `x` does not live long enough
-    }
-}
diff --git a/src/test/compile-fail/issue28498-reject-ex1.rs b/src/test/compile-fail/issue28498-reject-ex1.rs
deleted file mode 100644 (file)
index cee7c57..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 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.
-
-// Example taken from RFC 1238 text
-
-// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
-//     #examples-of-code-that-will-start-to-be-rejected
-
-// Compare against test/run-pass/issue28498-must-work-ex2.rs
-
-use std::cell::Cell;
-
-struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
-
-struct Foo<T> { data: Vec<T> }
-
-fn potentially_specialized_wrt_t<T>(t: &T) {
-    // Hypothetical code that does one thing for generic T and then is
-    // specialized for T == Concrete (and the specialized form can
-    // then access a reference held in concrete tuple).
-    //
-    // (We don't have specialization yet, but we want to allow for it
-    // in the future.)
-}
-
-impl<T> Drop for Foo<T> {
-    fn drop(&mut self) {
-        potentially_specialized_wrt_t(&self.data[0])
-    }
-}
-
-fn main() {
-    let mut foo = Foo {  data: Vec::new() };
-    foo.data.push(Concrete(0, Cell::new(None)));
-    foo.data.push(Concrete(0, Cell::new(None)));
-
-    foo.data[0].1.set(Some(&foo.data[1]));
-    //~^ ERROR `foo.data` does not live long enough
-    foo.data[1].1.set(Some(&foo.data[0]));
-    //~^ ERROR `foo.data` does not live long enough
-}
diff --git a/src/test/compile-fail/issue28498-reject-lifetime-param.rs b/src/test/compile-fail/issue28498-reject-lifetime-param.rs
deleted file mode 100644 (file)
index 92028c7..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 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.
-
-// Demonstrate that having a lifetime param causes dropck to reject code
-// that might indirectly access previously dropped value.
-//
-// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs
-
-#[derive(Debug)]
-struct ScribbleOnDrop(String);
-
-impl Drop for ScribbleOnDrop {
-    fn drop(&mut self) {
-        self.0 = format!("DROPPED");
-    }
-}
-
-struct Foo<'a>(u32, &'a ScribbleOnDrop);
-
-impl<'a> Drop for Foo<'a> {
-    fn drop(&mut self) {
-        // Use of `unsafe_destructor_blind_to_params` is unsound,
-        // because destructor accesses borrowed data in `self.1`
-        // and we must force that to strictly outlive `self`.
-        println!("Dropping Foo({}, {:?})", self.0, self.1);
-    }
-}
-
-fn main() {
-    let (last_dropped, foo0);
-    let (foo1, first_dropped);
-
-    last_dropped = ScribbleOnDrop(format!("last"));
-    first_dropped = ScribbleOnDrop(format!("first"));
-    foo0 = Foo(0, &last_dropped);
-    //~^ ERROR `last_dropped` does not live long enough
-    foo1 = Foo(1, &first_dropped);
-    //~^ ERROR `first_dropped` does not live long enough
-
-    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
-}
diff --git a/src/test/compile-fail/issue28498-reject-passed-to-fn.rs b/src/test/compile-fail/issue28498-reject-passed-to-fn.rs
deleted file mode 100644 (file)
index 27378b1..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 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.
-
-// Demonstrate that a type param in negative position causes dropck to reject code
-// that might indirectly access previously dropped value.
-//
-// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
-
-#[derive(Debug)]
-struct ScribbleOnDrop(String);
-
-impl Drop for ScribbleOnDrop {
-    fn drop(&mut self) {
-        self.0 = format!("DROPPED");
-    }
-}
-
-struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
-
-impl<T> Drop for Foo<T> {
-    fn drop(&mut self) {
-        // Use of `unsafe_destructor_blind_to_params` is unsound,
-        // because we pass `T` to the callback in `self.2`
-        // below, and thus potentially read from borrowed data.
-        println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
-    }
-}
-
-fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
-
-fn main() {
-    let (last_dropped, foo0);
-    let (foo1, first_dropped);
-
-    last_dropped = ScribbleOnDrop(format!("last"));
-    first_dropped = ScribbleOnDrop(format!("first"));
-    foo0 = Foo(0, &last_dropped, Box::new(callback));
-    //~^ ERROR `last_dropped` does not live long enough
-    foo1 = Foo(1, &first_dropped, Box::new(callback));
-    //~^ ERROR `first_dropped` does not live long enough
-
-    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
-}
diff --git a/src/test/compile-fail/issue28498-reject-trait-bound.rs b/src/test/compile-fail/issue28498-reject-trait-bound.rs
deleted file mode 100644 (file)
index 3904d68..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 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.
-
-// Demonstrate that having a trait bound causes dropck to reject code
-// that might indirectly access previously dropped value.
-//
-// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs
-
-use std::fmt;
-
-#[derive(Debug)]
-struct ScribbleOnDrop(String);
-
-impl Drop for ScribbleOnDrop {
-    fn drop(&mut self) {
-        self.0 = format!("DROPPED");
-    }
-}
-
-struct Foo<T:fmt::Debug>(u32, T);
-
-impl<T:fmt::Debug> Drop for Foo<T> {
-    fn drop(&mut self) {
-        // Use of `unsafe_destructor_blind_to_params` is unsound,
-        // because we access `T` fmt method when we pass `self.1`
-        // below, and thus potentially read from borrowed data.
-        println!("Dropping Foo({}, {:?})", self.0, self.1);
-    }
-}
-
-fn main() {
-    let (last_dropped, foo0);
-    let (foo1, first_dropped);
-
-    last_dropped = ScribbleOnDrop(format!("last"));
-    first_dropped = ScribbleOnDrop(format!("first"));
-    foo0 = Foo(0, &last_dropped);
-    //~^ ERROR `last_dropped` does not live long enough
-    foo1 = Foo(1, &first_dropped);
-    //~^ ERROR `first_dropped` does not live long enough
-
-    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
-}
diff --git a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs
deleted file mode 100644 (file)
index c8f4326..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2015 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.
-
-// Checking that `Vec<T>` cannot hide lifetimes within `T` when `T`
-// implements `Drop` and might access methods of values that have
-// since been deallocated.
-//
-// In this case, the values in question hold (non-zero) unique-ids
-// that zero themselves out when dropped, and are wrapped in another
-// type with a destructor that asserts that the ids it references are
-// indeed non-zero (i.e., effectively checking that the id's are not
-// dropped while there are still any outstanding references).
-//
-// However, the values in question are also formed into a
-// cyclic-structure, ensuring that there is no way for all of the
-// conditions above to be satisfied, meaning that if the dropck is
-// sound, it should reject this code.
-
-#![feature(const_fn)]
-
-use std::cell::Cell;
-use id::Id;
-
-mod s {
-    use std::sync::atomic::{AtomicUsize, Ordering};
-
-    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
-
-    /// generates globally unique count (global across the current
-    /// process, that is)
-    pub fn next_count() -> usize {
-        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
-    }
-}
-
-mod id {
-    use s;
-
-    /// Id represents a globally unique identifier (global across the
-    /// current process, that is). When dropped, it automatically
-    /// clears its `count` field, but leaves `orig_count` untouched,
-    /// so that if there are subsequent (erroneous) invocations of its
-    /// method (which is unsound), we can observe it by seeing that
-    /// the `count` is 0 while the `orig_count` is non-zero.
-    #[derive(Debug)]
-    pub struct Id {
-        orig_count: usize,
-        count: usize,
-    }
-
-    impl Id {
-        /// Creates an `Id` with a globally unique count.
-        pub fn new() -> Id {
-            let c = s::next_count();
-            println!("building Id {}", c);
-            Id { orig_count: c, count: c }
-        }
-        /// returns the `count` of self; should be non-zero if
-        /// everything is working.
-        pub fn count(&self) -> usize {
-            println!("Id::count on {} returns {}", self.orig_count, self.count);
-            self.count
-        }
-    }
-
-    impl Drop for Id {
-        fn drop(&mut self) {
-            println!("dropping Id {}", self.count);
-            self.count = 0;
-        }
-    }
-}
-
-trait HasId {
-    fn count(&self) -> usize;
-}
-
-#[derive(Debug)]
-struct CheckId<T:HasId> {
-    v: T
-}
-
-#[allow(non_snake_case)]
-fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
-
-impl<T:HasId> Drop for CheckId<T> {
-    fn drop(&mut self) {
-        assert!(self.v.count() > 0);
-    }
-}
-
-#[derive(Debug)]
-struct C<'a> {
-    id: Id,
-    v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>,
-}
-
-impl<'a> HasId for Cell<Option<&'a C<'a>>> {
-    fn count(&self) -> usize {
-        match self.get() {
-            None => 1,
-            Some(c) => c.id.count(),
-        }
-    }
-}
-
-impl<'a> C<'a> {
-    fn new() -> C<'a> {
-        C { id: Id::new(), v: Vec::new() }
-    }
-}
-
-fn f() {
-    let (mut c1, mut c2);
-    c1 = C::new();
-    c2 = C::new();
-
-    c1.v.push(CheckId(Cell::new(None)));
-    c2.v.push(CheckId(Cell::new(None)));
-    c1.v[0].v.set(Some(&c2)); //~ ERROR `c2` does not live long enough
-    c2.v[0].v.set(Some(&c1)); //~ ERROR `c1` does not live long enough
-}
-
-fn main() {
-    f();
-}
diff --git a/src/test/compile-fail/vec_refs_data_with_early_death.rs b/src/test/compile-fail/vec_refs_data_with_early_death.rs
deleted file mode 100644 (file)
index 0025449..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 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.
-
-// This test is a simple example of code that violates the dropck
-// rules: it pushes `&x` and `&y` into `v`, but the referenced data
-// will be dropped before the vector itself is.
-
-// (In principle we know that `Vec` does not reference the data it
-//  owns from within its drop code, apart from calling drop on each
-//  element it owns; thus, for data like this, it seems like we could
-//  loosen the restrictions here if we wanted. But it also is not
-//  clear whether such loosening is terribly important.)
-
-fn main() {
-    let mut v = Vec::new();
-
-    let x: i8 = 3;
-    let y: i8 = 4;
-
-    v.push(&x); //~ ERROR `x` does not live long enough
-    v.push(&y); //~ ERROR `y` does not live long enough
-
-    assert_eq!(v, [&3, &4]);
-}
index 5d2096e8b07a45126670f4a4c55793a0dbc32769..2a4ba22ecc46711cf4cb6f1e06ba5f81eb900c95 100644 (file)
@@ -1,44 +1,44 @@
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-extern-crate.rs:39:20
+  --> $DIR/dropck-eyepatch-extern-crate.rs:55:1
    |
 39 |     dt = Dt("dt", &c); //~ ERROR `c` does not live long enough
-   |                    ^ does not live long enough
+   |                    - borrow occurs here
 ...
 55 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-extern-crate.rs:40:20
+  --> $DIR/dropck-eyepatch-extern-crate.rs:55:1
    |
 40 |     dr = Dr("dr", &c); //~ ERROR `c` does not live long enough
-   |                    ^ does not live long enough
+   |                    - borrow occurs here
 ...
 55 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-extern-crate.rs:47:29
+  --> $DIR/dropck-eyepatch-extern-crate.rs:55:1
    |
 47 |     pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough
-   |                             ^ does not live long enough
+   |                             - borrow occurs here
 ...
 55 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-extern-crate.rs:48:29
+  --> $DIR/dropck-eyepatch-extern-crate.rs:55:1
    |
 48 |     pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough
-   |                             ^ does not live long enough
+   |                             - borrow occurs here
 ...
 55 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
index 33b18f6f02e0f180b479b90364ace3f903088259..cfcf988f31f7b1295ea73bac6d32b2eb44c554cb 100644 (file)
@@ -1,44 +1,44 @@
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:57:20
+  --> $DIR/dropck-eyepatch-reorder.rs:73:1
    |
 57 |     dt = Dt("dt", &c); //~ ERROR `c` does not live long enough
-   |                    ^ does not live long enough
+   |                    - borrow occurs here
 ...
 73 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:58:20
+  --> $DIR/dropck-eyepatch-reorder.rs:73:1
    |
 58 |     dr = Dr("dr", &c); //~ ERROR `c` does not live long enough
-   |                    ^ does not live long enough
+   |                    - borrow occurs here
 ...
 73 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:65:29
+  --> $DIR/dropck-eyepatch-reorder.rs:73:1
    |
 65 |     pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough
-   |                             ^ does not live long enough
+   |                             - borrow occurs here
 ...
 73 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:66:29
+  --> $DIR/dropck-eyepatch-reorder.rs:73:1
    |
 66 |     pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough
-   |                             ^ does not live long enough
+   |                             - borrow occurs here
 ...
 73 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
index 75e612ca9c8f181ae860aac9e45d5e7d6065b644..cd420756b444c81f207a8785b121e04637cf9dd1 100644 (file)
@@ -1,44 +1,44 @@
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:80:20
+  --> $DIR/dropck-eyepatch.rs:96:1
    |
 80 |     dt = Dt("dt", &c); //~ ERROR `c` does not live long enough
-   |                    ^ does not live long enough
+   |                    - borrow occurs here
 ...
 96 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:81:20
+  --> $DIR/dropck-eyepatch.rs:96:1
    |
 81 |     dr = Dr("dr", &c); //~ ERROR `c` does not live long enough
-   |                    ^ does not live long enough
+   |                    - borrow occurs here
 ...
 96 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:88:29
+  --> $DIR/dropck-eyepatch.rs:96:1
    |
 88 |     pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough
-   |                             ^ does not live long enough
+   |                             - borrow occurs here
 ...
 96 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:89:29
+  --> $DIR/dropck-eyepatch.rs:96:1
    |
 89 |     pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough
-   |                             ^ does not live long enough
+   |                             - borrow occurs here
 ...
 96 | }
-   | - borrowed value dropped before borrower
+   | ^ `c` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
new file mode 100644 (file)
index 0000000..1206d71
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2015 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.
+
+fn f() {
+    let old = ['o'];         // statement 0
+    let mut v1 = Vec::new(); // statement 1
+
+    let mut v2 = Vec::new(); // statement 2
+
+    let young = ['y'];       // statement 3
+
+    v2.push(&young[0]);      // statement 4
+    //~^ NOTE borrow occurs here
+
+    let mut v3 = Vec::new(); // statement 5
+
+    v3.push(&'x');           // statement 6
+    //~^ ERROR borrowed value does not live long enough
+    //~| NOTE temporary value created here
+    //~| NOTE temporary value only lives until here
+    //~| NOTE consider using a `let` binding to increase its lifetime
+
+    {
+
+        let mut v4 = Vec::new(); // (sub) statement 0
+
+        v4.push(&'y');
+        //~^ ERROR borrowed value does not live long enough
+        //~| NOTE temporary value created here
+        //~| NOTE temporary value only lives until here
+        //~| NOTE consider using a `let` binding to increase its lifetime
+
+    }                       // (statement 7)
+    //~^ NOTE temporary value needs to live until here
+
+    let mut v5 = Vec::new(); // statement 8
+
+    v5.push(&'z');
+    //~^ ERROR borrowed value does not live long enough
+    //~| NOTE temporary value created here
+    //~| NOTE temporary value only lives until here
+    //~| NOTE consider using a `let` binding to increase its lifetime
+
+    v1.push(&old[0]);
+}
+//~^ ERROR `young[..]` does not live long enough
+//~| NOTE `young[..]` dropped here while still borrowed
+//~| NOTE values in a scope are dropped in the opposite order they are created
+//~| NOTE temporary value needs to live until here
+//~| NOTE temporary value needs to live until here
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
new file mode 100644 (file)
index 0000000..0bba986
--- /dev/null
@@ -0,0 +1,52 @@
+error: `young[..]` does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:52:1
+   |
+19 |     v2.push(&young[0]);      // statement 4
+   |              -------- borrow occurs here
+...
+52 | }
+   | ^ `young[..]` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:24:14
+   |
+24 |     v3.push(&'x');           // statement 6
+   |              ^^^ - temporary value only lives until here
+   |              |
+   |              temporary value created here
+...
+52 | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:34:18
+   |
+34 |         v4.push(&'y');
+   |                  ^^^ - temporary value only lives until here
+   |                  |
+   |                  temporary value created here
+...
+40 |     }                       // (statement 7)
+   |     - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: borrowed value does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:45:14
+   |
+45 |     v5.push(&'z');
+   |              ^^^ - temporary value only lives until here
+   |              |
+   |              temporary value created here
+...
+52 | }
+   | - temporary value needs to live until here
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/span/dropck-object-cycle.rs b/src/test/ui/span/dropck-object-cycle.rs
new file mode 100644 (file)
index 0000000..ce9bc17
--- /dev/null
@@ -0,0 +1,61 @@
+// 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.
+
+// This test used to be part of a run-pass test, but revised outlives
+// rule means that it no longer compiles.
+
+#![allow(unused_variables)]
+
+trait Trait<'a> {
+    fn long(&'a self) -> isize;
+    fn short<'b>(&'b self) -> isize;
+}
+
+fn object_invoke1<'d>(x: &'d Trait<'d>) -> (isize, isize) { loop { } }
+
+trait MakerTrait {
+    fn mk() -> Self;
+}
+
+fn make_val<T:MakerTrait>() -> T {
+    MakerTrait::mk()
+}
+
+impl<'t> MakerTrait for Box<Trait<'t>+'static> {
+    fn mk() -> Box<Trait<'t>+'static> { loop { } }
+}
+
+pub fn main() {
+    let m : Box<Trait+'static> = make_val();
+    assert_eq!(object_invoke1(&*m), (4,5));
+    //~^ NOTE borrow occurs here
+
+    // the problem here is that the full type of `m` is
+    //
+    //   Box<Trait<'m>+'static>
+    //
+    // Here `'m` must be exactly the lifetime of the variable `m`.
+    // This is because of two requirements:
+    // 1. First, the basic type rules require that the
+    //    type of `m`'s value outlives the lifetime of `m`. This puts a lower
+    //    bound `'m`.
+    //
+    // 2. Meanwhile, the signature of `object_invoke1` requires that
+    //    we create a reference of type `&'d Trait<'d>` for some `'d`.
+    //    `'d` cannot outlive `'m`, so that forces the lifetime to be `'m`.
+    //
+    // This then conflicts with the dropck rules, which require that
+    // the type of `m` *strictly outlives* `'m`. Hence we get an
+    // error.
+}
+//~^ ERROR `*m` does not live long enough
+//~| NOTE `*m` dropped here while still borrowed
+//~| NOTE values in a scope are dropped in the opposite order they are created
+
diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr
new file mode 100644 (file)
index 0000000..e31c36e
--- /dev/null
@@ -0,0 +1,13 @@
+error: `*m` does not live long enough
+  --> $DIR/dropck-object-cycle.rs:57:1
+   |
+37 |     assert_eq!(object_invoke1(&*m), (4,5));
+   |                                -- borrow occurs here
+...
+57 | }
+   | ^ `*m` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.rs b/src/test/ui/span/dropck_arr_cycle_checked.rs
new file mode 100644 (file)
index 0000000..8e8b3c2
--- /dev/null
@@ -0,0 +1,119 @@
+// Copyright 2015 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.
+
+// Reject mixing cyclic structure and Drop when using fixed length
+// arrays.
+//
+// (Compare against compile-fail/dropck_vec_cycle_checked.rs)
+
+#![feature(const_fn)]
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+#[derive(Debug)]
+struct B<'a> {
+    id: Id,
+    a: [CheckId<Cell<Option<&'a B<'a>>>>; 2]
+}
+
+impl<'a> HasId for Cell<Option<&'a B<'a>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(b) => b.id.count(),
+        }
+    }
+}
+
+impl<'a> B<'a> {
+    fn new() -> B<'a> {
+        B { id: Id::new(), a: [CheckId(Cell::new(None)), CheckId(Cell::new(None))] }
+    }
+}
+
+fn f() {
+    let (b1, b2, b3);
+    b1 = B::new();
+    b2 = B::new();
+    b3 = B::new();
+    b1.a[0].v.set(Some(&b2));
+    b1.a[1].v.set(Some(&b3));
+    b2.a[0].v.set(Some(&b2));
+    b2.a[1].v.set(Some(&b3));
+    b3.a[0].v.set(Some(&b1));
+    b3.a[1].v.set(Some(&b2));
+}
+//~^ ERROR `b2` does not live long enough
+//~| ERROR `b3` does not live long enough
+//~| ERROR `b2` does not live long enough
+//~| ERROR `b3` does not live long enough
+//~| ERROR `b1` does not live long enough
+//~| ERROR `b2` does not live long enough
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr
new file mode 100644 (file)
index 0000000..c89da0b
--- /dev/null
@@ -0,0 +1,67 @@
+error: `b2` does not live long enough
+   --> $DIR/dropck_arr_cycle_checked.rs:109:1
+    |
+103 |     b1.a[0].v.set(Some(&b2));
+    |                         -- borrow occurs here
+...
+109 | }
+    | ^ `b2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `b3` does not live long enough
+   --> $DIR/dropck_arr_cycle_checked.rs:109:1
+    |
+104 |     b1.a[1].v.set(Some(&b3));
+    |                         -- borrow occurs here
+...
+109 | }
+    | ^ `b3` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `b2` does not live long enough
+   --> $DIR/dropck_arr_cycle_checked.rs:109:1
+    |
+105 |     b2.a[0].v.set(Some(&b2));
+    |                         -- borrow occurs here
+...
+109 | }
+    | ^ `b2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `b3` does not live long enough
+   --> $DIR/dropck_arr_cycle_checked.rs:109:1
+    |
+106 |     b2.a[1].v.set(Some(&b3));
+    |                         -- borrow occurs here
+...
+109 | }
+    | ^ `b3` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `b1` does not live long enough
+   --> $DIR/dropck_arr_cycle_checked.rs:109:1
+    |
+107 |     b3.a[0].v.set(Some(&b1));
+    |                         -- borrow occurs here
+108 |     b3.a[1].v.set(Some(&b2));
+109 | }
+    | ^ `b1` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `b2` does not live long enough
+   --> $DIR/dropck_arr_cycle_checked.rs:109:1
+    |
+108 |     b3.a[1].v.set(Some(&b2));
+    |                         -- borrow occurs here
+109 | }
+    | ^ `b2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.rs b/src/test/ui/span/dropck_direct_cycle_with_drop.rs
new file mode 100644 (file)
index 0000000..6d13dfc
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2015 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.
+
+// A simple example of an unsound mixing of cyclic structure and Drop.
+//
+// Each `D` has a name and an optional reference to another `D`
+// sibling, but also implements a drop method that prints out its own
+// name as well as the name of its sibling.
+//
+// By setting up a cyclic structure, the drop code cannot possibly
+// work. Therefore this code must be rejected.
+//
+// (As it turns out, essentially any attempt to install a sibling here
+//  will be rejected, regardless of whether it forms a cyclic
+//  structure or not. This is because the use of the same lifetime
+//  `'a` in `&'a D<'a>` cannot be satisfied when `D<'a>` implements
+//  `Drop`.)
+
+use std::cell::Cell;
+
+struct D<'a> {
+    name: String,
+    p: Cell<Option<&'a D<'a>>>,
+}
+
+impl<'a> D<'a> {
+    fn new(name: String) -> D<'a> { D { name: name, p: Cell::new(None) } }
+}
+
+impl<'a> Drop for D<'a> {
+    fn drop(&mut self) {
+        println!("dropping {} whose sibling is {:?}",
+                 self.name, self.p.get().map(|d| &d.name));
+    }
+}
+
+fn g() {
+    let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2")));
+    d1.p.set(Some(&d2));
+    d2.p.set(Some(&d1));
+}
+//~^ ERROR `d2` does not live long enough
+//~| ERROR `d1` does not live long enough
+
+fn main() {
+    g();
+}
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr
new file mode 100644 (file)
index 0000000..9eb2a21
--- /dev/null
@@ -0,0 +1,23 @@
+error: `d2` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:48:1
+   |
+46 |     d1.p.set(Some(&d2));
+   |                    -- borrow occurs here
+47 |     d2.p.set(Some(&d1));
+48 | }
+   | ^ `d2` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `d1` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:48:1
+   |
+47 |     d2.p.set(Some(&d1));
+   |                    -- borrow occurs here
+48 | }
+   | ^ `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/dropck_misc_variants.rs b/src/test/ui/span/dropck_misc_variants.rs
new file mode 100644 (file)
index 0000000..7b94eb1
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2015 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 dropck does the right thing with misc. Ty variants
+
+use std::fmt;
+struct NoisyDrop<T: fmt::Debug>(T);
+impl<T: fmt::Debug> Drop for NoisyDrop<T> {
+    fn drop(&mut self) {
+        let _ = vec!["0wned"];
+        println!("dropping {:?}", self.0)
+    }
+}
+
+trait Associator {
+    type As;
+}
+impl<T: fmt::Debug> Associator for T {
+    type As = NoisyDrop<T>;
+}
+struct Wrap<A: Associator>(<A as Associator>::As);
+
+fn projection() {
+    let (_w, bomb);
+    bomb = vec![""];
+    _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
+}
+//~^ ERROR `bomb` does not live long enough
+
+fn closure() {
+    let (_w,v);
+    v = vec![""];
+    _w = {
+        let u = NoisyDrop(&v);
+        move || u.0.len()
+    };
+}
+//~^ ERROR `v` does not live long enough
+
+fn main() { closure(); projection() }
diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr
new file mode 100644 (file)
index 0000000..98c1cbb
--- /dev/null
@@ -0,0 +1,23 @@
+error: `bomb` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:34:1
+   |
+33 |     _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
+   |                                     ---- borrow occurs here
+34 | }
+   | ^ `bomb` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `v` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:44:1
+   |
+41 |         let u = NoisyDrop(&v);
+   |                            - borrow occurs here
+...
+44 | }
+   | ^ `v` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.rs b/src/test/ui/span/dropck_vec_cycle_checked.rs
new file mode 100644 (file)
index 0000000..65db2a5
--- /dev/null
@@ -0,0 +1,126 @@
+// Copyright 2015 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.
+
+// Reject mixing cyclic structure and Drop when using Vec.
+//
+// (Compare against compile-fail/dropck_arr_cycle_checked.rs)
+
+#![feature(const_fn)]
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+#[derive(Debug)]
+struct C<'a> {
+    id: Id,
+    v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>,
+}
+
+impl<'a> HasId for Cell<Option<&'a C<'a>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(c) => c.id.count(),
+        }
+    }
+}
+
+impl<'a> C<'a> {
+    fn new() -> C<'a> {
+        C { id: Id::new(), v: Vec::new() }
+    }
+}
+
+fn f() {
+    let (mut c1, mut c2, mut c3);
+    c1 = C::new();
+    c2 = C::new();
+    c3 = C::new();
+
+    c1.v.push(CheckId(Cell::new(None)));
+    c1.v.push(CheckId(Cell::new(None)));
+    c2.v.push(CheckId(Cell::new(None)));
+    c2.v.push(CheckId(Cell::new(None)));
+    c3.v.push(CheckId(Cell::new(None)));
+    c3.v.push(CheckId(Cell::new(None)));
+
+    c1.v[0].v.set(Some(&c2));
+    c1.v[1].v.set(Some(&c3));
+    c2.v[0].v.set(Some(&c2));
+    c2.v[1].v.set(Some(&c3));
+    c3.v[0].v.set(Some(&c1));
+    c3.v[1].v.set(Some(&c2));
+}
+//~^ ERROR `c2` does not live long enough
+//~| ERROR `c3` does not live long enough
+//~| ERROR `c2` does not live long enough
+//~| ERROR `c3` does not live long enough
+//~| ERROR `c1` does not live long enough
+//~| ERROR `c2` does not live long enough
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr
new file mode 100644 (file)
index 0000000..961ac81
--- /dev/null
@@ -0,0 +1,67 @@
+error: `c2` does not live long enough
+   --> $DIR/dropck_vec_cycle_checked.rs:116:1
+    |
+110 |     c1.v[0].v.set(Some(&c2));
+    |                         -- borrow occurs here
+...
+116 | }
+    | ^ `c2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `c3` does not live long enough
+   --> $DIR/dropck_vec_cycle_checked.rs:116:1
+    |
+111 |     c1.v[1].v.set(Some(&c3));
+    |                         -- borrow occurs here
+...
+116 | }
+    | ^ `c3` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `c2` does not live long enough
+   --> $DIR/dropck_vec_cycle_checked.rs:116:1
+    |
+112 |     c2.v[0].v.set(Some(&c2));
+    |                         -- borrow occurs here
+...
+116 | }
+    | ^ `c2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `c3` does not live long enough
+   --> $DIR/dropck_vec_cycle_checked.rs:116:1
+    |
+113 |     c2.v[1].v.set(Some(&c3));
+    |                         -- borrow occurs here
+...
+116 | }
+    | ^ `c3` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `c1` does not live long enough
+   --> $DIR/dropck_vec_cycle_checked.rs:116:1
+    |
+114 |     c3.v[0].v.set(Some(&c1));
+    |                         -- borrow occurs here
+115 |     c3.v[1].v.set(Some(&c2));
+116 | }
+    | ^ `c1` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `c2` does not live long enough
+   --> $DIR/dropck_vec_cycle_checked.rs:116:1
+    |
+115 |     c3.v[1].v.set(Some(&c2));
+    |                         -- borrow occurs here
+116 | }
+    | ^ `c2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.rs b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.rs
new file mode 100644 (file)
index 0000000..a04edd9
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2015 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.
+
+// This is just checking that we still reject code where temp values
+// are borrowing values for longer than they will be around.
+//
+// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs
+
+use std::cell::RefCell;
+
+fn foo(x: RefCell<String>) -> String {
+    let y = x;
+    y.borrow().clone()
+}
+//~^ ERROR `y` does not live long enough
+
+fn foo2(x: RefCell<String>) -> String {
+    let ret = {
+        let y = x;
+        y.borrow().clone() //~ ERROR `y` does not live long enough
+    };
+    ret
+}
+
+fn main() {
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo(r), "data");
+    let r = RefCell::new(format!("data"));
+    assert_eq!(foo2(r), "data");
+}
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
new file mode 100644 (file)
index 0000000..f10ba0b
--- /dev/null
@@ -0,0 +1,22 @@
+error: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:21:1
+   |
+20 |     y.borrow().clone()
+   |     - borrow occurs here
+21 | }
+   | ^ `y` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `y` does not live long enough
+  --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9
+   |
+27 |         y.borrow().clone() //~ ERROR `y` does not live long enough
+   |         ^ does not live long enough
+28 |     };
+   |     -- borrowed value needs to live until here
+   |     |
+   |     borrowed value only lives until here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.rs b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.rs
new file mode 100644 (file)
index 0000000..acd363f
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2015 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 child trait who only has items via its *parent* trait
+// does cause dropck to inject extra region constraints.
+
+#![allow(non_camel_case_types)]
+
+trait Parent { fn foo(&self); }
+trait Child: Parent { }
+
+impl Parent for i32 { fn foo(&self) { } }
+impl<'a> Parent for &'a D_Child<i32> {
+    fn foo(&self) {
+        println!("accessing child value: {}", self.0);
+    }
+}
+
+impl Child for i32 { }
+impl<'a> Child for &'a D_Child<i32> { }
+
+struct D_Child<T:Child>(T);
+impl <T:Child> Drop for D_Child<T> { fn drop(&mut self) { self.0.foo() } }
+
+fn f_child() {
+    // `_d` and `d1` are assigned the *same* lifetime by region inference ...
+    let (_d, d1);
+
+    d1 = D_Child(1);
+    // ... we store a reference to `d1` within `_d` ...
+    _d = D_Child(&d1);
+
+    // ... dropck *should* complain, because Drop of _d could (and
+    // does) access the already dropped `d1` via the `foo` method.
+}
+//~^ ERROR `d1` does not live long enough
+
+fn main() {
+    f_child();
+}
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
new file mode 100644 (file)
index 0000000..a622e7c
--- /dev/null
@@ -0,0 +1,13 @@
+error: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:42:1
+   |
+38 |     _d = D_Child(&d1);
+   |                   -- borrow occurs here
+...
+42 | }
+   | ^ `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.rs b/src/test/ui/span/issue-24805-dropck-trait-has-items.rs
new file mode 100644 (file)
index 0000000..3deb714
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2015 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 traits with various kinds of associated items cause
+// dropck to inject extra region constraints.
+
+#![allow(non_camel_case_types)]
+
+trait HasSelfMethod { fn m1(&self) { } }
+trait HasMethodWithSelfArg { fn m2(x: &Self) { } }
+trait HasType { type Something; }
+
+impl HasSelfMethod for i32 { }
+impl HasMethodWithSelfArg for i32 { }
+impl HasType for i32 { type Something = (); }
+
+impl<'a,T> HasSelfMethod for &'a T { }
+impl<'a,T> HasMethodWithSelfArg for &'a T { }
+impl<'a,T> HasType for &'a T { type Something = (); }
+
+// e.g. `impl_drop!(Send, D_Send)` expands to:
+//   ```rust
+//   struct D_Send<T:Send>(T);
+//   impl<T:Send> Drop for D_Send<T> { fn drop(&mut self) { } }
+//   ```
+macro_rules! impl_drop {
+    ($Bound:ident, $Id:ident) => {
+        struct $Id<T:$Bound>(T);
+        impl <T:$Bound> Drop for $Id<T> { fn drop(&mut self) { } }
+    }
+}
+
+impl_drop!{HasSelfMethod,        D_HasSelfMethod}
+impl_drop!{HasMethodWithSelfArg, D_HasMethodWithSelfArg}
+impl_drop!{HasType,              D_HasType}
+
+fn f_sm() {
+    let (_d, d1);
+    d1 = D_HasSelfMethod(1);
+    _d = D_HasSelfMethod(&d1);
+}
+//~^ ERROR `d1` does not live long enough
+fn f_mwsa() {
+    let (_d, d1);
+    d1 = D_HasMethodWithSelfArg(1);
+    _d = D_HasMethodWithSelfArg(&d1);
+}
+//~^ ERROR `d1` does not live long enough
+fn f_t() {
+    let (_d, d1);
+    d1 = D_HasType(1);
+    _d = D_HasType(&d1);
+}
+//~^ ERROR `d1` does not live long enough
+
+fn main() {
+    f_sm();
+    f_mwsa();
+    f_t();
+}
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr
new file mode 100644 (file)
index 0000000..d06c8af
--- /dev/null
@@ -0,0 +1,32 @@
+error: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:48:1
+   |
+47 |     _d = D_HasSelfMethod(&d1);
+   |                           -- borrow occurs here
+48 | }
+   | ^ `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:54:1
+   |
+53 |     _d = D_HasMethodWithSelfArg(&d1);
+   |                                  -- borrow occurs here
+54 | }
+   | ^ `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:60:1
+   |
+59 |     _d = D_HasType(&d1);
+   |                     -- borrow occurs here
+60 | }
+   | ^ `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.rs b/src/test/ui/span/issue-24895-copy-clone-dropck.rs
new file mode 100644 (file)
index 0000000..a4207eb
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 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 one cannot subvert Drop Check rule via a user-defined
+// Clone implementation.
+
+#![allow(unused_variables, unused_assignments)]
+
+struct D<T:Copy>(T, &'static str);
+
+#[derive(Copy)]
+struct S<'a>(&'a D<i32>, &'static str);
+impl<'a> Clone for S<'a> {
+    fn clone(&self) -> S<'a> {
+        println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0);
+        S(self.0, self.1)
+    }
+}
+
+impl<T:Copy> Drop for D<T> {
+    fn drop(&mut self) {
+        println!("calling Drop for {}", self.1);
+        let _call = self.0.clone();
+    }
+}
+
+fn main() {
+    let (d2, d1);
+    d1 = D(34, "d1");
+    d2 = D(S(&d1, "inner"), "d2");
+} //~ ERROR `d1` does not live long enough
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr
new file mode 100644 (file)
index 0000000..160bfb6
--- /dev/null
@@ -0,0 +1,12 @@
+error: `d1` does not live long enough
+  --> $DIR/issue-24895-copy-clone-dropck.rs:38:1
+   |
+37 |     d2 = D(S(&d1, "inner"), "d2");
+   |               -- borrow occurs here
+38 | } //~ ERROR `d1` does not live long enough
+   | ^ `d1` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-25199.rs b/src/test/ui/span/issue-25199.rs
new file mode 100644 (file)
index 0000000..b88c58c
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright 2015 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.
+
+// Regression test for Issue 25199: Check that one cannot hide a
+// destructor's access to borrowed data behind a boxed trait object.
+//
+// Prior to fixing Issue 25199, this example was able to be compiled
+// with rustc, and thus when you ran it, you would see the `Drop` impl
+// for `Test` accessing state that had already been dropping (which is
+// marked explicitly here with checking code within the `Drop` impl
+// for `VecHolder`, but in the general case could just do unsound
+// things like accessing memory that has been freed).
+//
+// Note that I would have liked to encode my go-to example of cyclic
+// structure that accesses its neighbors in drop (and thus is
+// fundamentally unsound) via this trick, but the closest I was able
+// to come was dropck_trait_cycle_checked.rs, which is not quite as
+// "good" as this regression test because the encoding of that example
+// was forced to attach a lifetime to the trait definition itself
+// (`trait Obj<'a>`) while *this* example is solely
+
+use std::cell::RefCell;
+
+trait Obj { }
+
+struct VecHolder {
+    v: Vec<(bool, &'static str)>,
+}
+
+impl Drop for VecHolder {
+    fn drop(&mut self) {
+        println!("Dropping Vec");
+        self.v[30].0 = false;
+        self.v[30].1 = "invalid access: VecHolder dropped already";
+    }
+}
+
+struct Container<'a> {
+    v: VecHolder,
+    d: RefCell<Vec<Box<Obj+'a>>>,
+}
+
+impl<'a> Container<'a> {
+    fn new() -> Container<'a> {
+        Container {
+            d: RefCell::new(Vec::new()),
+            v: VecHolder {
+                v: vec![(true, "valid"); 100]
+            }
+        }
+    }
+
+    fn store<T: Obj+'a>(&'a self, val: T) {
+        self.d.borrow_mut().push(Box::new(val));
+    }
+}
+
+struct Test<'a> {
+    test: &'a Container<'a>,
+}
+
+impl<'a> Obj for Test<'a> { }
+impl<'a> Drop for Test<'a> {
+    fn drop(&mut self) {
+        for e in &self.test.v.v {
+            assert!(e.0, e.1);
+        }
+    }
+}
+
+fn main() {
+    let container = Container::new();
+    let test = Test{test: &container};
+    println!("container.v[30]: {:?}", container.v.v[30]);
+    container.store(test);
+}
+//~^ ERROR `container` does not live long enough
+//~| ERROR `container` does not live long enough
diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr
new file mode 100644 (file)
index 0000000..3c8ee07
--- /dev/null
@@ -0,0 +1,23 @@
+error: `container` does not live long enough
+  --> $DIR/issue-25199.rs:83:1
+   |
+80 |     let test = Test{test: &container};
+   |                            --------- borrow occurs here
+...
+83 | }
+   | ^ `container` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `container` does not live long enough
+  --> $DIR/issue-25199.rs:83:1
+   |
+82 |     container.store(test);
+   |     --------- borrow occurs here
+83 | }
+   | ^ `container` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue-26656.rs b/src/test/ui/span/issue-26656.rs
new file mode 100644 (file)
index 0000000..621da47
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2015 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.
+
+// Issue #26656: Verify that trait objects cannot bypass dropck.
+
+// Using this instead of Fn etc. to take HRTB out of the equation.
+trait Trigger<B> { fn fire(&self, b: &mut B); }
+impl<B: Button> Trigger<B> for () {
+    fn fire(&self, b: &mut B) {
+        b.push();
+    }
+}
+
+// Still unsound Zook
+trait Button { fn push(&self); }
+struct Zook<B> { button: B, trigger: Box<Trigger<B>+'static> }
+
+impl<B> Drop for Zook<B> {
+    fn drop(&mut self) {
+        self.trigger.fire(&mut self.button);
+    }
+}
+
+// AND
+struct Bomb { usable: bool }
+impl Drop for Bomb { fn drop(&mut self) { self.usable = false; } }
+impl Bomb { fn activate(&self) { assert!(self.usable) } }
+
+enum B<'a> { HarmlessButton, BigRedButton(&'a Bomb) }
+impl<'a> Button for B<'a> {
+    fn push(&self) {
+        if let B::BigRedButton(borrowed) = *self {
+            borrowed.activate();
+        }
+    }
+}
+
+fn main() {
+    let (mut zook, ticking);
+    zook = Zook { button: B::HarmlessButton,
+                  trigger: Box::new(()) };
+    ticking = Bomb { usable: true };
+    zook.button = B::BigRedButton(&ticking);
+}
+//~^ ERROR `ticking` does not live long enough
diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr
new file mode 100644 (file)
index 0000000..f960844
--- /dev/null
@@ -0,0 +1,12 @@
+error: `ticking` does not live long enough
+  --> $DIR/issue-26656.rs:51:1
+   |
+50 |     zook.button = B::BigRedButton(&ticking);
+   |                                    ------- borrow occurs here
+51 | }
+   | ^ `ticking` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-29106.rs b/src/test/ui/span/issue-29106.rs
new file mode 100644 (file)
index 0000000..8d28c64
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Foo<'a>(&'a String);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        println!("{:?}", self.0);
+    }
+}
+
+fn main() {
+    {
+        let (y, x);
+        x = "alive".to_string();
+        y = Arc::new(Foo(&x));
+    } //~ ERROR `x` does not live long enough
+
+    {
+        let (y, x);
+        x = "alive".to_string();
+        y = Rc::new(Foo(&x));
+    } //~ ERROR `x` does not live long enough
+}
diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr
new file mode 100644 (file)
index 0000000..a7d3b84
--- /dev/null
@@ -0,0 +1,22 @@
+error: `x` does not live long enough
+  --> $DIR/issue-29106.rs:27:5
+   |
+26 |         y = Arc::new(Foo(&x));
+   |                           - borrow occurs here
+27 |     } //~ ERROR `x` does not live long enough
+   |     ^ `x` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `x` does not live long enough
+  --> $DIR/issue-29106.rs:33:5
+   |
+32 |         y = Rc::new(Foo(&x));
+   |                          - borrow occurs here
+33 |     } //~ ERROR `x` does not live long enough
+   |     ^ `x` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue-36537.rs b/src/test/ui/span/issue-36537.rs
new file mode 100644 (file)
index 0000000..33182e0
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+fn main() {
+    let p;
+    let a = 42;
+    p = &a; //~ NOTE borrow occurs here
+}
+//~^ ERROR `a` does not live long enough
+//~| NOTE `a` dropped here while still borrowed
+//~| NOTE values in a scope are dropped in the opposite order they are created
diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr
new file mode 100644 (file)
index 0000000..a335194
--- /dev/null
@@ -0,0 +1,12 @@
+error: `a` does not live long enough
+  --> $DIR/issue-36537.rs:15:1
+   |
+14 |     p = &a; //~ NOTE borrow occurs here
+   |          - borrow occurs here
+15 | }
+   | ^ `a` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue28498-reject-ex1.rs b/src/test/ui/span/issue28498-reject-ex1.rs
new file mode 100644 (file)
index 0000000..bed7680
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 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.
+
+// Example taken from RFC 1238 text
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #examples-of-code-that-will-start-to-be-rejected
+
+// Compare against test/run-pass/issue28498-must-work-ex2.rs
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+fn potentially_specialized_wrt_t<T>(t: &T) {
+    // Hypothetical code that does one thing for generic T and then is
+    // specialized for T == Concrete (and the specialized form can
+    // then access a reference held in concrete tuple).
+    //
+    // (We don't have specialization yet, but we want to allow for it
+    // in the future.)
+}
+
+impl<T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        potentially_specialized_wrt_t(&self.data[0])
+    }
+}
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    foo.data[1].1.set(Some(&foo.data[0]));
+}
+//~^ ERROR `foo.data` does not live long enough
+//~| ERROR `foo.data` does not live long enough
diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr
new file mode 100644 (file)
index 0000000..b5fbe99
--- /dev/null
@@ -0,0 +1,23 @@
+error: `foo.data` does not live long enough
+  --> $DIR/issue28498-reject-ex1.rs:46:1
+   |
+44 |     foo.data[0].1.set(Some(&foo.data[1]));
+   |                             -------- borrow occurs here
+45 |     foo.data[1].1.set(Some(&foo.data[0]));
+46 | }
+   | ^ `foo.data` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `foo.data` does not live long enough
+  --> $DIR/issue28498-reject-ex1.rs:46:1
+   |
+45 |     foo.data[1].1.set(Some(&foo.data[0]));
+   |                             -------- borrow occurs here
+46 | }
+   | ^ `foo.data` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.rs b/src/test/ui/span/issue28498-reject-lifetime-param.rs
new file mode 100644 (file)
index 0000000..7e7893a
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 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.
+
+// Demonstrate that having a lifetime param causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<'a>(u32, &'a ScribbleOnDrop);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because destructor accesses borrowed data in `self.1`
+        // and we must force that to strictly outlive `self`.
+        println!("Dropping Foo({}, {:?})", self.0, self.1);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    foo1 = Foo(1, &first_dropped);
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
+//~^ ERROR `last_dropped` does not live long enough
+//~| ERROR `first_dropped` does not live long enough
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr
new file mode 100644 (file)
index 0000000..debb835
--- /dev/null
@@ -0,0 +1,24 @@
+error: `last_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:46:1
+   |
+42 |     foo0 = Foo(0, &last_dropped);
+   |                    ------------ borrow occurs here
+...
+46 | }
+   | ^ `last_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:46:1
+   |
+43 |     foo1 = Foo(1, &first_dropped);
+   |                    ------------- borrow occurs here
+...
+46 | }
+   | ^ `first_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.rs b/src/test/ui/span/issue28498-reject-passed-to-fn.rs
new file mode 100644 (file)
index 0000000..54fc20b
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+impl<T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because we pass `T` to the callback in `self.2`
+        // below, and thus potentially read from borrowed data.
+        println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
+    }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped, Box::new(callback));
+    foo1 = Foo(1, &first_dropped, Box::new(callback));
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
+//~^ ERROR `last_dropped` does not live long enough
+//~| ERROR `first_dropped` does not live long enough
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr
new file mode 100644 (file)
index 0000000..7d3ac3e
--- /dev/null
@@ -0,0 +1,24 @@
+error: `last_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:48:1
+   |
+44 |     foo0 = Foo(0, &last_dropped, Box::new(callback));
+   |                    ------------ borrow occurs here
+...
+48 | }
+   | ^ `last_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:48:1
+   |
+45 |     foo1 = Foo(1, &first_dropped, Box::new(callback));
+   |                    ------------- borrow occurs here
+...
+48 | }
+   | ^ `first_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.rs b/src/test/ui/span/issue28498-reject-trait-bound.rs
new file mode 100644 (file)
index 0000000..6164bea
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+// Demonstrate that having a trait bound causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs
+
+use std::fmt;
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T:fmt::Debug>(u32, T);
+
+impl<T:fmt::Debug> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because we access `T` fmt method when we pass `self.1`
+        // below, and thus potentially read from borrowed data.
+        println!("Dropping Foo({}, {:?})", self.0, self.1);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    foo1 = Foo(1, &first_dropped);
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
+//~^ ERROR `last_dropped` does not live long enough
+//~| ERROR `first_dropped` does not live long enough
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr
new file mode 100644 (file)
index 0000000..ae96cac
--- /dev/null
@@ -0,0 +1,24 @@
+error: `last_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.rs:48:1
+   |
+44 |     foo0 = Foo(0, &last_dropped);
+   |                    ------------ borrow occurs here
+...
+48 | }
+   | ^ `last_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.rs:48:1
+   |
+45 |     foo1 = Foo(1, &first_dropped);
+   |                    ------------- borrow occurs here
+...
+48 | }
+   | ^ `first_dropped` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/loan-extend.rs b/src/test/ui/span/loan-extend.rs
new file mode 100644 (file)
index 0000000..a4b951d
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+#![feature(conservative_impl_trait)]
+
+// Helper creating a fake borrow, captured by the impl Trait.
+fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () }
+
+fn main() {
+    let long;
+    let mut short = 0;
+    long = borrow(&mut short);
+    //~^ NOTE borrow occurs here
+}
+//~^ ERROR `short` does not live long enough
+//~| NOTE `short` dropped here while still borrowed
+//~| NOTE values in a scope are dropped in the opposite order they are created
diff --git a/src/test/ui/span/loan-extend.stderr b/src/test/ui/span/loan-extend.stderr
new file mode 100644 (file)
index 0000000..b0f191e
--- /dev/null
@@ -0,0 +1,13 @@
+error: `short` does not live long enough
+  --> $DIR/loan-extend.rs:21:1
+   |
+19 |     long = borrow(&mut short);
+   |                        ----- borrow occurs here
+20 |     //~^ NOTE borrow occurs here
+21 | }
+   | ^ `short` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs b/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
new file mode 100644 (file)
index 0000000..310ab20
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2015 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.
+
+// Checking that `Vec<T>` cannot hide lifetimes within `T` when `T`
+// implements `Drop` and might access methods of values that have
+// since been deallocated.
+//
+// In this case, the values in question hold (non-zero) unique-ids
+// that zero themselves out when dropped, and are wrapped in another
+// type with a destructor that asserts that the ids it references are
+// indeed non-zero (i.e., effectively checking that the id's are not
+// dropped while there are still any outstanding references).
+//
+// However, the values in question are also formed into a
+// cyclic-structure, ensuring that there is no way for all of the
+// conditions above to be satisfied, meaning that if the dropck is
+// sound, it should reject this code.
+
+#![feature(const_fn)]
+
+use std::cell::Cell;
+use id::Id;
+
+mod s {
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    static S_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+    /// generates globally unique count (global across the current
+    /// process, that is)
+    pub fn next_count() -> usize {
+        S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
+    }
+}
+
+mod id {
+    use s;
+
+    /// Id represents a globally unique identifier (global across the
+    /// current process, that is). When dropped, it automatically
+    /// clears its `count` field, but leaves `orig_count` untouched,
+    /// so that if there are subsequent (erroneous) invocations of its
+    /// method (which is unsound), we can observe it by seeing that
+    /// the `count` is 0 while the `orig_count` is non-zero.
+    #[derive(Debug)]
+    pub struct Id {
+        orig_count: usize,
+        count: usize,
+    }
+
+    impl Id {
+        /// Creates an `Id` with a globally unique count.
+        pub fn new() -> Id {
+            let c = s::next_count();
+            println!("building Id {}", c);
+            Id { orig_count: c, count: c }
+        }
+        /// returns the `count` of self; should be non-zero if
+        /// everything is working.
+        pub fn count(&self) -> usize {
+            println!("Id::count on {} returns {}", self.orig_count, self.count);
+            self.count
+        }
+    }
+
+    impl Drop for Id {
+        fn drop(&mut self) {
+            println!("dropping Id {}", self.count);
+            self.count = 0;
+        }
+    }
+}
+
+trait HasId {
+    fn count(&self) -> usize;
+}
+
+#[derive(Debug)]
+struct CheckId<T:HasId> {
+    v: T
+}
+
+#[allow(non_snake_case)]
+fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
+
+impl<T:HasId> Drop for CheckId<T> {
+    fn drop(&mut self) {
+        assert!(self.v.count() > 0);
+    }
+}
+
+#[derive(Debug)]
+struct C<'a> {
+    id: Id,
+    v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>,
+}
+
+impl<'a> HasId for Cell<Option<&'a C<'a>>> {
+    fn count(&self) -> usize {
+        match self.get() {
+            None => 1,
+            Some(c) => c.id.count(),
+        }
+    }
+}
+
+impl<'a> C<'a> {
+    fn new() -> C<'a> {
+        C { id: Id::new(), v: Vec::new() }
+    }
+}
+
+fn f() {
+    let (mut c1, mut c2);
+    c1 = C::new();
+    c2 = C::new();
+
+    c1.v.push(CheckId(Cell::new(None)));
+    c2.v.push(CheckId(Cell::new(None)));
+    c1.v[0].v.set(Some(&c2));
+    c2.v[0].v.set(Some(&c1));
+}
+//~^ ERROR `c2` does not live long enough
+//~| ERROR `c1` does not live long enough
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr
new file mode 100644 (file)
index 0000000..11031ee
--- /dev/null
@@ -0,0 +1,23 @@
+error: `c2` does not live long enough
+   --> $DIR/vec-must-not-hide-type-from-dropck.rs:129:1
+    |
+127 |     c1.v[0].v.set(Some(&c2));
+    |                         -- borrow occurs here
+128 |     c2.v[0].v.set(Some(&c1));
+129 | }
+    | ^ `c2` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: `c1` does not live long enough
+   --> $DIR/vec-must-not-hide-type-from-dropck.rs:129:1
+    |
+128 |     c2.v[0].v.set(Some(&c1));
+    |                         -- borrow occurs here
+129 | }
+    | ^ `c1` dropped here while still borrowed
+    |
+    = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.rs b/src/test/ui/span/vec_refs_data_with_early_death.rs
new file mode 100644 (file)
index 0000000..f40a259
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+// This test is a simple example of code that violates the dropck
+// rules: it pushes `&x` and `&y` into `v`, but the referenced data
+// will be dropped before the vector itself is.
+
+// (In principle we know that `Vec` does not reference the data it
+//  owns from within its drop code, apart from calling drop on each
+//  element it owns; thus, for data like this, it seems like we could
+//  loosen the restrictions here if we wanted. But it also is not
+//  clear whether such loosening is terribly important.)
+
+fn main() {
+    let mut v = Vec::new();
+
+    let x: i8 = 3;
+    let y: i8 = 4;
+
+    v.push(&x);
+    v.push(&y);
+
+    assert_eq!(v, [&3, &4]);
+}
+//~^ ERROR `x` does not live long enough
+//~| ERROR `y` does not live long enough
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr
new file mode 100644 (file)
index 0000000..8cc12c3
--- /dev/null
@@ -0,0 +1,24 @@
+error: `x` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:31:1
+   |
+27 |     v.push(&x);
+   |             - borrow occurs here
+...
+31 | }
+   | ^ `x` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: `y` does not live long enough
+  --> $DIR/vec_refs_data_with_early_death.rs:31:1
+   |
+28 |     v.push(&y);
+   |             - borrow occurs here
+...
+31 | }
+   | ^ `y` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 2 previous errors
+