about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs16
-rw-r--r--compiler/rustc_hir/src/hir_id.rs68
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs4
-rw-r--r--src/bootstrap/bootstrap.py10
-rw-r--r--src/doc/rustdoc/src/unstable-features.md22
-rw-r--r--src/librustdoc/html/static/css/noscript.css9
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css4
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css4
-rw-r--r--src/librustdoc/html/static/css/themes/light.css4
-rw-r--r--src/librustdoc/html/static/js/main.js4
-rw-r--r--src/librustdoc/html/templates/page.html1
-rw-r--r--src/librustdoc/scrape_examples.rs20
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile5
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs2
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs1
-rw-r--r--src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs2
-rw-r--r--src/test/rustdoc-gui/javascript-disabled.goml6
-rw-r--r--src/test/ui/async-await/issue-64130-non-send-future-diags.rs2
-rw-r--r--src/test/ui/async-await/issue-64130-non-send-future-diags.stderr6
-rw-r--r--src/test/ui/async-await/issue-71137.rs2
-rw-r--r--src/test/ui/async-await/issue-71137.stderr6
-rw-r--r--src/test/ui/consts/promote-not.rs15
-rw-r--r--src/test/ui/consts/promote-not.stderr94
-rw-r--r--src/test/ui/lint/must_not_suspend/gated.rs14
-rw-r--r--src/test/ui/lint/must_not_suspend/gated.stderr54
-rw-r--r--src/test/ui/lint/must_not_suspend/issue-89562.rs19
-rw-r--r--src/test/ui/lint/must_not_suspend/mutex.rs1
-rw-r--r--src/test/ui/lint/must_not_suspend/mutex.stderr8
-rw-r--r--src/test/ui/lint/must_not_suspend/warn.rs1
-rw-r--r--src/test/ui/lint/must_not_suspend/warn.stderr12
31 files changed, 294 insertions, 123 deletions
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 67664d2ede1..7bf378601e0 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -835,11 +835,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
         new_temp
     }
 
-    fn promote_candidate(
-        mut self,
-        candidate: Candidate,
-        next_promoted_id: usize,
-    ) -> Option<Body<'tcx>> {
+    fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
         let def = self.source.source.with_opt_param();
         let mut rvalue = {
             let promoted = &mut self.promoted;
@@ -938,7 +934,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
 
         let span = self.promoted.span;
         self.assign(RETURN_PLACE, rvalue, span);
-        Some(self.promoted)
+        self.promoted
     }
 }
 
@@ -1011,11 +1007,9 @@ pub fn promote_candidates<'tcx>(
             keep_original: false,
         };
 
-        //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice
-        if let Some(mut promoted) = promoter.promote_candidate(candidate, promotions.len()) {
-            promoted.source.promoted = Some(promotions.next_index());
-            promotions.push(promoted);
-        }
+        let mut promoted = promoter.promote_candidate(candidate, promotions.len());
+        promoted.source.promoted = Some(promotions.next_index());
+        promotions.push(promoted);
     }
 
     // Insert each of `extra_statements` before its indicated location, which
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 877871f7c3d..39552eb9f31 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,5 +1,4 @@
 use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
-use rustc_index::vec::IndexVec;
 use std::fmt;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
@@ -66,70 +65,3 @@ pub const CRATE_HIR_ID: HirId = HirId {
     owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
     local_id: ItemLocalId::from_u32(0),
 };
