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 5cf362bfa7e98..02d24344e0ac8 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, @@ -1024,7 +1025,6 @@ symbols! { pattern_parentheses, phantom_data, pin, - pinned, platform_intrinsics, plugin, plugin_registrar, diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index cc6dfb0e33017..03c532bb69769 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::take(&mut 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 1ca5ee5537582..9773ec023377f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2579,7 +2579,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 diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ca0fcc855c7b8..19e39ebf910b5 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,31 @@ 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); + 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] fn test_from_iter_specialization() { let src: Vec = vec![0usize; 1]; 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..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]. - #[unstable(feature = "thread_is_running", issue = "90470")] pub fn is_finished(&self) -> bool { Arc::strong_count(&self.0.packet) == 1 } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 8f076ad914d9a..570a61742bcf3 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}; @@ -904,7 +905,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. 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(); +} 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"})