From 0f9c349834622fa337c8dab886af4041bcdad5bb Mon Sep 17 00:00:00 2001
From: Gus Wynn <guswynn@gmail.com>
Date: Mon, 27 Sep 2021 08:43:30 -0700
Subject: [PATCH 1/3] lock types

---
 library/std/src/lib.rs                        |  1 +
 library/std/src/sync/mutex.rs                 |  6 +++++
 library/std/src/sync/rwlock.rs                | 12 +++++++++
 src/test/ui/lint/must_not_suspend/mutex.rs    | 13 ++++++++++
 .../ui/lint/must_not_suspend/mutex.stderr     | 26 +++++++++++++++++++
 5 files changed, 58 insertions(+)
 create mode 100644 src/test/ui/lint/must_not_suspend/mutex.rs
 create mode 100644 src/test/ui/lint/must_not_suspend/mutex.stderr

diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f69baba9e733f..9d150b69f6a6d 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -297,6 +297,7 @@
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
+#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
 #![feature(needs_panic_runtime)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index e1d6324c17e33..9abd4b547c77e 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -188,6 +188,12 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
 /// [`lock`]: Mutex::lock
 /// [`try_lock`]: Mutex::try_lock
 #[must_use = "if unused the Mutex will immediately unlock"]
+#[cfg_attr(
+    not(bootstrap),
+    must_not_suspend = "Holding a MutexGuard across suspend \
+                      points can cause deadlocks, delays, \
+                      and cause Future's to not implement `Send`"
+)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
     lock: &'a Mutex<T>,
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index e50d62d817376..1523d36323fd9 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -95,6 +95,12 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 /// [`read`]: RwLock::read
 /// [`try_read`]: RwLock::try_read
 #[must_use = "if unused the RwLock will immediately unlock"]
+#[cfg_attr(
+    not(bootstrap),
+    must_not_suspend = "Holding a RwLockReadGuard across suspend \
+                      points can cause deadlocks, delays, \
+                      and cause Future's to not implement `Send`"
+)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
     lock: &'a RwLock<T>,
@@ -115,6 +121,12 @@ unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
 /// [`write`]: RwLock::write
 /// [`try_write`]: RwLock::try_write
 #[must_use = "if unused the RwLock will immediately unlock"]
+#[cfg_attr(
+    not(bootstrap),
+    must_not_suspend = "Holding a RwLockWriteGuard across suspend \
+                      points can cause deadlocks, delays, \
+                      and cause Future's to not implement `Send`"
+)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
     lock: &'a RwLock<T>,