-
-/// N.B. This collection is currently unused, but will be used by #72015 and future PRs.
-#[derive(Clone, Default, Debug, Encodable, Decodable)]
-pub struct HirIdVec<T> {
-    map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
-}
-
-impl<T> HirIdVec<T> {
-    pub fn push_owner(&mut self, id: LocalDefId) {
-        self.map.ensure_contains_elem(id, IndexVec::new);
-    }
-
-    pub fn push(&mut self, id: HirId, value: T) {
-        if id.local_id == ItemLocalId::from_u32(0) {
-            self.push_owner(id.owner);
-        }
-        let submap = &mut self.map[id.owner];
-        let _ret_id = submap.push(value);
-        debug_assert_eq!(_ret_id, id.local_id);
-    }
-
-    pub fn push_sparse(&mut self, id: HirId, value: T)
-    where
-        T: Default,
-    {
-        self.map.ensure_contains_elem(id.owner, IndexVec::new);
-        let submap = &mut self.map[id.owner];
-        let i = id.local_id.index();
-        let len = submap.len();
-        if i >= len {
-            submap.extend(std::iter::repeat_with(T::default).take(i - len + 1));
-        }
-        submap[id.local_id] = value;
-    }
-
-    pub fn get(&self, id: HirId) -> Option<&T> {
-        self.map.get(id.owner)?.get(id.local_id)
-    }
-
-    pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
-        &self.map[id]
-    }
-
-    pub fn iter(&self) -> impl Iterator<Item = &T> {
-        self.map.iter().flat_map(|la| la.iter())
-    }
-
-    pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
-        self.map.iter_enumerated().flat_map(|(owner, la)| {
-            la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
-        })
-    }
-}
-
-impl<T> std::ops::Index<HirId> for HirIdVec<T> {
-    type Output = T;
-
-    fn index(&self, id: HirId) -> &T {
-        &self.map[id.owner][id.local_id]
-    }
-}
-
-impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
-    fn index_mut(&mut self, id: HirId) -> &mut T {
-        &mut self.map[id.owner][id.local_id]
-    }
-}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index d98d65385e5..f6514ddca9f 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -303,7 +303,6 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
         UNUSED_LABELS,
         UNUSED_PARENS,
         UNUSED_BRACES,
-        MUST_NOT_SUSPEND,
         REDUNDANT_SEMICOLONS
     );
 
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1db9d3f65d4..b83d04f3dc2 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -323,6 +323,7 @@ declare_lint! {
     ///
     /// ```rust
     /// #![feature(must_not_suspend)]
+    /// #![warn(must_not_suspend)]
     ///
     /// #[must_not_suspend]
     /// struct SyncThing {}
@@ -349,8 +350,9 @@ declare_lint! {
     /// `MutexGuard`'s)
     ///
     pub MUST_NOT_SUSPEND,
-    Warn,
+    Allow,
     "use of a `#[must_not_suspend]` value across a yield point",
+    @feature_gate = rustc_span::symbol::sym::must_not_suspend;
 }
 
 declare_lint! {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 0c5a0cbc06e..38d3c7aec49 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1026,7 +1026,15 @@ class RustBuild(object):
         if self.git_version >= distutils.version.LooseVersion("2.11.0"):
             update_args.append("--progress")
         update_args.append(module)
-        run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
+        try:
+            run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
+        except RuntimeError:
+            print("Failed updating submodule. This is probably due to uncommitted local changes.")
+            print('Either stash the changes by running "git stash" within the submodule\'s')
+            print('directory, reset them by running "git reset --hard", or commit them.')
+            print("To reset all submodules' changes run", end=" ")
+            print('"git submodule foreach --recursive git reset --hard".')
+            raise SystemExit(1)
 
         run(["git", "reset", "-q", "--hard"],
             cwd=module_path, verbose=self.verbose)
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 51f365be922..b3b6422afab 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -134,9 +134,27 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
 
 ## Document primitives
 
+This is for Rust compiler internal use only.
+
 Since primitive types are defined in the compiler, there's no place to attach documentation
-attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way to generate
-documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable.
+attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way
+to generate documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable.
+
+## Document keywords
+
+This is for Rust compiler internal use only.
+
+Rust keywords are documented in the standard library (look for `match` for example).
+
+To do so, the `#[doc(keyword = "...")]` attribute is used. Example:
+
+```rust
+#![feature(doc_keyword)]
+
+/// Some documentation about the keyword.
+#[doc(keyword = "keyword")]
+mod empty_mod {}
+```
 
 ## Unstable command-line arguments
 
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 0a196edd53b..37ea7b00033 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -13,3 +13,12 @@ rules.
 	/* It requires JS to work so no need to display it in this case. */
 	display: none;
 }
+
+.sub {
+	/* The search bar and related controls don't work without JS */
+	display: none;
+}
+
+#theme-picker {
+	display: none;
+}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index f9c84dc3e31..ba7fb3b5456 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -255,10 +255,6 @@ details.undocumented > summary::before {
 	box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
 }
 
