From 95ae8687df49e5fb0004b2950241b7e8b66499a1 Mon Sep 17 00:00:00 2001 From: Yuval Dolev Date: Sat, 16 Oct 2021 01:33:05 +0300 Subject: [PATCH 1/8] Handling submodule update failures more gracefully from x.py --- src/bootstrap/bootstrap.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 0170be967e1e3..f015928037277 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1005,7 +1005,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) From b8ecc9fefa4c9c763cf74e9c9659ecc00f30ba3a Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Fri, 29 Oct 2021 13:21:50 -0700 Subject: [PATCH 2/8] Fix rare ICE during typeck in rustdoc scrape_examples --- src/librustdoc/scrape_examples.rs | 20 +++++++++++++++++-- .../Makefile | 5 +++++ .../examples/ex.rs | 2 ++ .../src/lib.rs | 1 + .../src/lib.rs | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/test/run-make/rustdoc-scrape-examples-invalid-expr/Makefile create mode 100644 src/test/run-make/rustdoc-scrape-examples-invalid-expr/examples/ex.rs create mode 100644 src/test/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index fc54e55b87655..05e746573f479 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 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() {} From 3a95338f312c630e89c35ffa9e5ece97520e5253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 31 Oct 2021 00:00:00 +0000 Subject: [PATCH 3/8] Remove unnecessary `Option` from `promote_candidate` return type --- .../src/transform/promote_consts.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) 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 From 7bea8eafde0a9afec94af8fc14486069b81c3809 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 29 Oct 2021 14:48:54 +0200 Subject: [PATCH 4/8] Add doc about doc(keyword) unstable attribute --- src/doc/rustdoc/src/unstable-features.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) 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 From fadb9cc521da4f6010d80af5f750e8d9011c8f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 31 Oct 2021 00:00:00 +0000 Subject: [PATCH 5/8] Test that promotion follows references when looking for drop Noticed that this wasn't covered by any of existing tests. The const checking and const qualification, which currently shares the implementation with promotion, will likely need a different behaviour here (see issue #90193). --- src/test/ui/consts/promote-not.rs | 15 +++++ src/test/ui/consts/promote-not.stderr | 94 ++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 9 deletions(-) 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`. From 9137960c899b7d8893c79df2cef9c8effbe4280a Mon Sep 17 00:00:00 2001 From: pierwill Date: Sun, 31 Oct 2021 13:34:19 -0500 Subject: [PATCH 6/8] Remove `rustc_hir::hir_id::HirIdVec` --- compiler/rustc_hir/src/hir_id.rs | 68 -------------------------------- 1 file changed, 68 deletions(-) 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] - } -} From a4fe76ff7cd66d4cad19c0f32a5d3c9efd1d4a60 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Tue, 26 Oct 2021 18:50:07 -0700 Subject: [PATCH 7/8] Hide search bar in noscript.css Also, remove the highlighting of the search bar in disabled state. This reduces flicker when loading a page. --- src/librustdoc/html/static/css/noscript.css | 9 +++++++++ src/librustdoc/html/static/css/themes/ayu.css | 4 ---- src/librustdoc/html/static/css/themes/dark.css | 4 ---- src/librustdoc/html/static/css/themes/light.css | 4 ---- src/librustdoc/html/static/js/main.js | 4 +++- src/librustdoc/html/templates/page.html | 1 - src/test/rustdoc-gui/javascript-disabled.goml | 6 ++++++ 7 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 src/test/rustdoc-gui/javascript-disabled.goml 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 @@ Date: Tue, 12 Oct 2021 09:10:05 -0700 Subject: [PATCH 8/8] Feature gate and make must_not_suspend allow-by-default This lint is not yet ready for stable use, primarily due to false positives in edge cases; we want to test it out more before stabilizing. --- compiler/rustc_lint/src/lib.rs | 1 - compiler/rustc_lint_defs/src/builtin.rs | 4 +- .../issue-64130-non-send-future-diags.rs | 2 + .../issue-64130-non-send-future-diags.stderr | 6 +-- src/test/ui/async-await/issue-71137.rs | 2 + src/test/ui/async-await/issue-71137.stderr | 6 +-- src/test/ui/lint/must_not_suspend/gated.rs | 14 +++++ .../ui/lint/must_not_suspend/gated.stderr | 54 +++++++++++++++++++ .../ui/lint/must_not_suspend/issue-89562.rs | 19 +++++++ src/test/ui/lint/must_not_suspend/mutex.rs | 1 + .../ui/lint/must_not_suspend/mutex.stderr | 8 +-- src/test/ui/lint/must_not_suspend/warn.rs | 1 + src/test/ui/lint/must_not_suspend/warn.stderr | 12 +++-- 13 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/lint/must_not_suspend/gated.rs create mode 100644 src/test/ui/lint/must_not_suspend/gated.stderr create mode 100644 src/test/ui/lint/must_not_suspend/issue-89562.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 6f684a0fe5128..ee0567608f4ed 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -300,7 +300,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 f35ca2659fd65..c42d2471ca5e6 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/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/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(); | ^^^^^^