diff --git a/src/test/ui/lint/must_not_suspend/mutex.rs b/src/test/ui/lint/must_not_suspend/mutex.rs
new file mode 100644
index 0000000000000..7bb895e7d3643
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/mutex.rs
@@ -0,0 +1,13 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+async fn other() {}
+
+pub async fn uhoh(m: std::sync::Mutex<()>) {
+    let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr
new file mode 100644
index 0000000000000..69638fc20107c
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/mutex.stderr
@@ -0,0 +1,26 @@
+error: `MutexGuard` held across a suspend point, but should not be
+  --> $DIR/mutex.rs:8:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/mutex.rs:3:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Future's to not implement `Send`
+  --> $DIR/mutex.rs:8:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/mutex.rs:8:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+
+error: aborting due to previous error
+

From 4cc3297dc403e9d4d2106b26418efe35d4bb1af2 Mon Sep 17 00:00:00 2001
From: Gus Wynn <guswynn@gmail.com>
Date: Mon, 27 Sep 2021 08:49:36 -0700
Subject: [PATCH 2/3] #[feature] not required for lint result

---
 src/test/ui/lint/must_not_suspend/mutex.rs     | 1 -
 src/test/ui/lint/must_not_suspend/mutex.stderr | 8 ++++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/test/ui/lint/must_not_suspend/mutex.rs b/src/test/ui/lint/must_not_suspend/mutex.rs
index 7bb895e7d3643..596249b2e4e4f 100644
--- a/src/test/ui/lint/must_not_suspend/mutex.rs
+++ b/src/test/ui/lint/must_not_suspend/mutex.rs
@@ -1,5 +1,4 @@
 // edition:2018
-#![feature(must_not_suspend)]
 #![deny(must_not_suspend)]
 
 async fn other() {}
diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr
index 69638fc20107c..47a84fdbc5731 100644
--- a/src/test/ui/lint/must_not_suspend/mutex.stderr
+++ b/src/test/ui/lint/must_not_suspend/mutex.stderr
@@ -1,5 +1,5 @@
 error: `MutexGuard` held across a suspend point, but should not be
-  --> $DIR/mutex.rs:8:9
+  --> $DIR/mutex.rs:7:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^
@@ -7,17 +7,17 @@ LL |     other().await;
    |     ------------- the value is held across this suspend point
    |
 note: the lint level is defined here
-  --> $DIR/mutex.rs:3:9
+  --> $DIR/mutex.rs:2:9
    |
 LL | #![deny(must_not_suspend)]
    |         ^^^^^^^^^^^^^^^^
 note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Future's to not implement `Send`
-  --> $DIR/mutex.rs:8:9
+  --> $DIR/mutex.rs:7:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^
 help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
-  --> $DIR/mutex.rs:8:9
+  --> $DIR/mutex.rs:7:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^

From cb8e83caeba7268ebb3515468d348aea7af9fdae Mon Sep 17 00:00:00 2001
From: Gus Wynn <guswynn@gmail.com>
Date: Tue, 28 Sep 2021 17:57:08 -0700
Subject: [PATCH 3/3] ref/refmut

---
 library/core/src/cell.rs                       | 10 ++++++++++
 library/core/src/lib.rs                        |  1 +
 library/std/src/sync/mutex.rs                  |  2 +-
 library/std/src/sync/rwlock.rs                 |  2 +-
 src/test/ui/lint/must_not_suspend/mutex.stderr |  2 +-
 5 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index e56b631dbaf8d..c0121eebb7fef 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1303,6 +1303,11 @@ impl Clone for BorrowRef<'_> {
 ///
 /// See the [module-level documentation](self) for more.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(
+    not(bootstrap),
+    must_not_suspend = "Holding a Ref across suspend \
+                      points can cause BorrowErrors"
+)]
 pub struct Ref<'b, T: ?Sized + 'b> {
     value: &'b T,
     borrow: BorrowRef<'b>,
@@ -1679,6 +1684,11 @@ impl<'b> BorrowRefMut<'b> {
 ///
 /// See the [module-level documentation](self) for more.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(
+    not(bootstrap),
+    must_not_suspend = "Holding a RefMut across suspend \
+                      points can cause BorrowErrors"
+)]
 pub struct RefMut<'b, T: ?Sized + 'b> {
     value: &'b mut T,
     borrow: BorrowRefMut<'b>,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 265ba9f1bb91b..2230461b5f4b5 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -141,6 +141,7 @@
 #![feature(link_llvm_intrinsics)]
 #![feature(llvm_asm)]
 #![feature(min_specialization)]
+#![cfg_attr(not(bootstrap), feature(must_not_suspend))]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(no_core)]
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index 9abd4b547c77e..06a97fd3f7610 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -192,7 +192,7 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
     not(bootstrap),
     must_not_suspend = "Holding a MutexGuard across suspend \
                       points can cause deadlocks, delays, \
-                      and cause Future's to not implement `Send`"
+                      and cause Futures to not implement `Send`"
 )]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 1523d36323fd9..aa1ce82d96799 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -99,7 +99,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
     not(bootstrap),
     must_not_suspend = "Holding a RwLockReadGuard across suspend \
                       points can cause deadlocks, delays, \
-                      and cause Future's to not implement `Send`"
+                      and cause Futures to not implement `Send`"
 )]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr
index 47a84fdbc5731..4e0d9343c2c71 100644
--- a/src/test/ui/lint/must_not_suspend/mutex.stderr
+++ b/src/test/ui/lint/must_not_suspend/mutex.stderr
@@ -11,7 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(must_not_suspend)]
    |         ^^^^^^^^^^^^^^^^
-note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Future's to not implement `Send`
+note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
   --> $DIR/mutex.rs:7:9
    |
 LL |     let _guard = m.lock().unwrap();