Test for restricting capture precision

This commit is contained in:
Aman Arora 2020-12-14 03:09:17 -05:00
parent 1373f988fa
commit 0897db5609
12 changed files with 657 additions and 0 deletions

View file

@ -0,0 +1,41 @@
// Test that we handle derferences properly when only some of the captures are being moved with
// `capture_disjoint_fields` enabled.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
//~| NOTE: `#[warn(incomplete_features)]` on by default
//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
#![feature(rustc_attrs)]
#[derive(Debug, Default)]
struct SomeLargeType;
struct MuchLargerType([SomeLargeType; 32]);
// Ensure that we don't capture any derefs when moving captures into the closures,
// i.e. only data from the enclosing stack is moved.
fn big_box() {
let s = MuchLargerType(Default::default());
let b = Box::new(s);
let t = (b, 10);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
let p = t.0.0;
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
println!("{} {:?}", t.1, p);
//~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow
//~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
};
c();
}
fn main() {
big_box();
}

View file

@ -0,0 +1,67 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/by_value.rs:22:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/by_value.rs:5:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
error: First Pass analysis includes:
--> $DIR/by_value.rs:25:5
|
LL | / || {
LL | |
LL | |
LL | | let p = t.0.0;
... |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
--> $DIR/by_value.rs:28:17
|
LL | let p = t.0.0;
| ^^^^^
note: Capturing t[(1, 0)] -> ImmBorrow
--> $DIR/by_value.rs:31:29
|
LL | println!("{} {:?}", t.1, p);
| ^^^
error: Min Capture analysis includes:
--> $DIR/by_value.rs:25:5
|
LL | / || {
LL | |
LL | |
LL | | let p = t.0.0;
... |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0)] -> ByValue
--> $DIR/by_value.rs:28:17
|
LL | let p = t.0.0;
| ^^^^^
note: Min Capture t[(1, 0)] -> ImmBorrow
--> $DIR/by_value.rs:31:29
|
LL | println!("{} {:?}", t.1, p);
| ^^^
error: aborting due to 3 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,72 @@
// Test that move closures drop derefs with `capture_disjoint_fields` enabled.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
//~| NOTE: `#[warn(incomplete_features)]` on by default
//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
#![feature(rustc_attrs)]
// Test we truncate derefs properly
fn simple_ref() {
let mut s = 10;
let ref_s = &mut s;
let mut c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
move || {
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
*ref_s += 10;
//~^ NOTE: Capturing ref_s[Deref] -> ByValue
//~| NOTE: Min Capture ref_s[] -> ByValue
};
c();
}
// Test we truncate derefs properly
fn struct_contains_ref_to_another_struct() {
struct S(String);
struct T<'a>(&'a mut S);
let mut s = S("s".into());
let t = T(&mut s);
let mut c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
move || {
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
t.0.0 = "new s".into();
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
};
c();
}
// Test that we don't reduce precision when there is nothing deref.
fn no_ref() {
struct S(String);
struct T(S);
let t = T(S("s".into()));
let mut c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
move || {
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
t.0.0 = "new S".into();
//~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue
//~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
};
c();
}
fn main() {
simple_ref();
struct_contains_ref_to_another_struct();
no_ref();
}

View file

