This commit only applies the flag to the one test case,
ui/span/dropck_vec_cycle_checked.rs, that absolutely needs it. Without
the flag, that test takes an unknown amount of time (greater than 1
minute) to compile. But its possible that other tests would also
benefit from the flag, and we may want to make it the default (after
evaluating its impact on other tests).
In terms of its known impact on other tests, I have only evaluated the
ui tests, and the *only* ui test I have found that the flag impacts
(running under NLL mode, of course), is src/test/ui/nll/issue-31567.rs
In particular:
```
% ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/nll/issue-31567.rs
error[E0597]: `*v.0` does not live long enough
--> ../src/test/ui/nll/issue-31567.rs:22:26
|
22 | let s_inner: &'a S = &*v.0; //~ ERROR `*v.0` does not live long enough
| ^^^^^ borrowed value does not live long enough
23 | &s_inner.0
24 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 21:1...
--> ../src/test/ui/nll/issue-31567.rs:21:1
|
21 | fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
% ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/nll/issue-31567.rs -Z nll-subminimal-causes
error[E0597]: `*v.0` does not live long enough
--> ../src/test/ui/nll/issue-31567.rs:22:26
|
22 | let s_inner: &'a S = &*v.0; //~ ERROR `*v.0` does not live long enough
| ^^^^^ borrowed value does not live long enough
23 | &s_inner.0
24 | }
| -
| |
| borrowed value only lives until here
| borrow later used here, when `v` is dropped
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
%
```
129 lines
3 KiB
Rust
129 lines
3 KiB
Rust
// 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.
|
|
|
|
// compile-flags: -Z nll-subminimal-causes
|
|
// (Work around rust-lang/rust#49998 by opting into nll-subminimal-causes.)
|
|
|
|
// Reject mixing cyclic structure and Drop when using Vec.
|
|
//
|
|
// (Compare against compile-fail/dropck_arr_cycle_checked.rs)
|
|
|
|
|
|
|
|
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();
|
|
}
|