diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 67664d2ede1dd..7bf378601e053 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> { + 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 877871f7c3d80..39552eb9f3102 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 { - map: IndexVec>, -} - -impl HirIdVec { - 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 { - &self.map[id] - } - - pub fn iter(&self) -> impl Iterator { - self.map.iter().flat_map(|la| la.iter()) - } - - pub fn iter_enumerated(&self) -> impl Iterator { - self.map.iter_enumerated().flat_map(|(owner, la)| { - la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr)) - }) - } -} - -impl std::ops::Index for HirIdVec { - type Output = T; - - fn index(&self, id: HirId) -> &T { - &self.map[id.owner][id.local_id] - } -} - -impl std::ops::IndexMut for HirIdVec { - 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 d98d65385e533..f6514ddca9f57 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 1db9d3f65d4e4..b83d04f3dc2e7 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 0c5a0cbc06eb9..38d3c7aec4941 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1026,7 +1026,15 @@ def update_submodule(self, module, checked_out, recorded_submodules): 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 51f365be922fa..b3b6422afab42 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 0a196edd53b1d..37ea7b000339f 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 f9c84dc3e318d..ba7fb3b5456a5 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 9a38277d55905..77ac217e6f41d 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 fba8231caac31..6df137e391415 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 e396fd9d288db..c421c6e9dc16e 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 b0174d59a7be2..cead54412bbbd 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -85,7 +85,6 @@ ) { 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 0000000000000..dce8b83eefe4e --- /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 0000000000000..b342b5b0aaece --- /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 0000000000000..c30c99dec6038 --- /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 bd59584bbbf4f..bdfeda92d79a0 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 0000000000000..1693f7b645f1b --- /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 656ade67c71a7..b652d23915330 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 7125c62dbaf9a..a373ba6aa7136 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: 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 ebb392a45308e..7695e0325ff31 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 ac254346c08a6..3cc800f96c20d 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: 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 99926532247ab..6830b23cfa345 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 932109bd86dcf..0d0b0f9c689b5 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 0000000000000..acb81b0bf9def --- /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 0000000000000..be077deb3f197 --- /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 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 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 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 0000000000000..acdb36fcdabf9 --- /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 596249b2e4e4f..7bb895e7d3643 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 093f581264f36..dde506c19e725 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 50a696ba52322..7fdea66a23517 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 24f52275b430a..42374d4acac27 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(); | ^^^^^^