@ -0,0 +1,147 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:14:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:35:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:55:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/move_closure.rs:3:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
error: First Pass analysis includes:
--> $DIR/move_closure.rs:17:5
|
LL | / move || {
LL | |
LL | |
LL | | *ref_s += 10;
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing ref_s[Deref] -> ByValue
--> $DIR/move_closure.rs:20:9
|
LL | *ref_s += 10;
| ^^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:17:5
|
LL | / move || {
LL | |
LL | |
LL | | *ref_s += 10;
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture ref_s[] -> ByValue
--> $DIR/move_closure.rs:20:9
|
LL | *ref_s += 10;
| ^^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:38:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new s".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
--> $DIR/move_closure.rs:41:9
|
LL | t.0.0 = "new s".into();
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:38:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new s".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0)] -> ByValue
--> $DIR/move_closure.rs:41:9
|
LL | t.0.0 = "new s".into();
| ^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:58:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new S".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),(0, 0)] -> ByValue
--> $DIR/move_closure.rs:61:9
|
LL | t.0.0 = "new S".into();
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:58:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new S".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0),(0, 0)] -> ByValue
--> $DIR/move_closure.rs:61:9
|
LL | t.0.0 = "new S".into();
| ^^^^^
error: aborting due to 9 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,28 @@
// run-pass
// Test that ByValue captures compile sucessefully especially when the captures are
// derefenced within the closure.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
#[derive(Debug, Default)]
struct SomeLargeType;
struct MuchLargerType([SomeLargeType; 32]);
fn big_box() {
let s = MuchLargerType(Default::default());
let b = Box::new(s);
let t = (b, 10);
let c = || {
let p = t.0.0;
println!("{} {:?}", t.1, p);
};
c();
}
fn main() {
big_box();
}

View file

@ -0,0 +1,11 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/by_value.rs:6:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
warning: 1 warning emitted

View file

@ -0,0 +1,47 @@
// run-pass
// Test that move closures compile properly with `capture_disjoint_fields` enabled.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
fn simple_ref() {
let mut s = 10;
let ref_s = &mut s;
let mut c = move || {
*ref_s += 10;
};
c();
}
fn struct_contains_ref_to_another_struct() {
struct S(String);
struct T<'a>(&'a mut S);
let mut s = S("s".into());
let t = T(&mut s);
let mut c = move || {
t.0.0 = "new s".into();
};
c();
}
fn no_ref() {
struct S(String);
struct T(S);
let t = T(S("s".into()));
let mut c = move || {
t.0.0 = "new S".into();
};
c();
}
fn main() {
simple_ref();
struct_contains_ref_to_another_struct();
no_ref();
}

View file

@ -0,0 +1,21 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/move_closure.rs:5:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
warning: variable does not need to be mutable
--> $DIR/move_closure.rs:36:9
|
LL | let mut t = T(S("s".into()));
| ----^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: 2 warnings emitted

View file

@ -0,0 +1,47 @@
// run-pass
// Test that we can use raw ptrs when using `capture_disjoint_fields`.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
#[derive(Debug)]
struct S {
s: String,
t: String,
}
struct T(*const S);
fn unsafe_imm() {
let s = "".into();
let t = "".into();
let my_speed: Box<S> = Box::new(S { s, t });
let p : *const S = Box::into_raw(my_speed);
let t = T(p);
let c = || unsafe {
println!("{:?}", (*t.0).s);
};
c();
}
fn unsafe_mut() {
let s = "".into();
let t = "".into();
let mut my_speed: Box<S> = Box::new(S { s, t });
let p : *mut S = &mut *my_speed;
let c = || {
let x = unsafe { &mut (*p).s };
*x = "s".into();
};
c();
}
fn main() {
unsafe_mut();
unsafe_imm();
}

View file

@ -0,0 +1,11 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/unsafe_ptr.rs:5:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
warning: 1 warning emitted

View file

@ -0,0 +1,63 @@
// Test that we restrict precision of a capture when we access a raw ptr,
// i.e. the capture doesn't deref the raw ptr.
#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
//~| `#[warn(incomplete_features)]` on by default
//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
#![feature(rustc_attrs)]
#[derive(Debug)]
struct S {
s: String,
t: String,
}
struct T(*const S);
fn unsafe_imm() {
let s = "".into();
let t = "".into();
let my_speed: Box<S> = Box::new(S { s, t });
let p : *const S = Box::into_raw(my_speed);
let t = T(p);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| unsafe {
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
println!("{:?}", (*t.0).s);
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow
};
c();
}
fn unsafe_mut() {
let s = "".into();
let t = "".into();
let mut my_speed: Box<S> = Box::new(S { s, t });
let p : *mut S = &mut *my_speed;
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
let x = unsafe { &mut (*p).s };
//~^ NOTE: Capturing p[Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture p[] -> ImmBorrow
*x = "s".into();
};
c();
}
fn main() {
unsafe_mut();
unsafe_imm();
}

View file

@ -0,0 +1,102 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/unsafe_ptr.rs:26:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/unsafe_ptr.rs:46:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/unsafe_ptr.rs:4:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
error: First Pass analysis includes:
--> $DIR/unsafe_ptr.rs:29:6
|
LL | / || unsafe {
LL | |
LL | |
LL | | println!("{:?}", (*t.0).s);
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
--> $DIR/unsafe_ptr.rs:32:26
|
LL | println!("{:?}", (*t.0).s);
| ^^^^^^^^
error: Min Capture analysis includes:
--> $DIR/unsafe_ptr.rs:29:6
|
LL | / || unsafe {
LL | |
LL | |
LL | | println!("{:?}", (*t.0).s);
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0)] -> ImmBorrow
--> $DIR/unsafe_ptr.rs:32:26
|
LL | println!("{:?}", (*t.0).s);
| ^^^^^^^^
error: First Pass analysis includes:
--> $DIR/unsafe_ptr.rs:49:5
|
LL | / || {
LL | |
LL | |
LL | | let x = unsafe { &mut (*p).s };
... |
LL | | *x = "s".into();
LL | | };
| |_____^
|
note: Capturing p[Deref,(0, 0)] -> ImmBorrow
--> $DIR/unsafe_ptr.rs:52:31
|
LL | let x = unsafe { &mut (*p).s };
| ^^^^^^
error: Min Capture analysis includes:
--> $DIR/unsafe_ptr.rs:49:5
|
LL | / || {
LL | |
LL | |
LL | | let x = unsafe { &mut (*p).s };
... |
LL | | *x = "s".into();
LL | | };
| |_____^
|
note: Min Capture p[] -> ImmBorrow
--> $DIR/unsafe_ptr.rs:52:31
|
LL | let x = unsafe { &mut (*p).s };
| ^^^^^^
error: aborting due to 6 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0658`.