Tests for precise lint analysis

This commit is contained in:
Aman Arora 2021-02-04 18:50:32 -05:00
parent c01036af1d
commit 319f1aba62
3 changed files with 232 additions and 0 deletions

View file

@ -0,0 +1,78 @@
#![deny(disjoint_capture_drop_reorder)]
//~^ NOTE: the lint level is defined here
#[derive(Debug)]
struct Foo(i32);
impl Drop for Foo {
fn drop(&mut self) {
println!("{:?} dropped", self.0);
}
}
struct ConstainsDropField(Foo, Foo);
#[derive(Debug)]
struct ContainsAndImplsDrop(Foo);
impl Drop for ContainsAndImplsDrop {
fn drop(&mut self) {
println!("{:?} dropped", self.0);
}
}
// Test that even if all paths starting at root variable that implement Drop are captured,
// the lint is triggered if the root variable implements drop and isn't captured.
fn test_precise_analysis_parent_root_impl_drop_not_captured() {
let t = ContainsAndImplsDrop(Foo(10));
let c = || {
//~^ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~| NOTE: drop(&(t));
let _t = t.0;
};
c();
}
// Test that lint is triggered if a path that implements Drop is not captured by move
fn test_precise_analysis_drop_paths_not_captured_by_move() {
let t = ConstainsDropField(Foo(10), Foo(20));
let c = || {
//~^ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~| NOTE: drop(&(t));
let _t = t.0;
let _t = &t.1;
};
c();
}
struct S;
impl Drop for S {
fn drop(&mut self) {
}
}
struct T(S, S);
struct U(T, T);
// Test precise analysis for the lint works with paths longer than one.
fn test_precise_analysis_long_path_missing() {
let u = U(T(S, S), T(S, S));
let c = || {
//~^ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~| NOTE: drop(&(u));
let _x = u.0.0;
let _x = u.0.1;
let _x = u.1.0;
};
c();
}
fn main() {
test_precise_analysis_parent_root_impl_drop_not_captured();
test_precise_analysis_drop_paths_not_captured_by_move();
test_precise_analysis_long_path_missing();
}

View file

@ -0,0 +1,49 @@
error: drop order affected for closure because of `capture_disjoint_fields`
--> $DIR/precise.rs:27:13
|
LL | let c = || {
| _____________^
LL | |
LL | |
LL | | let _t = t.0;
LL | | };
| |_____^
|
note: the lint level is defined here
--> $DIR/precise.rs:1:9
|
LL | #![deny(disjoint_capture_drop_reorder)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: drop(&(t));
error: drop order affected for closure because of `capture_disjoint_fields`
--> $DIR/precise.rs:40:13
|
LL | let c = || {
| _____________^
LL | |
LL | |
LL | | let _t = t.0;
LL | | let _t = &t.1;
LL | | };
| |_____^
|
= note: drop(&(t));
error: drop order affected for closure because of `capture_disjoint_fields`
--> $DIR/precise.rs:63:13
|
LL | let c = || {
| _____________^
LL | |
LL | |
LL | | let _x = u.0.0;
LL | | let _x = u.0.1;
LL | | let _x = u.1.0;
LL | | };
| |_____^
|
= note: drop(&(u));
error: aborting due to 3 previous errors

View file

@ -0,0 +1,105 @@
// run-pass
#![deny(disjoint_capture_drop_reorder)]
#[derive(Debug)]
struct Foo(i32);
impl Drop for Foo {
fn drop(&mut self) {
println!("{:?} dropped", self.0);
}
}
struct ConstainsDropField(Foo, Foo);
// Test that if all paths starting at root variable that implement Drop are captured
// then it doesn't trigger the lint.
fn test_precise_analysis_simple_1() {
let t = (Foo(10), Foo(20), Foo(30));
let c = || {
let _t = t.0;
let _t = t.1;
let _t = t.2;
};
c();
}
// Test that if all paths starting at root variable that implement Drop are captured
// then it doesn't trigger the lint.
fn test_precise_analysis_simple_2() {
let t = ConstainsDropField(Foo(10), Foo(20));
let c = || {
let _t = t.0;
let _t = t.1;
};
c();
}
#[derive(Debug)]
struct ContainsAndImplsDrop(Foo);
impl Drop for ContainsAndImplsDrop {
fn drop(&mut self) {
println!("{:?} dropped", self.0);
}
}
// If a path isn't directly captured but requires Drop, then this tests that migrations aren't
// needed if the a parent to that path is captured.
fn test_precise_analysis_parent_captured_1() {
let t = ConstainsDropField(Foo(10), Foo(20));
let c = || {
let _t = t;
};
c();
}
// If a path isn't directly captured but requires Drop, then this tests that migrations aren't
// needed if the a parent to that path is captured.
fn test_precise_analysis_parent_captured_2() {
let t = ContainsAndImplsDrop(Foo(10));
let c = || {
let _t = t;
};
c();
}
struct S;
impl Drop for S {
fn drop(&mut self) {
}
}
struct T(S, S);
struct U(T, T);
// Test that if the path is longer than just one element, precise analysis works correctly.
fn test_precise_analysis_long_path() {
let u = U(T(S, S), T(S, S));
let c = || {
let _x = u.0.0;
let _x = u.0.1;
let _x = u.1.0;
let _x = u.1.1;
};
c();
}
fn main() {
test_precise_analysis_simple_1();
test_precise_analysis_simple_2();
test_precise_analysis_parent_captured_1();
test_precise_analysis_parent_captured_2();
test_precise_analysis_long_path();
}