-.search-input:disabled {
-	background-color: #3e3e3e;
-}
-
 .module-item .stab,
 .import-item .stab {
 	color: #000;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 9a38277d559..77ac217e6f4 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -219,10 +219,6 @@ details.undocumented > summary::before {
 	border-color: #008dfd;
 }
 
-.search-input:disabled {
-	background-color: #c5c4c4;
-}
-
 #crate-search + .search-input:focus {
 	box-shadow: 0 0 8px 4px #078dd8;
 }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index fba8231caac..6df137e3914 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -209,10 +209,6 @@ details.undocumented > summary::before {
 	border-color: #66afe9;
 }
 
-.search-input:disabled {
-	background-color: #e6e6e6;
-}
-
 #crate-search + .search-input:focus {
 	box-shadow: 0 0 8px #078dd8;
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index e396fd9d288..c421c6e9dc1 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -263,7 +263,9 @@ function hideThemeButtonState() {
                 search_input.placeholder = searchState.input.origPlaceholder;
             });
 
-            search_input.removeAttribute('disabled');
+            if (search_input.value != '') {
+                loadSearch();
+            }
 
             // `crates{version}.js` should always be loaded before this script, so we can use it
             // safely.
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index b0174d59a7b..cead54412bb 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -85,7 +85,6 @@
                     <input {# -#}
                         class="search-input" {# -#}
                         name="search" {# -#}
-                        disabled {# -#}
                         autocomplete="off" {# -#}
                         spellcheck="false" {# -#}
                         placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index fc54e55b876..05e746573f4 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -132,12 +132,28 @@ where
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
 
-        // Get type of function if expression is a function call
         let tcx = self.tcx;
+
+        // If we visit an item that contains an expression outside a function body,
+        // then we need to exit before calling typeck (which will panic). See
+        // test/run-make/rustdoc-scrape-examples-invalid-expr for an example.
+        let hir = tcx.hir();
+        let owner = hir.local_def_id_to_hir_id(ex.hir_id.owner);
+        if hir.maybe_body_owned_by(owner).is_none() {
+            return;
+        }
+
+        // Get type of function if expression is a function call
         let (ty, span) = match ex.kind {
             hir::ExprKind::Call(f, _) => {
                 let types = tcx.typeck(ex.hir_id.owner);
-                (types.node_type(f.hir_id), ex.span)
+
+                match types.node_type_opt(f.hir_id) {
+                    Some(ty) => (ty, ex.span),
+                    None => {
+                        return;
+                    }
+                }
             }
             hir::ExprKind::MethodCall(_, _, _, span) => {
                 let types = tcx.typeck(ex.hir_id.owner);
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
new file mode 100644
index 00000000000..dce8b83eefe
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile
@@ -0,0 +1,5 @@
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
new file mode 100644
index 00000000000..b342b5b0aae
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs
@@ -0,0 +1,2 @@
+pub struct Foo([usize; foobar::f()]);
+fn main() {}
diff --git a/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
new file mode 100644
index 00000000000..c30c99dec60
--- /dev/null
+++ b/src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs
@@ -0,0 +1 @@
+pub const fn f() -> usize { 5 }
diff --git a/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
index bd59584bbbf..bdfeda92d79 100644
--- a/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
+++ b/src/test/run-make/rustdoc-scrape-examples-multiple/src/lib.rs
@@ -1,4 +1,6 @@
 // @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' ''
 // @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' ''
+// @has src/ex/ex.rs.html
+// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' ''
 
 pub fn ok() {}
diff --git a/src/test/rustdoc-gui/javascript-disabled.goml b/src/test/rustdoc-gui/javascript-disabled.goml
new file mode 100644
index 00000000000..1693f7b645f
--- /dev/null
+++ b/src/test/rustdoc-gui/javascript-disabled.goml
@@ -0,0 +1,6 @@
+// When JavaScript is disabled, we hide the search bar, because it
+// can't be used without JS.
+javascript: false
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-css: (".sub", {"display": "none"})
diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs
index 656ade67c71..b652d239153 100644
--- a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs
+++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs
@@ -1,4 +1,6 @@
 // edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
 
 // This tests the basic example case for the async-await-specific error.
 
diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
index 7125c62dbaf..a373ba6aa71 100644
--- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
+++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-64130-non-send-future-diags.rs:21:13
+  --> $DIR/issue-64130-non-send-future-diags.rs:23:13
    |
 LL |     is_send(foo());
    |             ^^^^^ future returned by `foo` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/issue-64130-non-send-future-diags.rs:15:5
+  --> $DIR/issue-64130-non-send-future-diags.rs:17:5
    |
 LL |     let g = x.lock().unwrap();
    |         - has type `MutexGuard<'_, u32>` which is not `Send`
@@ -15,7 +15,7 @@ LL |     baz().await;
 LL | }
    | - `g` is later dropped here
 note: required by a bound in `is_send`
-  --> $DIR/issue-64130-non-send-future-diags.rs:7:15
+  --> $DIR/issue-64130-non-send-future-diags.rs:9:15
    |
 LL | fn is_send<T: Send>(t: T) { }
    |               ^^^^ required by this bound in `is_send`
diff --git a/src/test/ui/async-await/issue-71137.rs b/src/test/ui/async-await/issue-71137.rs
index ebb392a4530..7695e0325ff 100644
--- a/src/test/ui/async-await/issue-71137.rs
+++ b/src/test/ui/async-await/issue-71137.rs
@@ -1,4 +1,6 @@
 // edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
 
 use std::future::Future;
 use std::sync::Mutex;
diff --git a/src/test/ui/async-await/issue-71137.stderr b/src/test/ui/async-await/issue-71137.stderr
index ac254346c08..3cc800f96c2 100644
--- a/src/test/ui/async-await/issue-71137.stderr
+++ b/src/test/ui/async-await/issue-71137.stderr
@@ -1,12 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-71137.rs:20:14
+  --> $DIR/issue-71137.rs:22:14
    |
 LL |   fake_spawn(wrong_mutex());
    |              ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
    |
    = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`
 note: future is not `Send` as this value is used across an await
-  --> $DIR/issue-71137.rs:12:5
+  --> $DIR/issue-71137.rs:14:5
    |
 LL |     let mut guard = m.lock().unwrap();
    |         --------- has type `MutexGuard<'_, i32>` which is not `Send`
@@ -16,7 +16,7 @@ LL |     *guard += 1;
 LL |   }
    |   - `mut guard` is later dropped here
 note: required by a bound in `fake_spawn`
-  --> $DIR/issue-71137.rs:6:27
+  --> $DIR/issue-71137.rs:8:27
    |
 LL | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
    |                           ^^^^ required by this bound in `fake_spawn`
diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs
index 99926532247..6830b23cfa3 100644
--- a/src/test/ui/consts/promote-not.rs
+++ b/src/test/ui/consts/promote-not.rs
@@ -39,6 +39,8 @@ const TEST_INTERIOR_MUT: () = {
     let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed
 };
 
+const TEST_DROP: String = String::new();
+
 fn main() {
     // We must not promote things with interior mutability. Not even if we "project it away".
     let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed
@@ -50,4 +52,17 @@ fn main() {
     let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed
     let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed
     let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed
+
+    // No promotion of temporaries that need to be dropped.
+    let _val: &'static _ = &TEST_DROP;
+    //~^ ERROR temporary value dropped while borrowed
+    let _val: &'static _ = &&TEST_DROP;
+    //~^ ERROR temporary value dropped while borrowed
+    //~| ERROR temporary value dropped while borrowed
+    let _val: &'static _ = &(&TEST_DROP,);
+    //~^ ERROR temporary value dropped while borrowed
+    //~| ERROR temporary value dropped while borrowed
+    let _val: &'static _ = &[&TEST_DROP; 1];
+    //~^ ERROR temporary value dropped while borrowed
+    //~| ERROR temporary value dropped while borrowed
 }
diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr
index 932109bd86d..0d0b0f9c689 100644
--- a/src/test/ui/consts/promote-not.stderr
+++ b/src/test/ui/consts/promote-not.stderr
@@ -59,7 +59,7 @@ LL | };
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:44:29
+  --> $DIR/promote-not.rs:46:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).0;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -70,7 +70,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:45:29
+  --> $DIR/promote-not.rs:47:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -81,7 +81,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:48:29
+  --> $DIR/promote-not.rs:50:29
    |
 LL |     let _val: &'static _ = &(1/0);
    |               ----------    ^^^^^ creates a temporary which is freed while still in use
@@ -92,7 +92,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:49:29
+  --> $DIR/promote-not.rs:51:29
    |
 LL |     let _val: &'static _ = &(1/(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
@@ -103,7 +103,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:50:29
+  --> $DIR/promote-not.rs:52:29
    |
 LL |     let _val: &'static _ = &(1%0);
    |               ----------    ^^^^^ creates a temporary which is freed while still in use
@@ -114,26 +114,102 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:51:29
+  --> $DIR/promote-not.rs:53:29
    |
 LL |     let _val: &'static _ = &(1%(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
-LL |     let _val: &'static _ = &([1,2,3][4]+1);
+...
 LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:52:29
+  --> $DIR/promote-not.rs:54:29
    |
 LL |     let _val: &'static _ = &([1,2,3][4]+1);
    |               ----------    ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:57:29
+   |
+LL |     let _val: &'static _ = &TEST_DROP;
+   |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:59:29
+   |
+LL |     let _val: &'static _ = &&TEST_DROP;
+   |               ----------    ^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:59:30
+   |
+LL |     let _val: &'static _ = &&TEST_DROP;
+   |               ----------     ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:62:29
+   |
+LL |     let _val: &'static _ = &(&TEST_DROP,);
+   |               ----------    ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
 LL | }
    | - temporary value is freed at the end of this statement
 
-error: aborting due to 13 previous errors
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:62:31
+   |
+LL |     let _val: &'static _ = &(&TEST_DROP,);
+   |               ----------      ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:65:29
+   |
+LL |     let _val: &'static _ = &[&TEST_DROP; 1];
+   |               ----------    ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               |
+   |               type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:65:31
+   |
+LL |     let _val: &'static _ = &[&TEST_DROP; 1];
+   |               ----------      ^^^^^^^^^    - temporary value is freed at the end of this statement
+   |               |               |
+   |               |               creates a temporary which is freed while still in use
+   |               type annotation requires that borrow lasts for `'static`
+
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/lint/must_not_suspend/gated.rs b/src/test/ui/lint/must_not_suspend/gated.rs
new file mode 100644
index 00000000000..acb81b0bf9d
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/gated.rs
@@ -0,0 +1,14 @@
+// edition:2018
+#![deny(must_not_suspend)]  //~ ERROR the `must_not_suspend`
+//~| ERROR the `must_not_suspend`
+//~| ERROR the `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/gated.stderr b/src/test/ui/lint/must_not_suspend/gated.stderr
new file mode 100644
index 00000000000..be077deb3f1
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/gated.stderr
@@ -0,0 +1,54 @@
+error[E0658]: the `must_not_suspend` lint is unstable
+  --> $DIR/gated.rs:2:1
+   |
+LL | #![deny(must_not_suspend)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error[E0658]: the `must_not_suspend` lint is unstable
+  --> $DIR/gated.rs:2:1
+   |
+LL | #![deny(must_not_suspend)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error[E0658]: the `must_not_suspend` lint is unstable
+  --> $DIR/gated.rs:2:1
+   |
+LL | #![deny(must_not_suspend)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error: `MutexGuard` held across a suspend point, but should not be
+  --> $DIR/gated.rs:9: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/gated.rs:2:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
+  --> $DIR/gated.rs:9:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/gated.rs:9:9
+   |
+LL |     let _guard = m.lock().unwrap();
+   |         ^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/must_not_suspend/issue-89562.rs b/src/test/ui/lint/must_not_suspend/issue-89562.rs
new file mode 100644
index 00000000000..acdb36fcdab
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/issue-89562.rs
@@ -0,0 +1,19 @@
+// edition:2018
+// run-pass
+
+use std::sync::Mutex;
+
+// Copied from the issue. Allow-by-default for now, so run-pass
+pub async fn foo() {
+    let foo = Mutex::new(1);
+    let lock = foo.lock().unwrap();
+
+    // Prevent mutex lock being held across `.await` point.
+    drop(lock);
+
+    bar().await;
+}
+
+async fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/lint/must_not_suspend/mutex.rs b/src/test/ui/lint/must_not_suspend/mutex.rs
index 596249b2e4e..7bb895e7d36 100644
--- a/src/test/ui/lint/must_not_suspend/mutex.rs
+++ b/src/test/ui/lint/must_not_suspend/mutex.rs
@@ -1,4 +1,5 @@
 // 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 093f581264f..dde506c19e7 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:7:9
+  --> $DIR/mutex.rs:8: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:2:9
+  --> $DIR/mutex.rs:3:9
    |
 LL | #![deny(must_not_suspend)]
    |         ^^^^^^^^^^^^^^^^
 note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
-  --> $DIR/mutex.rs:7:9
+  --> $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:7:9
+  --> $DIR/mutex.rs:8:9
    |
 LL |     let _guard = m.lock().unwrap();
    |         ^^^^^^
diff --git a/src/test/ui/lint/must_not_suspend/warn.rs b/src/test/ui/lint/must_not_suspend/warn.rs
index 50a696ba523..7fdea66a235 100644
--- a/src/test/ui/lint/must_not_suspend/warn.rs
+++ b/src/test/ui/lint/must_not_suspend/warn.rs
@@ -1,6 +1,7 @@
 // edition:2018
 // run-pass
 #![feature(must_not_suspend)]
+#![warn(must_not_suspend)]
 
 #[must_not_suspend = "You gotta use Umm's, ya know?"]
 struct Umm {
diff --git a/src/test/ui/lint/must_not_suspend/warn.stderr b/src/test/ui/lint/must_not_suspend/warn.stderr
index 24f52275b43..42374d4acac 100644
--- a/src/test/ui/lint/must_not_suspend/warn.stderr
+++ b/src/test/ui/lint/must_not_suspend/warn.stderr
@@ -1,19 +1,23 @@
 warning: `Umm` held across a suspend point, but should not be
-  --> $DIR/warn.rs:20:9
+  --> $DIR/warn.rs:21:9
    |
 LL |     let _guard = bar();
    |         ^^^^^^
 LL |     other().await;
    |     ------------- the value is held across this suspend point
    |
-   = note: `#[warn(must_not_suspend)]` on by default
+note: the lint level is defined here
+  --> $DIR/warn.rs:4:9
+   |
+LL | #![warn(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
 note: You gotta use Umm's, ya know?
-  --> $DIR/warn.rs:20:9
+  --> $DIR/warn.rs:21:9
    |
 LL |     let _guard = bar();
    |         ^^^^^^
 help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
-  --> $DIR/warn.rs:20:9
+  --> $DIR/warn.rs:21:9
    |
 LL |     let _guard = bar();
    |         ^^^^^^