From 25a7d2d540656e0499a43bfd01243250f2a25d7a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 10 Mar 2022 08:47:53 -0600 Subject: [PATCH 1/9] Fix `cargo run tidy` When I implemented rust-only bootstrapping in https://github.com/rust-lang/rust/pull/92260, I neglected to test stage0 tools - it turns out they were broken because they couldn't find the sysroot of the initial bootstrap compiler. This fixes stage0 tools by using `rustc --print sysroot` instead of assuming rustc is already in a sysroot and hard-coding the relative directory. --- src/bootstrap/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2ae63858ff610..91a0e40ca183d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -117,6 +117,7 @@ use std::os::unix::fs::symlink as symlink_file; use std::os::windows::fs::symlink_file; use filetime::FileTime; +use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; @@ -892,7 +893,12 @@ impl Build { /// Returns the sysroot of the snapshot compiler. fn rustc_snapshot_sysroot(&self) -> &Path { - self.initial_rustc.parent().unwrap().parent().unwrap() + static SYSROOT_CACHE: OnceCell = once_cell::sync::OnceCell::new(); + SYSROOT_CACHE.get_or_init(|| { + let mut rustc = Command::new(&self.initial_rustc); + rustc.args(&["--print", "sysroot"]); + output(&mut rustc).trim().into() + }) } /// Runs a command, printing out nice contextual information if it fails. From 5a25e228eb7df1f8d227460c577215e5c75794b2 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 19 Mar 2022 19:53:26 -0700 Subject: [PATCH 2/9] Stabilize thread::is_finished --- library/std/src/thread/mod.rs | 2 +- library/std/src/thread/scoped.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index ae292caaed994..5309dc47ac4e7 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1471,7 +1471,7 @@ impl JoinHandle { /// /// This function does not block. To block while waiting on the thread to finish, /// use [`join`][Self::join]. - #[unstable(feature = "thread_is_running", issue = "90470")] + #[stable(feature = "thread_is_running", since = "1.61.0")] pub fn is_finished(&self) -> bool { Arc::strong_count(&self.0.packet) == 1 } diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 07e113f3b6222..e3da79932c721 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -316,7 +316,7 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> { /// /// This function does not block. To block while waiting on the thread to finish, /// use [`join`][Self::join]. - #[unstable(feature = "thread_is_running", issue = "90470")] + #[stable(feature = "thread_is_running", since = "1.61.0")] pub fn is_finished(&self) -> bool { Arc::strong_count(&self.0.packet) == 1 } From 0cf606177e79bc580fa27a82eb9c8b56e7253f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Horstmann?= Date: Fri, 25 Mar 2022 11:39:11 +0100 Subject: [PATCH 3/9] Fix double drop of allocator in IntoIter impl of Vec --- library/alloc/src/vec/into_iter.rs | 15 +++++++++------ library/alloc/src/vec/mod.rs | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index f17b8d71b3a1a..471042cd7177e 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -8,7 +8,8 @@ use core::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self}; +use core::mem::{self, ManuallyDrop}; +use core::ops::Deref; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -32,7 +33,9 @@ pub struct IntoIter< pub(super) buf: NonNull, pub(super) phantom: PhantomData, pub(super) cap: usize, - pub(super) alloc: A, + // the drop impl reconstructs a RawVec from buf, cap and alloc + // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop + pub(super) alloc: ManuallyDrop, pub(super) ptr: *const T, pub(super) end: *const T, } @@ -295,11 +298,11 @@ where impl Clone for IntoIter { #[cfg(not(test))] fn clone(&self) -> Self { - self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() } #[cfg(test)] fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() + crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter() } } @@ -311,8 +314,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { impl Drop for DropGuard<'_, T, A> { fn drop(&mut self) { unsafe { - // `IntoIter::alloc` is not used anymore after this - let alloc = ptr::read(&self.0.alloc); + // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec + let alloc = ManuallyDrop::into_inner(ptr::read(&self.0.alloc)); // RawVec handles deallocation let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 9a66e69bdc061..96857c4bd6ffd 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2575,7 +2575,7 @@ impl IntoIterator for Vec { fn into_iter(self) -> IntoIter { unsafe { let mut me = ManuallyDrop::new(self); - let alloc = ptr::read(me.allocator()); + let alloc = ManuallyDrop::new(ptr::read(me.allocator())); let begin = me.as_mut_ptr(); let end = if mem::size_of::() == 0 { arith_offset(begin as *const i8, me.len() as isize) as *const T From d14c0d2acb3ff1d0111920185109c9697a3cd460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Horstmann?= Date: Fri, 25 Mar 2022 13:27:18 +0100 Subject: [PATCH 4/9] Use ManuallyDrop::take instead of into_inner Co-authored-by: Daniel Henry-Mantilla --- library/alloc/src/vec/into_iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 471042cd7177e..1f9398faf2267 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -315,7 +315,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { fn drop(&mut self) { unsafe { // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec - let alloc = ManuallyDrop::into_inner(ptr::read(&self.0.alloc)); + let alloc = ManuallyDrop::take(&mut self.0.alloc); // RawVec handles deallocation let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); } From 4b53f563bd5b0f0e9cad26dbf2514f9a72c3fa2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Horstmann?= Date: Fri, 25 Mar 2022 13:00:49 +0100 Subject: [PATCH 5/9] Add a test verifying the number of drop calls --- library/alloc/tests/vec.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ca0fcc855c7b8..ab2414a6dc0b4 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1,3 +1,6 @@ +use core::alloc::{Allocator, Layout}; +use core::ptr::NonNull; +use std::alloc::System; use std::assert_matches::assert_matches; use std::borrow::Cow; use std::cell::Cell; @@ -991,6 +994,27 @@ fn test_into_iter_advance_by() { assert_eq!(i.len(), 0); } +#[test] +fn test_into_iter_drop_allocator() { + struct ReferenceCountedAllocator<'a>(DropCounter<'a>); + + unsafe impl Allocator for ReferenceCountedAllocator<'_> { + fn allocate(&self, layout: Layout) -> Result, core::alloc::AllocError> { + System.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + System.deallocate(ptr, layout) + } + } + + let mut drop_count = 0; + let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); + let _ = Vec::::new_in(allocator).into_iter(); + + assert_eq!(drop_count, 1); +} + #[test] fn test_from_iter_specialization() { let src: Vec = vec![0usize; 1]; From d9a438dc73de6ff146ae3e6bc4050b7cea41b09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Horstmann?= Date: Fri, 25 Mar 2022 16:57:59 +0100 Subject: [PATCH 6/9] Add another assertion without into_iter --- library/alloc/tests/vec.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ab2414a6dc0b4..19e39ebf910b5 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1009,10 +1009,14 @@ fn test_into_iter_drop_allocator() { } let mut drop_count = 0; - let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); - let _ = Vec::::new_in(allocator).into_iter(); + let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); + let _ = Vec::::new_in(allocator); assert_eq!(drop_count, 1); + + let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); + let _ = Vec::::new_in(allocator).into_iter(); + assert_eq!(drop_count, 2); } #[test] From 78e27e2c7a85021a0b72253c17d0d99a383e8385 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 16 Mar 2022 15:52:21 +0100 Subject: [PATCH 7/9] async: Give predictable, reserved name to binding generated from .await expressions. This name makes it to debuginfo and allows debuggers to identify such bindings and their captured versions in suspended async fns. --- compiler/rustc_ast_lowering/src/expr.rs | 29 ++++++++++--------- compiler/rustc_span/src/symbol.rs | 2 +- .../codegen/async-fn-debug-awaitee-field.rs | 23 +++++++++++++++ 3 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 src/test/codegen/async-fn-debug-awaitee-field.rs diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d64f1a05712a9..9442e0f1a1f35 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -618,9 +618,9 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Desugar `.await` into: /// ```rust /// match ::std::future::IntoFuture::into_future() { - /// mut pinned => loop { + /// mut __awaitee => loop { /// match unsafe { ::std::future::Future::poll( - /// <::std::pin::Pin>::new_unchecked(&mut pinned), + /// <::std::pin::Pin>::new_unchecked(&mut __awaitee), /// ::std::future::get_context(task_context), /// ) } { /// ::std::task::Poll::Ready(result) => break result, @@ -657,21 +657,24 @@ impl<'hir> LoweringContext<'_, 'hir> { let expr = self.lower_expr_mut(expr); let expr_hir_id = expr.hir_id; - let pinned_ident = Ident::with_dummy_span(sym::pinned); - let (pinned_pat, pinned_pat_hid) = - self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable); + // Note that the name of this binding must not be changed to something else because + // debuggers and debugger extensions expect it to be called `__awaitee`. They use + // this name to identify what is being awaited by a suspended async functions. + let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); + let (awaitee_pat, awaitee_pat_hid) = + self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable); let task_context_ident = Ident::with_dummy_span(sym::_task_context); // unsafe { // ::std::future::Future::poll( - // ::std::pin::Pin::new_unchecked(&mut pinned), + // ::std::pin::Pin::new_unchecked(&mut __awaitee), // ::std::future::get_context(task_context), // ) // } let poll_expr = { - let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid); - let ref_mut_pinned = self.expr_mut_addr_of(span, pinned); + let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid); + let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee); let task_context = if let Some(task_context_hid) = self.task_context { self.expr_ident_mut(span, task_context_ident, task_context_hid) } else { @@ -681,7 +684,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let new_unchecked = self.expr_call_lang_item_fn_mut( span, hir::LangItem::PinNewUnchecked, - arena_vec![self; ref_mut_pinned], + arena_vec![self; ref_mut_awaitee], Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( @@ -782,8 +785,8 @@ impl<'hir> LoweringContext<'_, 'hir> { span: self.lower_span(span), }); - // mut pinned => loop { ... } - let pinned_arm = self.arm(pinned_pat, loop_expr); + // mut __awaitee => loop { ... } + let awaitee_arm = self.arm(awaitee_pat, loop_expr); // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_span = self.mark_span_with_reason( @@ -799,11 +802,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ); // match { - // mut pinned => loop { .. } + // mut __awaitee => loop { .. } // } hir::ExprKind::Match( into_future_expr, - arena_vec![self; pinned_arm], + arena_vec![self; awaitee_arm], hir::MatchSource::AwaitDesugar, ) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4dd1c3fed6b36..774cf6a19c76d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -272,6 +272,7 @@ symbols! { __D, __H, __S, + __awaitee, __try_var, _d, _e, @@ -1022,7 +1023,6 @@ symbols! { pattern_parentheses, phantom_data, pin, - pinned, platform_intrinsics, plugin, plugin_registrar, diff --git a/src/test/codegen/async-fn-debug-awaitee-field.rs b/src/test/codegen/async-fn-debug-awaitee-field.rs new file mode 100644 index 0000000000000..efb345fa9f3e5 --- /dev/null +++ b/src/test/codegen/async-fn-debug-awaitee-field.rs @@ -0,0 +1,23 @@ +// This test makes sure that the generator field capturing the awaitee in a `.await` expression +// is called "__awaitee" in debuginfo. This name must not be changed since debuggers and debugger +// extensions rely on the field having this name. + +// ignore-tidy-linelength +// compile-flags: -C debuginfo=2 --edition=2018 + +async fn foo() {} + +async fn async_fn_test() { + foo().await; +} + +// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", +// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum$", +// CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]], +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]], +// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture", +// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture >", + +fn main() { + let _fn = async_fn_test(); +} From 25eb06077997bca0b20f0ef7d828672a8140519e Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 30 Mar 2022 13:59:27 +0200 Subject: [PATCH 8/9] Don't stabilize ScopedJoinHandle::is_finished yet. --- library/std/src/thread/scoped.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index e3da79932c721..eeccc99b3a317 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -316,7 +316,6 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> { /// /// This function does not block. To block while waiting on the thread to finish, /// use [`join`][Self::join]. - #[stable(feature = "thread_is_running", since = "1.61.0")] pub fn is_finished(&self) -> bool { Arc::strong_count(&self.0.packet) == 1 } From a4a9fff5947df86292a6a5700782aeaaa7a645ca Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 30 Mar 2022 14:30:46 +0200 Subject: [PATCH 9/9] Fix last rustdoc-gui spurious test --- src/test/rustdoc-gui/search-result-display.goml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index 823ea67b1b055..ff792eced703a 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -2,8 +2,7 @@ goto: file://|DOC_PATH|/test_docs/index.html size: (900, 1000) write: (".search-input", "test") -// Waiting for the search results to appear... -wait-for: "#titles" +wait-for: "#search-settings" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... assert-css: (".search-results div.desc", {"width": "295px"})