about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-07 13:39:28 +0000
committerbors <bors@rust-lang.org>2023-08-07 13:39:28 +0000
commit84ec2633defc5c459c682ac0c45efb41715249df (patch)
treeb9278f7a43740dde5eb72e2058badfe1fd936c13 /tests
parent139b49b99523c43219b39079aa8fb2e084c52a1c (diff)
parentb4b33df983b4badac5c2578756cd42a76236be8d (diff)
downloadrust-84ec2633defc5c459c682ac0c45efb41715249df.tar.gz
rust-84ec2633defc5c459c682ac0c45efb41715249df.zip
Auto merge of #113902 - Enselic:lint-recursive-drop, r=oli-obk
Make `unconditional_recursion` warning detect recursive drops

Closes #55388

Also closes #50049 unless we want to keep it for the second example which this PR does not solve, but I think it is better to track that work in #57965.

r? `@oli-obk` since you are the mentor for #55388

Unresolved questions:
- [x] There are two false positives that must be fixed before merging (see diff). I suspect the best way to solve them is to perform analysis after drop elaboration instead of before, as now, but I have not explored that any further yet. Could that be an option? **Answer:** Yes, that solved the problem.

`@rustbot` label +T-compiler +C-enhancement +A-lint
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/lint/lint-unconditional-drop-recursion.rs38
-rw-r--r--tests/ui/lint/lint-unconditional-drop-recursion.stderr17
2 files changed, 55 insertions, 0 deletions
diff --git a/tests/ui/lint/lint-unconditional-drop-recursion.rs b/tests/ui/lint/lint-unconditional-drop-recursion.rs
new file mode 100644
index 00000000000..348cd280139
--- /dev/null
+++ b/tests/ui/lint/lint-unconditional-drop-recursion.rs
@@ -0,0 +1,38 @@
+// Because drop recursion can only be detected after drop elaboration which
+// happens for codegen:
+// build-fail
+
+#![deny(unconditional_recursion)]
+#![allow(dead_code)]
+
+pub struct RecursiveDrop;
+
+impl Drop for RecursiveDrop {
+    fn drop(&mut self) { //~ ERROR function cannot return without recursing
+        let _ = RecursiveDrop;
+    }
+}
+
+#[derive(Default)]
+struct NotRecursiveDrop1;
+
+impl Drop for NotRecursiveDrop1 {
+    fn drop(&mut self) {
+        // Before drop elaboration, the MIR can look like a recursive drop will
+        // occur. But it will not, since forget() prevents drop() from running.
+        let taken = std::mem::take(self);
+        std::mem::forget(taken);
+    }
+}
+
+struct NotRecursiveDrop2;
+
+impl Drop for NotRecursiveDrop2 {
+    fn drop(&mut self) {
+        // Before drop elaboration, the MIR can look like a recursive drop will
+        // occur. But it will not, since this will panic.
+        std::panic::panic_any(NotRecursiveDrop2);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/lint-unconditional-drop-recursion.stderr b/tests/ui/lint/lint-unconditional-drop-recursion.stderr
new file mode 100644
index 00000000000..76f95481605
--- /dev/null
+++ b/tests/ui/lint/lint-unconditional-drop-recursion.stderr
@@ -0,0 +1,17 @@
+error: function cannot return without recursing
+  --> $DIR/lint-unconditional-drop-recursion.rs:11:5
+   |
+LL |     fn drop(&mut self) {
+   |     ^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |         let _ = RecursiveDrop;
+   |                              - recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+note: the lint level is defined here
+  --> $DIR/lint-unconditional-drop-recursion.rs:5:9
+   |
+LL | #![deny(unconditional_recursion)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+