about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-08-18 05:10:41 +0200
committerGitHub <noreply@github.com>2022-08-18 05:10:41 +0200
commit370bf1543dc1033194403241fbb73d3b8c1d48b3 (patch)
treed76d8728ba9503add4a3022454a550a4eb13b39d
parent9c20b2a8cc7588decb6de25ac6a7912dcef24d65 (diff)
parent0da81997a2652b8a46506cf0a5e4d382ea1f3308 (diff)
downloadrust-370bf1543dc1033194403241fbb73d3b8c1d48b3.tar.gz
rust-370bf1543dc1033194403241fbb73d3b8c1d48b3.zip
Rollup merge of #97962 - eholk:drop-tracking-must-not-suspend, r=cjgillot
Make must_not_suspend lint see through references when drop tracking is enabled

See #97333.

With drop tracking enabled, sometimes values that were previously linted are now considered dropped and not linted. This change makes must_not_suspend traverse through references to still catch these values.

Unfortunately, this leads to duplicate warnings in some cases (e.g. [dedup.rs](https://cs.github.com/rust-lang/rust/blob/9a74608543d499bcc7dd505e195e8bfab9447315/src/test/ui/lint/must_not_suspend/dedup.rs#L4)), so we only use the new behavior when drop tracking is enabled.

cc ``@guswynn``
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior.rs12
-rw-r--r--src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs30
-rw-r--r--src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr27
3 files changed, 67 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index d4f8001493c..85a0d4e4499 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -457,7 +457,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
 }
 
 #[derive(Default)]
-pub struct SuspendCheckData<'a, 'tcx> {
+struct SuspendCheckData<'a, 'tcx> {
     expr: Option<&'tcx Expr<'tcx>>,
     source_span: Span,
     yield_span: Span,
@@ -472,7 +472,7 @@ pub struct SuspendCheckData<'a, 'tcx> {
 //
 // Note that this technique was chosen over things like a `Suspend` marker trait
 // as it is simpler and has precedent in the compiler
-pub fn check_must_not_suspend_ty<'tcx>(
+fn check_must_not_suspend_ty<'tcx>(
     fcx: &FnCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
     hir_id: HirId,
@@ -489,6 +489,8 @@ pub fn check_must_not_suspend_ty<'tcx>(
 
     let plural_suffix = pluralize!(data.plural_len);
 
+    debug!("Checking must_not_suspend for {}", ty);
+
     match *ty.kind() {
         ty::Adt(..) if ty.is_box() => {
             let boxed_ty = ty.boxed_ty();
@@ -580,6 +582,12 @@ pub fn check_must_not_suspend_ty<'tcx>(
                 },
             )
         }
+        // If drop tracking is enabled, we want to look through references, since the referrent
+        // may not be considered live across the await point.
+        ty::Ref(_region, ty, _mutability) if fcx.sess().opts.unstable_opts.drop_tracking => {
+            let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
+            check_must_not_suspend_ty(fcx, ty, hir_id, SuspendCheckData { descr_pre, ..data })
+        }
         _ => false,
     }
 }
diff --git a/src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs
new file mode 100644
index 00000000000..1bc4a381257
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs
@@ -0,0 +1,30 @@
+// edition:2018
+// compile-flags: -Zdrop-tracking
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    i: i64
+}
+
+struct Bar {
+    u: Umm,
+}
+
+async fn other() {}
+
+impl Bar {
+    async fn uhoh(&mut self) {
+        let guard = &mut self.u; //~ ERROR `Umm` held across
+
+        other().await;
+
+        *guard = Umm {
+            i: 2
+        }
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
new file mode 100644
index 00000000000..c49d2712853
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
@@ -0,0 +1,27 @@
+error: reference to `Umm` held across a suspend point, but should not be
+  --> $DIR/ref-drop-tracking.rs:19:13
+   |
+LL |         let guard = &mut self.u;
+   |             ^^^^^
+LL |
+LL |         other().await;
+   |                ------ the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/ref-drop-tracking.rs:4:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+  --> $DIR/ref-drop-tracking.rs:19:13
+   |
+LL |         let guard = &mut self.u;
+   |             ^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/ref-drop-tracking.rs:19:13
+   |
+LL |         let guard = &mut self.u;
+   |             ^^^^^
+
+error: aborting due to previous error
+