Skip to content

Commit 73f35cf

Browse files
committed
Added tests illustrating when and when not to use the UGEH attribute w.r.t. types in negative position.
1 parent 7eda5b5 commit 73f35cf

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Demonstrate that a type param in negative position causes dropck to reject code
12+
// that might indirectly access previously dropped value.
13+
//
14+
// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
15+
16+
#[derive(Debug)]
17+
struct ScribbleOnDrop(String);
18+
19+
impl Drop for ScribbleOnDrop {
20+
fn drop(&mut self) {
21+
self.0 = format!("DROPPED");
22+
}
23+
}
24+
25+
struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
26+
27+
impl<T> Drop for Foo<T> {
28+
#[unsafe_destructor_blind_to_params]
29+
fn drop(&mut self) {
30+
// Use of `unsafe_destructor_blind_to_params` is unsound,
31+
// because we pass `T` to the callback in `self.2`
32+
// below, and thus potentially read from borrowed data.
33+
println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
34+
}
35+
}
36+
37+
fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
38+
39+
fn main() {
40+
let (last_dropped, foo0);
41+
let (foo1, first_dropped);
42+
43+
last_dropped = ScribbleOnDrop(format!("last"));
44+
first_dropped = ScribbleOnDrop(format!("first"));
45+
foo0 = Foo(0, &last_dropped, Box::new(callback));
46+
//~^ ERROR `last_dropped` does not live long enough
47+
foo1 = Foo(1, &first_dropped, Box::new(callback));
48+
//~^ ERROR `first_dropped` does not live long enough
49+
50+
println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Demonstrate the use of the unguarded escape hatch with a type param in negative position
12+
// to assert that destructor will not access any dead data.
13+
//
14+
// Compare with compile-fail/issue28498-reject-lifetime-param.rs
15+
16+
// Demonstrate that a type param in negative position causes dropck to reject code
17+
// that might indirectly access previously dropped value.
18+
//
19+
// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
20+
21+
#![feature(dropck_parametricity)]
22+
23+
#[derive(Debug)]
24+
struct ScribbleOnDrop(String);
25+
26+
impl Drop for ScribbleOnDrop {
27+
fn drop(&mut self) {
28+
self.0 = format!("DROPPED");
29+
}
30+
}
31+
32+
struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
33+
34+
impl<T> Drop for Foo<T> {
35+
#[unsafe_destructor_blind_to_params]
36+
fn drop(&mut self) {
37+
// Use of `unsafe_destructor_blind_to_params` is sound,
38+
// because destructor never passes a `self.1` to the callback
39+
// (in `self.2`) despite having it available.
40+
println!("Dropping Foo({}, _)", self.0);
41+
}
42+
}
43+
44+
fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
45+
46+
fn main() {
47+
let (last_dropped, foo0);
48+
let (foo1, first_dropped);
49+
50+
last_dropped = ScribbleOnDrop(format!("last"));
51+
first_dropped = ScribbleOnDrop(format!("first"));
52+
foo0 = Foo(0, &last_dropped, Box::new(callback));
53+
foo1 = Foo(1, &first_dropped, Box::new(callback));
54+
55+
println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
56+
}

0 commit comments

Comments
 (0)