diff options
| author | bors <bors@rust-lang.org> | 2015-10-10 00:39:29 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-10-10 00:39:29 +0000 |
| commit | 87cd2c08273dec5c8db8e59f4231b8e69aa9b85b (patch) | |
| tree | 24c7c70c06fbcd88be686bcf4e11d5ffc10aa27c /src/test | |
| parent | 439311d9382abd5d22c9068f3f158d3b9ef6d1c9 (diff) | |
| parent | a445f234a64cdbbf946af012b94dccf91447b5ff (diff) | |
| download | rust-87cd2c08273dec5c8db8e59f4231b8e69aa9b85b.tar.gz rust-87cd2c08273dec5c8db8e59f4231b8e69aa9b85b.zip | |
Auto merge of #28861 - pnkfelix:fsk-nonparam-dropck-issue28498, r=arielb1
implement RFC 1238: nonparametric dropck. cc #28498 cc @nikomatsakis
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/compile-fail/feature-gate-dropck-ugeh.rs | 40 | ||||
| -rw-r--r-- | src/test/compile-fail/issue28498-reject-ex1.rs | 48 | ||||
| -rw-r--r-- | src/test/compile-fail/issue28498-reject-lifetime-param.rs | 48 | ||||
| -rw-r--r-- | src/test/compile-fail/issue28498-reject-passed-to-fn.rs | 50 | ||||
| -rw-r--r-- | src/test/compile-fail/issue28498-reject-trait-bound.rs | 50 | ||||
| -rw-r--r-- | src/test/run-pass/issue-24805-dropck-itemless.rs | 7 | ||||
| -rw-r--r-- | src/test/run-pass/issue28498-must-work-ex1.rs | 27 | ||||
| -rw-r--r-- | src/test/run-pass/issue28498-must-work-ex2.rs | 30 | ||||
| -rw-r--r-- | src/test/run-pass/issue28498-ugeh-ex1.rs | 37 | ||||
| -rw-r--r-- | src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs | 48 | ||||
| -rw-r--r-- | src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs | 56 | ||||
| -rw-r--r-- | src/test/run-pass/issue28498-ugeh-with-trait-bound.rs | 51 |
12 files changed, 491 insertions, 1 deletions
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs new file mode 100644 index 00000000000..aa479a987a3 --- /dev/null +++ b/src/test/compile-fail/feature-gate-dropck-ugeh.rs @@ -0,0 +1,40 @@ +// 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. + +// Ensure that attempts to use the unsafe attribute are feature-gated. + +// Example adapted from RFC 1238 text (just left out the feature gate). + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #example-of-the-unguarded-escape-hatch + +// #![feature(dropck_parametricity)] + +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); + +struct Foo<T> { data: Vec<T> } + +impl<T> Drop for Foo<T> { + #[unsafe_destructor_blind_to_params] // This is the UGEH attribute + //~^ ERROR unsafe_destructor_blind_to_params has unstable semantics + fn drop(&mut self) { } +} + +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])); +} + diff --git a/src/test/compile-fail/issue28498-reject-ex1.rs b/src/test/compile-fail/issue28498-reject-ex1.rs new file mode 100644 index 00000000000..cee7c57c201 --- /dev/null +++ b/src/test/compile-fail/issue28498-reject-ex1.rs @@ -0,0 +1,48 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #examples-of-code-that-will-start-to-be-rejected + +// Compare against test/run-pass/issue28498-must-work-ex2.rs + +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); + +struct Foo<T> { data: Vec<T> } + +fn potentially_specialized_wrt_t<T>(t: &T) { + // Hypothetical code that does one thing for generic T and then is + // specialized for T == Concrete (and the specialized form can + // then access a reference held in concrete tuple). + // + // (We don't have specialization yet, but we want to allow for it + // in the future.) +} + +impl<T> Drop for Foo<T> { + fn drop(&mut self) { + potentially_specialized_wrt_t(&self.data[0]) + } +} + +fn main() { + let mut foo = Foo { data: Vec::new() }; + foo.data.push(Concrete(0, Cell::new(None))); + foo.data.push(Concrete(0, Cell::new(None))); + + foo.data[0].1.set(Some(&foo.data[1])); + //~^ ERROR `foo.data` does not live long enough + foo.data[1].1.set(Some(&foo.data[0])); + //~^ ERROR `foo.data` does not live long enough +} diff --git a/src/test/compile-fail/issue28498-reject-lifetime-param.rs b/src/test/compile-fail/issue28498-reject-lifetime-param.rs new file mode 100644 index 00000000000..92028c7a818 --- /dev/null +++ b/src/test/compile-fail/issue28498-reject-lifetime-param.rs @@ -0,0 +1,48 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Demonstrate that having a lifetime param causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<'a>(u32, &'a ScribbleOnDrop); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + // Use of `unsafe_destructor_blind_to_params` is unsound, + // because destructor accesses borrowed data in `self.1` + // and we must force that to strictly outlive `self`. + println!("Dropping Foo({}, {:?})", self.0, self.1); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); + //~^ ERROR `last_dropped` does not live long enough + foo1 = Foo(1, &first_dropped); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/src/test/compile-fail/issue28498-reject-passed-to-fn.rs b/src/test/compile-fail/issue28498-reject-passed-to-fn.rs new file mode 100644 index 00000000000..27378b1e0be --- /dev/null +++ b/src/test/compile-fail/issue28498-reject-passed-to-fn.rs @@ -0,0 +1,50 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Demonstrate that a type param in negative position causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>); + +impl<T> Drop for Foo<T> { + fn drop(&mut self) { + // Use of `unsafe_destructor_blind_to_params` is unsound, + // because we pass `T` to the callback in `self.2` + // below, and thus potentially read from borrowed data. + println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1)); + } +} + +fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) } + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped, Box::new(callback)); + //~^ ERROR `last_dropped` does not live long enough + foo1 = Foo(1, &first_dropped, Box::new(callback)); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/src/test/compile-fail/issue28498-reject-trait-bound.rs b/src/test/compile-fail/issue28498-reject-trait-bound.rs new file mode 100644 index 00000000000..3904d68ba19 --- /dev/null +++ b/src/test/compile-fail/issue28498-reject-trait-bound.rs @@ -0,0 +1,50 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Demonstrate that having a trait bound causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs + +use std::fmt; + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<T:fmt::Debug>(u32, T); + +impl<T:fmt::Debug> Drop for Foo<T> { + fn drop(&mut self) { + // Use of `unsafe_destructor_blind_to_params` is unsound, + // because we access `T` fmt method when we pass `self.1` + // below, and thus potentially read from borrowed data. + println!("Dropping Foo({}, {:?})", self.0, self.1); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); + //~^ ERROR `last_dropped` does not live long enough + foo1 = Foo(1, &first_dropped); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/src/test/run-pass/issue-24805-dropck-itemless.rs b/src/test/run-pass/issue-24805-dropck-itemless.rs index 4512bcc2000..9fa48202298 100644 --- a/src/test/run-pass/issue-24805-dropck-itemless.rs +++ b/src/test/run-pass/issue-24805-dropck-itemless.rs @@ -13,6 +13,8 @@ #![allow(non_camel_case_types)] +#![feature(dropck_parametricity)] + trait UserDefined { } impl UserDefined for i32 { } @@ -26,7 +28,10 @@ impl<'a, T> UserDefined for &'a T { } 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 <T:$Bound> Drop for $Id<T> { + #[unsafe_destructor_blind_to_params] + fn drop(&mut self) { } + } } } diff --git a/src/test/run-pass/issue28498-must-work-ex1.rs b/src/test/run-pass/issue28498-must-work-ex1.rs new file mode 100644 index 00000000000..83a978d57b9 --- /dev/null +++ b/src/test/run-pass/issue28498-must-work-ex1.rs @@ -0,0 +1,27 @@ +// 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-must-continue-to-work + +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); + +fn main() { + let mut data = Vec::new(); + data.push(Concrete(0, Cell::new(None))); + data.push(Concrete(0, Cell::new(None))); + + data[0].1.set(Some(&data[1])); + data[1].1.set(Some(&data[0])); +} diff --git a/src/test/run-pass/issue28498-must-work-ex2.rs b/src/test/run-pass/issue28498-must-work-ex2.rs new file mode 100644 index 00000000000..93652a1b612 --- /dev/null +++ b/src/test/run-pass/issue28498-must-work-ex2.rs @@ -0,0 +1,30 @@ +// 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-must-continue-to-work + +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); + +struct Foo<T> { data: Vec<T> } + +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])); +} + diff --git a/src/test/run-pass/issue28498-ugeh-ex1.rs b/src/test/run-pass/issue28498-ugeh-ex1.rs new file mode 100644 index 00000000000..b07831f552c --- /dev/null +++ b/src/test/run-pass/issue28498-ugeh-ex1.rs @@ -0,0 +1,37 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #example-of-the-unguarded-escape-hatch + +#![feature(dropck_parametricity)] +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); + +struct Foo<T> { data: Vec<T> } + +impl<T> Drop for Foo<T> { + // Below is the UGEH attribute + #[unsafe_destructor_blind_to_params] + fn drop(&mut self) { } +} + +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])); +} + diff --git a/src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs b/src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs new file mode 100644 index 00000000000..19be2568e4f --- /dev/null +++ b/src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs @@ -0,0 +1,48 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Demonstrate the use of the unguarded escape hatch with a lifetime param +// to assert that destructor will not access any dead data. +// +// Compare with compile-fail/issue28498-reject-lifetime-param.rs + +#![feature(dropck_parametricity)] + +#[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> { + #[unsafe_destructor_blind_to_params] + fn drop(&mut self) { + // Use of `unsafe_destructor_blind_to_params` is sound, + // because destructor never accesses `self.1`. + println!("Dropping Foo({}, _)", self.0); + } +} + +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); +} diff --git a/src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs b/src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs new file mode 100644 index 00000000000..bb430ea3e33 --- /dev/null +++ b/src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs @@ -0,0 +1,56 @@ +// 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 the use of the unguarded escape hatch with a type param in negative position +// to assert that destructor will not access any dead data. +// +// Compare with compile-fail/issue28498-reject-lifetime-param.rs + +// 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 + +#![feature(dropck_parametricity)] + +#[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> { + #[unsafe_destructor_blind_to_params] + fn drop(&mut self) { + // Use of `unsafe_destructor_blind_to_params` is sound, + // because destructor never passes a `self.1` to the callback + // (in `self.2`) despite having it available. + println!("Dropping Foo({}, _)", self.0); + } +} + +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); +} diff --git a/src/test/run-pass/issue28498-ugeh-with-trait-bound.rs b/src/test/run-pass/issue28498-ugeh-with-trait-bound.rs new file mode 100644 index 00000000000..2e9633b3a21 --- /dev/null +++ b/src/test/run-pass/issue28498-ugeh-with-trait-bound.rs @@ -0,0 +1,51 @@ +// 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 the use of the unguarded escape hatch with a trait bound +// to assert that destructor will not access any dead data. +// +// Compare with compile-fail/issue28498-reject-trait-bound.rs + +#![feature(dropck_parametricity)] + +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> { + #[unsafe_destructor_blind_to_params] + fn drop(&mut self) { + // Use of `unsafe_destructor_blind_to_params` is sound, + // because destructor never accesses the `Debug::fmt` method + // of `T`, despite having it available. + println!("Dropping Foo({}, _)", self.0); + } +} + +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); +} |
