about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAman Arora <me@aman-arora.com>2021-02-04 18:50:32 -0500
committerAman Arora <me@aman-arora.com>2021-02-09 02:53:59 -0500
commit319f1aba6281adb6ca22522003b49578c406745f (patch)
tree26574420a6d0780452c2b87af32ea4e3c5638424
parentc01036af1d8da0e5e16f8c126fa0017049d52636 (diff)
downloadrust-319f1aba6281adb6ca22522003b49578c406745f.tar.gz
rust-319f1aba6281adb6ca22522003b49578c406745f.zip
Tests for precise lint analysis
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/precise.rs78
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr49
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs105
3 files changed, 232 insertions, 0 deletions
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs
new file mode 100644
index 00000000000..79702cc6b56
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs
@@ -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();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
new file mode 100644
index 00000000000..968ca395f94
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
@@ -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
+
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs
new file mode 100644
index 00000000000..8af48501ca2
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs
@@ -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();
+}