From 5ccef564560df65db0cb761cb27751f15821f1af Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Sat, 2 Jan 2021 22:03:21 +1100 Subject: [PATCH 01/28] Explain why borrows can't be held across yield point in async blocks --- .../diagnostics/conflict_errors.rs | 10 ++++++ .../issues/issue-78938-async-block.rs | 33 +++++++++++++++++++ .../issues/issue-78938-async-block.stderr | 30 +++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/test/ui/async-await/issues/issue-78938-async-block.rs create mode 100644 src/test/ui/async-await/issues/issue-78938-async-block.stderr diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 0bb09e26f03e8..1dd102f4f347f 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1323,6 +1323,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { suggestion, Applicability::MachineApplicable, ); + if let Some(generator_kind) = use_span.generator_kind() { + if let GeneratorKind::Async(_) = generator_kind { + err.note( + "borrows cannot be held across a yield point, because the stack space of the current \ + function is not preserved", + ); + err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ + for more information"); + } + } let msg = match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs new file mode 100644 index 0000000000000..e3d8eb7377223 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs @@ -0,0 +1,33 @@ +// edition:2018 + +use std::{sync::Arc, future::Future, pin::Pin, task::{Context,Poll}}; + +async fn f() { + let room_ref = Arc::new(Vec::new()); + + let gameloop_handle = spawn(async { //~ ERROR E0373 + game_loop(Arc::clone(&room_ref)) + }); + gameloop_handle.await; +} + +fn game_loop(v: Arc>) {} + +fn spawn(future: F) -> JoinHandle +where + F: Future + Send + 'static, + F::Output: Send + 'static, +{ + loop {} +} + +struct JoinHandle; + +impl Future for JoinHandle { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + loop {} + } +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr new file mode 100644 index 0000000000000..83cf1a5bc46e8 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -0,0 +1,30 @@ +error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function + --> $DIR/issue-78938-async-block.rs:8:39 + | +LL | let gameloop_handle = spawn(async { + | _______________________________________^ +LL | | game_loop(Arc::clone(&room_ref)) + | | -------- `room_ref` is borrowed here +LL | | }); + | |_____^ may outlive borrowed value `room_ref` + | + = note: borrows cannot be held across a yield point, because the stack space of the current function is not preserved + = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information +note: function requires argument type to outlive `'static` + --> $DIR/issue-78938-async-block.rs:8:33 + | +LL | let gameloop_handle = spawn(async { + | _________________________________^ +LL | | game_loop(Arc::clone(&room_ref)) +LL | | }); + | |_____^ +help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword + | +LL | let gameloop_handle = spawn(async move { +LL | game_loop(Arc::clone(&room_ref)) +LL | }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. From 12f17957432fa03a8fe57c2b6063c662add45c2c Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Sun, 3 Jan 2021 03:53:50 +1100 Subject: [PATCH 02/28] Fix location of error message explanation --- .../diagnostics/conflict_errors.rs | 22 ++++++++++--------- .../issues/issue-78938-async-block.rs | 6 ++--- .../issues/issue-78938-async-block.stderr | 4 ++-- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 1dd102f4f347f..43e9701aa25ac 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1323,16 +1323,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { suggestion, Applicability::MachineApplicable, ); - if let Some(generator_kind) = use_span.generator_kind() { - if let GeneratorKind::Async(_) = generator_kind { - err.note( - "borrows cannot be held across a yield point, because the stack space of the current \ - function is not preserved", - ); - err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ - for more information"); - } - } let msg = match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { @@ -1349,6 +1339,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ), }; err.span_note(constraint_span, &msg); + if let ConstraintCategory::CallArgument = category { + if let Some(generator_kind) = use_span.generator_kind() { + if let GeneratorKind::Async(_) = generator_kind { + err.note( + "borrows cannot be held across a yield point, because the stack \ + space of the current function is not preserved", + ); + err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ + for more information"); + } + } + } err } diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs index e3d8eb7377223..a16061fd979d9 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.rs +++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs @@ -16,7 +16,7 @@ fn game_loop(v: Arc>) {} fn spawn(future: F) -> JoinHandle where F: Future + Send + 'static, - F::Output: Send + 'static, + F::Output: Send + 'static, { loop {} } @@ -26,8 +26,8 @@ struct JoinHandle; impl Future for JoinHandle { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - loop {} + loop {} } } -fn main() {} \ No newline at end of file +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr index 83cf1a5bc46e8..604c47b430f82 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.stderr +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -8,8 +8,6 @@ LL | | game_loop(Arc::clone(&room_ref)) LL | | }); | |_____^ may outlive borrowed value `room_ref` | - = note: borrows cannot be held across a yield point, because the stack space of the current function is not preserved - = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information note: function requires argument type to outlive `'static` --> $DIR/issue-78938-async-block.rs:8:33 | @@ -18,6 +16,8 @@ LL | let gameloop_handle = spawn(async { LL | | game_loop(Arc::clone(&room_ref)) LL | | }); | |_____^ + = note: borrows cannot be held across a yield point, because the stack space of the current function is not preserved + = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword | LL | let gameloop_handle = spawn(async move { From 2b9c8ff6b37e0fd9143ba0f5a1fd11057880cebc Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Sun, 3 Jan 2021 04:00:51 +1100 Subject: [PATCH 03/28] Update issue-78938-async-block.rs Fix whitespace --- src/test/ui/async-await/issues/issue-78938-async-block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs index a16061fd979d9..86afef08fc7c9 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.rs +++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs @@ -26,7 +26,7 @@ struct JoinHandle; impl Future for JoinHandle { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - loop {} + loop {} } } From 9e345a58936edc81acf09d89675f71711f3d2439 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Sat, 9 Jan 2021 19:46:19 +1100 Subject: [PATCH 04/28] Revise async block error message --- .../diagnostics/conflict_errors.rs | 31 +++++++++---------- .../issues/issue-78938-async-block.stderr | 10 +----- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 43e9701aa25ac..85ea70cefba3f 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1324,33 +1324,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MachineApplicable, ); - let msg = match category { + match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { - format!("{} is returned here", kind) + let msg = format!("{} is returned here", kind); + err.span_note(constraint_span, &msg); } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); - format!("function requires argument type to outlive `{}`", fr_name) + if matches!(use_span.generator_kind(), Some(generator_kind) + if matches!(generator_kind, GeneratorKind::Async(_))) + { + err.note("async blocks are not executed immediately and either must take a \ + reference or ownership of outside variables they use"); + err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ + for more information"); + } else { + let msg = format!("function requires argument type to outlive `{}`", fr_name); + err.span_note(constraint_span, &msg); + } } _ => bug!( "report_escaping_closure_capture called with unexpected constraint \ category: `{:?}`", category ), - }; - err.span_note(constraint_span, &msg); - if let ConstraintCategory::CallArgument = category { - if let Some(generator_kind) = use_span.generator_kind() { - if let GeneratorKind::Async(_) = generator_kind { - err.note( - "borrows cannot be held across a yield point, because the stack \ - space of the current function is not preserved", - ); - err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ - for more information"); - } - } } + err } diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr index 604c47b430f82..4468975b2f5c3 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.stderr +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -8,15 +8,7 @@ LL | | game_loop(Arc::clone(&room_ref)) LL | | }); | |_____^ may outlive borrowed value `room_ref` | -note: function requires argument type to outlive `'static` - --> $DIR/issue-78938-async-block.rs:8:33 - | -LL | let gameloop_handle = spawn(async { - | _________________________________^ -LL | | game_loop(Arc::clone(&room_ref)) -LL | | }); - | |_____^ - = note: borrows cannot be held across a yield point, because the stack space of the current function is not preserved + = note: async blocks are not executed immediately and either must take a reference or ownership of outside variables they use = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword | From 757bd23503e16311190c943efba093d70d6b3454 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Sat, 9 Jan 2021 20:02:47 +1100 Subject: [PATCH 05/28] Remove trailing whitespace --- .../src/borrow_check/diagnostics/conflict_errors.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 85ea70cefba3f..49cdf8c3cbec8 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1331,11 +1331,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); - if matches!(use_span.generator_kind(), Some(generator_kind) + if matches!(use_span.generator_kind(), Some(generator_kind) if matches!(generator_kind, GeneratorKind::Async(_))) { - err.note("async blocks are not executed immediately and either must take a \ - reference or ownership of outside variables they use"); + err.note( + "async blocks are not executed immediately and either must take a \ + reference or ownership of outside variables they use", + ); err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ for more information"); } else { From 04b60362f8eafdcd62acc2232e9ba0459d5acb5d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 10 Jan 2021 23:01:49 -0500 Subject: [PATCH 06/28] Make `--color always` apply to logging too --- src/bootstrap/builder.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ec9ce4c820c69..62065e27dd966 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -814,12 +814,22 @@ impl<'a> Builder<'a> { cargo.env("REAL_LIBRARY_PATH", e); } + // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger` + // from out of tree it shouldn't matter, since x.py is only used for + // building in-tree. + let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"]; match self.build.config.color { Color::Always => { cargo.arg("--color=always"); + for log in &color_logs { + cargo.env(log, "always"); + } } Color::Never => { cargo.arg("--color=never"); + for log in &color_logs { + cargo.env(log, "never"); + } } Color::Auto => {} // nothing to do } From 3ee3071344334a0ac9defe876d6781d2d9658933 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Tue, 12 Jan 2021 14:12:12 +1100 Subject: [PATCH 07/28] Update src/test/ui/async-await/issues/issue-78938-async-block.stderr Co-authored-by: Esteban Kuber --- src/test/ui/async-await/issues/issue-78938-async-block.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr index 4468975b2f5c3..5450038c0d956 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.stderr +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -8,7 +8,7 @@ LL | | game_loop(Arc::clone(&room_ref)) LL | | }); | |_____^ may outlive borrowed value `room_ref` | - = note: async blocks are not executed immediately and either must take a reference or ownership of outside variables they use + = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword | From b2f504801c5c7cadc1e5f0c950ec11cef7c1a3ef Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 13 Jan 2021 14:51:27 +1000 Subject: [PATCH 08/28] stabilize the poll_map feature --- library/core/src/task/poll.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 6851f3fcd2fc7..42c9d9f0cc039 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -84,7 +84,7 @@ impl Poll> { impl Poll>> { /// Changes the success value of this `Poll` with the closure provided. - #[unstable(feature = "poll_map", issue = "63514")] + #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_ok(self, f: F) -> Poll>> where F: FnOnce(T) -> U, @@ -98,7 +98,7 @@ impl Poll>> { } /// Changes the error value of this `Poll` with the closure provided. - #[unstable(feature = "poll_map", issue = "63514")] + #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_err(self, f: F) -> Poll>> where F: FnOnce(E) -> U, From c20003627453df608b2c6929a1b2ab1c316389a9 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 20:57:57 -0800 Subject: [PATCH 09/28] Put all feature gate tests under `feature-gates/` There was one directory that had only a single test and there was also a test in the top-level directory. This moves both of them to `feature-gates/`. --- .../feature-gate-const_refs_to_cell.rs | 0 .../ui/{ => feature-gates}/feature-gate-edition_macro_pats.rs | 0 .../ui/{ => feature-gates}/feature-gate-edition_macro_pats.stderr | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{feature-gate => feature-gates}/feature-gate-const_refs_to_cell.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-edition_macro_pats.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-edition_macro_pats.stderr (100%) diff --git a/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs b/src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs similarity index 100% rename from src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs rename to src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs diff --git a/src/test/ui/feature-gate-edition_macro_pats.rs b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs similarity index 100% rename from src/test/ui/feature-gate-edition_macro_pats.rs rename to src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs diff --git a/src/test/ui/feature-gate-edition_macro_pats.stderr b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr similarity index 100% rename from src/test/ui/feature-gate-edition_macro_pats.stderr rename to src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr From 7f41465f6d025445374626c14958f8181a54c639 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Wed, 13 Jan 2021 23:37:49 +1100 Subject: [PATCH 10/28] Move help link to error index --- .../src/error_codes/E0373.md | 22 +++++++++++++++++++ .../diagnostics/conflict_errors.rs | 4 +--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index fd96987793115..1dec705260a61 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -50,3 +50,25 @@ fn foo() -> Box u32> { Now that the closure has its own copy of the data, there's no need to worry about safety. + +This error may also be encountered while using `async` blocks: + +```compile_fail,E0373 +use std::sync::Arc; +use tokio::runtime::Runtime; // 0.3.1 + +async fn f() { + let room_ref = Arc::new(Vec::new()); + + let gameloop_handle = Runtime::new().unwrap().spawn(async { + game_loop(Arc::clone(&room_ref)) + }); + gameloop_handle.await; +} + +fn game_loop(v: Arc>) {} +``` + +Similarly to closures, `async` blocks are not executed immediately and may +capture closed-over data by reference. For more information, see +https://rust-lang.github.io/async-book/03_async_await/01_chapter.html. \ No newline at end of file diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 49cdf8c3cbec8..fb817d3ca1e72 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1335,11 +1335,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if matches!(generator_kind, GeneratorKind::Async(_))) { err.note( - "async blocks are not executed immediately and either must take a \ + "async blocks are not executed immediately and must either take a \ reference or ownership of outside variables they use", ); - err.help("see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor \ - for more information"); } else { let msg = format!("function requires argument type to outlive `{}`", fr_name); err.span_note(constraint_span, &msg); From f5c428799f42a34cc22621cc865fba787a32b405 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Thu, 14 Jan 2021 01:02:49 +1100 Subject: [PATCH 11/28] Bless test output --- src/test/ui/async-await/issues/issue-78938-async-block.stderr | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr index 5450038c0d956..01ffc48d6542e 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.stderr +++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr @@ -9,7 +9,6 @@ LL | | }); | |_____^ may outlive borrowed value `room_ref` | = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use - = help: see https://rust-lang.github.io/async-book/03_async_await/01_chapter.html#awaiting-on-a-multithreaded-executor for more information help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword | LL | let gameloop_handle = spawn(async move { From a9ead34371e92767f0dfcf0d6d347a65988420af Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Thu, 14 Jan 2021 01:21:27 +1100 Subject: [PATCH 12/28] Fix whitespace --- compiler/rustc_error_codes/src/error_codes/E0373.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index 1dec705260a61..8da16eb6e5235 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -70,5 +70,5 @@ fn game_loop(v: Arc>) {} ``` Similarly to closures, `async` blocks are not executed immediately and may -capture closed-over data by reference. For more information, see -https://rust-lang.github.io/async-book/03_async_await/01_chapter.html. \ No newline at end of file +capture closed-over data by reference. For more information, see +https://rust-lang.github.io/async-book/03_async_await/01_chapter.html. From 174135fb3b212f53c4b24ffb243398306b9146d0 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:15:04 +1100 Subject: [PATCH 13/28] Fix error E0373 documentation --- .../src/error_codes/E0373.md | 30 ++++++++++++++----- .../issues/issue-78938-async-block.rs | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index 8da16eb6e5235..0723897614f79 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -54,19 +54,35 @@ about safety. This error may also be encountered while using `async` blocks: ```compile_fail,E0373 -use std::sync::Arc; -use tokio::runtime::Runtime; // 0.3.1 +use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}}; async fn f() { - let room_ref = Arc::new(Vec::new()); + let v = Arc::new(Vec::new()); - let gameloop_handle = Runtime::new().unwrap().spawn(async { - game_loop(Arc::clone(&room_ref)) + let handle = spawn(async { //~ ERROR E0373 + g(Arc::clone(&v)) }); - gameloop_handle.await; + handle.await; } -fn game_loop(v: Arc>) {} +fn g(v: Arc>) {} + +fn spawn(future: F) -> JoinHandle +where + F: Future + Send + 'static, + F::Output: Send + 'static, +{ + unimplemented!() +} + +struct JoinHandle; + +impl Future for JoinHandle { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unimplemented!() + } +} ``` Similarly to closures, `async` blocks are not executed immediately and may diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs index 86afef08fc7c9..36f7160198526 100644 --- a/src/test/ui/async-await/issues/issue-78938-async-block.rs +++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs @@ -1,6 +1,6 @@ // edition:2018 -use std::{sync::Arc, future::Future, pin::Pin, task::{Context,Poll}}; +use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}}; async fn f() { let room_ref = Arc::new(Vec::new()); From 63deae5e2525ab7428b205d13953423a6cd91bdd Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Thu, 14 Jan 2021 21:52:38 +1100 Subject: [PATCH 14/28] Fix E0373 code example --- compiler/rustc_error_codes/src/error_codes/E0373.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index 0723897614f79..540a88a0d959a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -53,7 +53,7 @@ about safety. This error may also be encountered while using `async` blocks: -```compile_fail,E0373 +```compile_fail,E0373,edition2018 use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}}; async fn f() { From 5468d9805aba869e7712b5aadabb021e692ba1d0 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Fri, 15 Jan 2021 16:50:48 +1100 Subject: [PATCH 15/28] Simplify E0373 async code example --- .../src/error_codes/E0373.md | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index 540a88a0d959a..effa597aad918 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -54,35 +54,18 @@ about safety. This error may also be encountered while using `async` blocks: ```compile_fail,E0373,edition2018 -use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}}; +use std::future::Future; async fn f() { - let v = Arc::new(Vec::new()); - - let handle = spawn(async { //~ ERROR E0373 - g(Arc::clone(&v)) + let v = vec![1, 2, 3i32]; + spawn(async { //~ ERROR E0373 + println!("{:?}", v) }); - handle.await; } -fn g(v: Arc>) {} - -fn spawn(future: F) -> JoinHandle -where - F: Future + Send + 'static, - F::Output: Send + 'static, -{ +fn spawn(future: F) { unimplemented!() } - -struct JoinHandle; - -impl Future for JoinHandle { - type Output = (); - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - unimplemented!() - } -} ``` Similarly to closures, `async` blocks are not executed immediately and may From 0660b8b5a592a004557147ebe128d5d8fd024cc5 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Wed, 28 Oct 2020 00:15:36 +0100 Subject: [PATCH 16/28] Introduce {Ref, RefMut}::try_map for optional projections --- library/core/src/cell.rs | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index c5ab7a39ff0ca..af421cb00f02c 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1261,6 +1261,36 @@ impl<'b, T: ?Sized> Ref<'b, T> { Ref { value: f(orig.value), borrow: orig.borrow } } + /// Makes a new `Ref` for an optional component of the borrowed data. + /// + /// The `RefCell` is already immutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `Ref::try_map(...)`. A method would interfere with methods of the same + /// name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_try_map)] + /// + /// use std::cell::{RefCell, Ref}; + /// + /// let c = RefCell::new(vec![1, 2, 3]); + /// let b1: Ref> = c.borrow(); + /// let b2: Option> = Ref::try_map(b1, |v| v.get(1)); + /// assert_eq!(b2.as_deref(), Some(&2)) + /// ``` + #[unstable(feature = "cell_try_map", reason = "recently added", issue = "none")] + #[inline] + pub fn try_map(orig: Ref<'b, T>, f: F) -> Option> + where + F: FnOnce(&T) -> Option<&U>, + { + let value = f(orig.value)?; + Some(Ref { value, borrow: orig.borrow }) + } + /// Splits a `Ref` into multiple `Ref`s for different components of the /// borrowed data. /// @@ -1372,6 +1402,46 @@ impl<'b, T: ?Sized> RefMut<'b, T> { RefMut { value: f(value), borrow } } + /// Makes a new `RefMut` for an optional component of the borrowed data. + /// + /// The `RefCell` is already mutably borrowed, so this cannot fail. + /// + /// This is an associated function that needs to be used as + /// `RefMut::try_map(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_try_map)] + /// + /// use std::cell::{RefCell, RefMut}; + /// + /// let c = RefCell::new(vec![1, 2, 3]); + /// + /// { + /// let b1: RefMut> = c.borrow_mut(); + /// let mut b2: Option> = RefMut::try_map(b1, |v| v.get_mut(1)); + /// + /// if let Some(mut b2) = b2 { + /// *b2 += 2; + /// } + /// } + /// + /// assert_eq!(*c.borrow(), vec![1, 4, 3]); + /// ``` + #[unstable(feature = "cell_try_map", reason = "recently added", issue = "none")] + #[inline] + pub fn try_map(orig: RefMut<'b, T>, f: F) -> Option> + where + F: FnOnce(&mut T) -> Option<&mut U>, + { + // FIXME(nll-rfc#40): fix borrow-check + let RefMut { value, borrow } = orig; + let value = f(value)?; + Some(RefMut { value, borrow }) + } + /// Splits a `RefMut` into multiple `RefMut`s for different components of the /// borrowed data. /// From 3e9c95b9d44aba57ee70a596b73af514046b4b26 Mon Sep 17 00:00:00 2001 From: 1000teslas <47207223+1000teslas@users.noreply.github.com> Date: Sat, 16 Jan 2021 03:32:54 +1100 Subject: [PATCH 17/28] Update compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs Co-authored-by: Esteban Kuber --- .../rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index fb817d3ca1e72..9325f94393ff1 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -1331,9 +1331,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); - if matches!(use_span.generator_kind(), Some(generator_kind) - if matches!(generator_kind, GeneratorKind::Async(_))) - { + if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) { err.note( "async blocks are not executed immediately and must either take a \ reference or ownership of outside variables they use", From e8757af311601681f8002b699ab0d64838e75eab Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Thu, 17 Dec 2020 01:46:06 +0100 Subject: [PATCH 18/28] Use Result and rename to filter_map The use of Result allows for making use of a reconstructed original value on failed projections. --- library/core/src/cell.rs | 52 ++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index af421cb00f02c..c0a0e2f618f5d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1261,34 +1261,38 @@ impl<'b, T: ?Sized> Ref<'b, T> { Ref { value: f(orig.value), borrow: orig.borrow } } - /// Makes a new `Ref` for an optional component of the borrowed data. + /// Makes a new `Ref` for an optional component of the borrowed data. The + /// original guard is returned as an `Err(..)` if the closure returns + /// `None`. /// /// The `RefCell` is already immutably borrowed, so this cannot fail. /// /// This is an associated function that needs to be used as - /// `Ref::try_map(...)`. A method would interfere with methods of the same + /// `Ref::filter_map(...)`. A method would interfere with methods of the same /// name on the contents of a `RefCell` used through `Deref`. /// /// # Examples /// /// ``` - /// #![feature(cell_try_map)] + /// #![feature(cell_filter_map)] /// /// use std::cell::{RefCell, Ref}; /// /// let c = RefCell::new(vec![1, 2, 3]); /// let b1: Ref> = c.borrow(); - /// let b2: Option> = Ref::try_map(b1, |v| v.get(1)); - /// assert_eq!(b2.as_deref(), Some(&2)) + /// let b2: Result, _> = Ref::filter_map(b1, |v| v.get(1)); + /// assert_eq!(*b2.unwrap(), 2); /// ``` - #[unstable(feature = "cell_try_map", reason = "recently added", issue = "none")] + #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "none")] #[inline] - pub fn try_map(orig: Ref<'b, T>, f: F) -> Option> + pub fn filter_map(orig: Ref<'b, T>, f: F) -> Result, Self> where F: FnOnce(&T) -> Option<&U>, { - let value = f(orig.value)?; - Some(Ref { value, borrow: orig.borrow }) + match f(orig.value) { + Some(value) => Ok(Ref { value, borrow: orig.borrow }), + None => Err(orig), + } } /// Splits a `Ref` into multiple `Ref`s for different components of the @@ -1402,18 +1406,20 @@ impl<'b, T: ?Sized> RefMut<'b, T> { RefMut { value: f(value), borrow } } - /// Makes a new `RefMut` for an optional component of the borrowed data. + /// Makes a new `RefMut` for an optional component of the borrowed data. The + /// original guard is returned as an `Err(..)` if the closure returns + /// `None`. /// /// The `RefCell` is already mutably borrowed, so this cannot fail. /// /// This is an associated function that needs to be used as - /// `RefMut::try_map(...)`. A method would interfere with methods of the + /// `RefMut::filter_map(...)`. A method would interfere with methods of the /// same name on the contents of a `RefCell` used through `Deref`. /// /// # Examples /// /// ``` - /// #![feature(cell_try_map)] + /// #![feature(cell_filter_map)] /// /// use std::cell::{RefCell, RefMut}; /// @@ -1421,25 +1427,35 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// /// { /// let b1: RefMut> = c.borrow_mut(); - /// let mut b2: Option> = RefMut::try_map(b1, |v| v.get_mut(1)); + /// let mut b2: Result, _> = RefMut::filter_map(b1, |v| v.get_mut(1)); /// - /// if let Some(mut b2) = b2 { + /// if let Ok(mut b2) = b2 { /// *b2 += 2; /// } /// } /// /// assert_eq!(*c.borrow(), vec![1, 4, 3]); /// ``` - #[unstable(feature = "cell_try_map", reason = "recently added", issue = "none")] + #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "none")] #[inline] - pub fn try_map(orig: RefMut<'b, T>, f: F) -> Option> + pub fn filter_map(orig: RefMut<'b, T>, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut U>, { // FIXME(nll-rfc#40): fix borrow-check let RefMut { value, borrow } = orig; - let value = f(value)?; - Some(RefMut { value, borrow }) + let value = value as *mut T; + // SAFETY: function holds onto an exclusive reference for the duration + // of its call through `orig`, and the pointer is only de-referenced + // inside of the function call never allowing the exclusive reference to + // escape. + match f(unsafe { &mut *value }) { + Some(value) => Ok(RefMut { value, borrow }), + None => { + // SAFETY: same as above. + Err(RefMut { value: unsafe { &mut *value }, borrow }) + } + } } /// Splits a `RefMut` into multiple `RefMut`s for different components of the From e3274fd148273796e93c142d8cef28acc3af0b60 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 14 Jan 2021 14:49:58 -0500 Subject: [PATCH 19/28] Remove doctree::Import --- src/librustdoc/clean/mod.rs | 180 ++++++++++++++++++------------------ src/librustdoc/doctree.rs | 14 --- src/librustdoc/visit_ast.rs | 10 +- 3 files changed, 90 insertions(+), 114 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5ec79c586dcac..0aabd9477e325 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -219,7 +219,6 @@ impl Clean for CrateNum { impl Clean for doctree::Module<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let mut items: Vec = vec![]; - items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); items.extend(self.foreigns.iter().map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); items.extend(self.items.iter().map(|x| x.clean(cx)).flatten()); @@ -2019,7 +2018,7 @@ impl Clean> for (&hir::Item<'_>, Option) { ItemKind::Fn(ref sig, ref generics, body_id) => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } - hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { + ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { let items = item_ids .iter() .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)) @@ -2038,6 +2037,9 @@ impl Clean> for (&hir::Item<'_>, Option) { ItemKind::ExternCrate(orig_name) => { return clean_extern_crate(item, name, orig_name, cx); } + ItemKind::Use(path, kind) => { + return clean_use_statement(item, name, path, kind, cx); + } _ => unreachable!("not yet converted"), }; @@ -2159,105 +2161,101 @@ fn clean_extern_crate( }] } -impl Clean> for doctree::Import<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Vec { - // We need this comparison because some imports (for std types for example) - // are "inserted" as well but directly by the compiler and they should not be - // taken into account. - if self.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { - return Vec::new(); - } - - let (doc_meta_item, please_inline) = self.attrs.lists(sym::doc).get_word_attr(sym::inline); - let pub_underscore = self.vis.node.is_pub() && self.name == kw::Underscore; - - if pub_underscore && please_inline { - rustc_errors::struct_span_err!( - cx.tcx.sess, - doc_meta_item.unwrap().span(), - E0780, - "anonymous imports cannot be inlined" - ) - .span_label(self.span, "anonymous import") - .emit(); - } +fn clean_use_statement( + import: &hir::Item<'_>, + name: Symbol, + path: &hir::Path<'_>, + kind: hir::UseKind, + cx: &DocContext<'_>, +) -> Vec { + // We need this comparison because some imports (for std types for example) + // are "inserted" as well but directly by the compiler and they should not be + // taken into account. + if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { + return Vec::new(); + } + + let (doc_meta_item, please_inline) = import.attrs.lists(sym::doc).get_word_attr(sym::inline); + let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore; + + if pub_underscore && please_inline { + rustc_errors::struct_span_err!( + cx.tcx.sess, + doc_meta_item.unwrap().span(), + E0780, + "anonymous imports cannot be inlined" + ) + .span_label(import.span, "anonymous import") + .emit(); + } - // We consider inlining the documentation of `pub use` statements, but we - // forcefully don't inline if this is not public or if the - // #[doc(no_inline)] attribute is present. - // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let mut denied = !self.vis.node.is_pub() - || pub_underscore - || self.attrs.iter().any(|a| { - a.has_name(sym::doc) - && match a.meta_item_list() { - Some(l) => { - attr::list_contains_name(&l, sym::no_inline) - || attr::list_contains_name(&l, sym::hidden) - } - None => false, + // We consider inlining the documentation of `pub use` statements, but we + // forcefully don't inline if this is not public or if the + // #[doc(no_inline)] attribute is present. + // Don't inline doc(hidden) imports so they can be stripped at a later stage. + let mut denied = !import.vis.node.is_pub() + || pub_underscore + || import.attrs.iter().any(|a| { + a.has_name(sym::doc) + && match a.meta_item_list() { + Some(l) => { + attr::list_contains_name(&l, sym::no_inline) + || attr::list_contains_name(&l, sym::hidden) } - }); - // Also check whether imports were asked to be inlined, in case we're trying to re-export a - // crate in Rust 2018+ - let path = self.path.clean(cx); - let inner = if self.glob { - if !denied { - let mut visited = FxHashSet::default(); - if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) { - return items; + None => false, } + }); + + // Also check whether imports were asked to be inlined, in case we're trying to re-export a + // crate in Rust 2018+ + let path = path.clean(cx); + let inner = if kind == hir::UseKind::Glob { + if !denied { + let mut visited = FxHashSet::default(); + if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) { + return items; } - Import::new_glob(resolve_use_source(cx, path), true) - } else { - let name = self.name; - if !please_inline { - if let Res::Def(DefKind::Mod, did) = path.res { - if !did.is_local() && did.index == CRATE_DEF_INDEX { - // if we're `pub use`ing an extern crate root, don't inline it unless we - // were specifically asked for it - denied = true; - } + } + Import::new_glob(resolve_use_source(cx, path), true) + } else { + if !please_inline { + if let Res::Def(DefKind::Mod, did) = path.res { + if !did.is_local() && did.index == CRATE_DEF_INDEX { + // if we're `pub use`ing an extern crate root, don't inline it unless we + // were specifically asked for it + denied = true; } } - if !denied { - let mut visited = FxHashSet::default(); + } + if !denied { + let mut visited = FxHashSet::default(); - if let Some(mut items) = inline::try_inline( + if let Some(mut items) = inline::try_inline( + cx, + cx.tcx.parent_module(import.hir_id).to_def_id(), + path.res, + name, + Some(import.attrs), + &mut visited, + ) { + items.push(Item::from_def_id_and_parts( + cx.tcx.hir().local_def_id(import.hir_id).to_def_id(), + None, + ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), cx, - cx.tcx.parent_module(self.id).to_def_id(), - path.res, - name, - Some(self.attrs), - &mut visited, - ) { - items.push(Item { - name: None, - attrs: box self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), - visibility: self.vis.clean(cx), - kind: box ImportItem(Import::new_simple( - self.name, - resolve_use_source(cx, path), - false, - )), - }); - return items; - } + )); + return items; } - Import::new_simple(name, resolve_use_source(cx, path), true) - }; + } + Import::new_simple(name, resolve_use_source(cx, path), true) + }; - vec![Item { - name: None, - attrs: box self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), - visibility: self.vis.clean(cx), - kind: box ImportItem(inner), - }] - } + vec![Item::from_def_id_and_parts( + cx.tcx.hir().local_def_id(import.hir_id).to_def_id(), + None, + ImportItem(inner), + cx, + )] } impl Clean for (&hir::ForeignItem<'_>, Option) { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 4710c91f929bd..f90623c03118b 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -2,7 +2,6 @@ //! manner (and with prettier names) before cleaning. crate use self::StructType::*; -use rustc_ast as ast; use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; @@ -11,7 +10,6 @@ crate struct Module<'hir> { crate name: Option, crate where_outer: Span, crate where_inner: Span, - crate imports: Vec>, crate mods: Vec>, crate id: hir::HirId, // (item, renamed) @@ -28,7 +26,6 @@ impl Module<'hir> { id: hir::CRATE_HIR_ID, where_outer: rustc_span::DUMMY_SP, where_inner: rustc_span::DUMMY_SP, - imports: Vec::new(), mods: Vec::new(), items: Vec::new(), foreigns: Vec::new(), @@ -48,17 +45,6 @@ crate enum StructType { Unit, } -#[derive(Debug)] -crate struct Import<'hir> { - crate name: Symbol, - crate id: hir::HirId, - crate vis: &'hir hir::Visibility<'hir>, - crate attrs: &'hir [ast::Attribute], - crate path: &'hir hir::Path<'hir>, - crate glob: bool, - crate span: Span, -} - crate fn struct_type_from_def(vdata: &hir::VariantData<'_>) -> StructType { match *vdata { hir::VariantData::Struct(..) => Plain, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index f701352c486ba..7d161ca3648cc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -316,15 +316,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - om.imports.push(Import { - name, - id: item.hir_id, - vis: &item.vis, - attrs: &item.attrs, - path, - glob: is_glob, - span: item.span, - }); + om.items.push((item, renamed)) } hir::ItemKind::Mod(ref m) => { om.mods.push(self.visit_mod_contents( From 2a0c9e28cb5136c72753c93752c18ee64abc8a88 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 14 Jan 2021 15:03:17 -0500 Subject: [PATCH 20/28] Address nit --- src/librustdoc/clean/mod.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0aabd9477e325..e2cc7547781d5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2208,6 +2208,7 @@ fn clean_use_statement( // Also check whether imports were asked to be inlined, in case we're trying to re-export a // crate in Rust 2018+ + let def_id = cx.tcx.hir().local_def_id(import.hir_id).to_def_id(); let path = path.clean(cx); let inner = if kind == hir::UseKind::Glob { if !denied { @@ -2239,7 +2240,7 @@ fn clean_use_statement( &mut visited, ) { items.push(Item::from_def_id_and_parts( - cx.tcx.hir().local_def_id(import.hir_id).to_def_id(), + def_id, None, ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), cx, @@ -2250,12 +2251,7 @@ fn clean_use_statement( Import::new_simple(name, resolve_use_source(cx, path), true) }; - vec![Item::from_def_id_and_parts( - cx.tcx.hir().local_def_id(import.hir_id).to_def_id(), - None, - ImportItem(inner), - cx, - )] + vec![Item::from_def_id_and_parts(def_id, None, ImportItem(inner), cx)] } impl Clean for (&hir::ForeignItem<'_>, Option) { From e42c1b9c2acb218217c02ee25514b39a1b4efb62 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 14 Jan 2021 19:01:48 -0500 Subject: [PATCH 21/28] Fix JSON test --- src/test/rustdoc-json/nested.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc-json/nested.expected b/src/test/rustdoc-json/nested.expected index 65bb0c5fa0367..80070e75f1e5e 100644 --- a/src/test/rustdoc-json/nested.expected +++ b/src/test/rustdoc-json/nested.expected @@ -41,8 +41,8 @@ "inner": { "is_crate": false, "items": [ - "0:7", - "0:4" + "0:4", + "0:7" ] }, "kind": "module", From 31b17f513b79e7213f16c8acdcc38a5b9018d8a4 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 14 Jan 2021 19:39:59 -0500 Subject: [PATCH 22/28] Add warning to compare.py about error messages --- src/test/rustdoc-json/compare.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/rustdoc-json/compare.py b/src/test/rustdoc-json/compare.py index b0c5b16a19700..6a921266336e0 100644 --- a/src/test/rustdoc-json/compare.py +++ b/src/test/rustdoc-json/compare.py @@ -7,6 +7,9 @@ # and then create `yourtest.expected` by stripping unnecessary details from `yourtest.json`. If # you're on windows, replace `\` with `/`. +# WARNING: The error messages produced by this may be misleading, in the case of list re-ordering +# it may point to apparently unrelated keys. + import copy import sys import json From 32a20f4433c7fa8a5b6c517ff934cab8da3670c9 Mon Sep 17 00:00:00 2001 From: Han Mertens Date: Fri, 15 Jan 2021 21:50:05 +0100 Subject: [PATCH 23/28] Change rebuild heuristic in BinaryHeap::append See #77433 for why the new heuristic was chosen. Fixes #77433 --- library/alloc/src/collections/binary_heap.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 76051d9e1dffd..4dfdbe0a5b45b 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -630,10 +630,16 @@ impl BinaryHeap { // and about 2 * (len1 + len2) comparisons in the worst case // while `extend` takes O(len2 * log(len1)) operations // and about 1 * len2 * log_2(len1) comparisons in the worst case, - // assuming len1 >= len2. + // assuming len1 >= len2. For larger heaps, the crossover point + // no longer follows this reasoning and was determined empirically. #[inline] fn better_to_rebuild(len1: usize, len2: usize) -> bool { - 2 * (len1 + len2) < len2 * log2_fast(len1) + let tot_len = len1 + len2; + if tot_len <= 2048 { + 2 * tot_len < len2 * log2_fast(len1) + } else { + 2 * tot_len < len2 * 11 + } } if better_to_rebuild(self.len(), other.len()) { From c625b979aed9ad3c8380ea2239d9345d4cec695a Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sat, 16 Jan 2021 10:40:36 +1000 Subject: [PATCH 24/28] add tracking issue to cell_filter_map --- library/core/src/cell.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index c0a0e2f618f5d..fa0fbaa35c95c 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1283,7 +1283,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// let b2: Result, _> = Ref::filter_map(b1, |v| v.get(1)); /// assert_eq!(*b2.unwrap(), 2); /// ``` - #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "none")] + #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")] #[inline] pub fn filter_map(orig: Ref<'b, T>, f: F) -> Result, Self> where @@ -1436,7 +1436,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// /// assert_eq!(*c.borrow(), vec![1, 4, 3]); /// ``` - #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "none")] + #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")] #[inline] pub fn filter_map(orig: RefMut<'b, T>, f: F) -> Result, Self> where From eef383fa00be7565123f62e2dddd325e10e3ec21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Fri, 15 Jan 2021 15:51:32 +0300 Subject: [PATCH 25/28] doctest: Reset errors before dropping the parse session The first parse is to collect whether the code contains macros, has `main`, and uses other crates. In that pass we ignore errors as those will be reported when the test file is actually built. For that we need to reset errors in the `Diagnostic` otherwise when dropping it unhandled errors will be reported as compiler bugs. Fixes #80992 --- src/librustdoc/doctest.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index cf51162cfb52f..3de97f2dd2e59 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -500,6 +500,12 @@ crate fn make_test( } } + // Reset errors so that they won't be reported as compiler bugs when dropping the + // handler. Any errors in the tests will be reported when the test file is compiled, + // Note that we still need to cancel the errors above otherwise `DiagnosticBuilder` + // will panic on drop. + sess.span_diagnostic.reset_err_count(); + (found_main, found_extern_crate, found_macro) }) }); From 0ef55570fb35a79a32bc062c0a441c02952fd65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Sat, 16 Jan 2021 06:55:16 +0300 Subject: [PATCH 26/28] Add a test --- src/test/rustdoc-ui/issue-80992.rs | 11 +++++++++++ src/test/rustdoc-ui/issue-80992.stdout | 6 ++++++ 2 files changed, 17 insertions(+) create mode 100644 src/test/rustdoc-ui/issue-80992.rs create mode 100644 src/test/rustdoc-ui/issue-80992.stdout diff --git a/src/test/rustdoc-ui/issue-80992.rs b/src/test/rustdoc-ui/issue-80992.rs new file mode 100644 index 0000000000000..8983439bb64d3 --- /dev/null +++ b/src/test/rustdoc-ui/issue-80992.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +pub fn test() -> Result<(), ()> { + //! ```compile_fail + //! fn test() -> Result< {} + //! ``` + Ok(()) +} diff --git a/src/test/rustdoc-ui/issue-80992.stdout b/src/test/rustdoc-ui/issue-80992.stdout new file mode 100644 index 0000000000000..1dd19f468274c --- /dev/null +++ b/src/test/rustdoc-ui/issue-80992.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/issue-80992.rs - test (line 7) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From b681631eff8d842c9b5f1e9d7fcf5d8259a02a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Sat, 16 Jan 2021 07:17:13 +0300 Subject: [PATCH 27/28] codegen_cranelift: Fix redundant semicolon warn --- compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index be5b247bb9f0b..8946ac43bc65a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -824,7 +824,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( } ty => unreachable!("bswap {}", ty), } - }; + } let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T)); ret.write_cvalue(fx, res); }; From 8797986391022adf98bde252002dcfc9eaaef975 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 11 Jan 2021 13:20:18 +0900 Subject: [PATCH 28/28] Add a regression test for #76281 This has been fixed between 1.47.0-nightly (663d2f5cd 2020-08-22) and 1.47.0-nightly (5180f3da5 2020-08-23). --- src/test/ui/wasm/wasm-hang-issue-76281.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/wasm/wasm-hang-issue-76281.rs diff --git a/src/test/ui/wasm/wasm-hang-issue-76281.rs b/src/test/ui/wasm/wasm-hang-issue-76281.rs new file mode 100644 index 0000000000000..a4adfa6d04461 --- /dev/null +++ b/src/test/ui/wasm/wasm-hang-issue-76281.rs @@ -0,0 +1,12 @@ +// only-wasm32 +// compile-flags: -C opt-level=2 +// build-pass + +// Regression test for #76281. +// This seems like an issue related to LLVM rather than +// libs-impl so place here. + +fn main() { + let mut v: Vec<&()> = Vec::new(); + v.sort_by_key(|&r| r as *const ()); +}