}
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
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");
}
fn main() {
let arena = TypedArena::new();
- f(&arena); //~ ERROR `arena` does not live long enough
-}
+ f(&arena);
+} //~ ERROR `arena` does not live long enough
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
+
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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.
-}
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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() }
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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");
-}
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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
-}
+++ /dev/null
-// 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
-}
+++ /dev/null
-// 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
-}
+++ /dev/null
-// 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
- }
-}
+++ /dev/null
-// 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
-}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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]);
-}
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
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
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
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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
+
--- /dev/null
+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
+
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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() }
--- /dev/null
+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
+
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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");
+}
--- /dev/null
+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
+
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
+}
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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();
+}
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+