From 319f1aba6281adb6ca22522003b49578c406745f Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Thu, 4 Feb 2021 18:50:32 -0500 Subject: [PATCH] Tests for precise lint analysis --- .../migrations/precise.rs | 78 +++++++++++++ .../migrations/precise.stderr | 49 ++++++++ .../migrations/precise_no_migrations.rs | 105 ++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/precise.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs 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 000000000000..79702cc6b56f --- /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 000000000000..968ca395f946 --- /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 000000000000..8af48501ca29 --- /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(); +}