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_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index feef7295254a9..da52388654a87 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -400,6 +400,8 @@ declare_features! ( (active, generic_arg_infer, "1.55.0", Some(85077), None), /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). (active, generic_associated_types, "1.23.0", Some(44265), None), + /// An extension to the `generic_associated_types` feature, allowing incomplete features. + (incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None), /// Allows non-trivial generic constants which have to have wfness manually propagated to callers (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 388109e6512dd..075928c889d83 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1379,3 +1379,50 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { ControlFlow::CONTINUE } } + +/// Finds the max universe present +pub struct MaxUniverse { + max_universe: ty::UniverseIndex, +} + +impl MaxUniverse { + pub fn new() -> Self { + MaxUniverse { max_universe: ty::UniverseIndex::ROOT } + } + + pub fn max_universe(self) -> ty::UniverseIndex { + self.max_universe + } +} + +impl<'tcx> TypeVisitor<'tcx> for MaxUniverse { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if let ty::Placeholder(placeholder) = t.kind() { + self.max_universe = ty::UniverseIndex::from_u32( + self.max_universe.as_u32().max(placeholder.universe.as_u32()), + ); + } + + t.super_visit_with(self) + } + + fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow { + if let ty::ConstKind::Placeholder(placeholder) = c.val() { + self.max_universe = ty::UniverseIndex::from_u32( + self.max_universe.as_u32().max(placeholder.universe.as_u32()), + ); + } + + c.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + if let ty::RePlaceholder(placeholder) = *r { + self.max_universe = ty::UniverseIndex::from_u32( + self.max_universe.as_u32().max(placeholder.universe.as_u32()), + ); + } + + ControlFlow::CONTINUE + } +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 84dbad846dd29..0bca0a99e157f 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, @@ -722,6 +723,7 @@ symbols! { generators, generic_arg_infer, generic_associated_types, + generic_associated_types_extended, generic_const_exprs, generic_param_attrs, get_context, @@ -1018,7 +1020,6 @@ symbols! { pattern_parentheses, phantom_data, pin, - pinned, platform_intrinsics, plugin, plugin_registrar, diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 6082cdb78e478..52fce7c055309 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -279,7 +279,6 @@ impl ToJson for Endian { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct Size { - // The top 3 bits are ALWAYS zero. raw: u64, } @@ -287,22 +286,9 @@ impl Size { pub const ZERO: Size = Size { raw: 0 }; /// Rounds `bits` up to the next-higher byte boundary, if `bits` is - /// is not aligned. + /// not a multiple of 8. pub fn from_bits(bits: impl TryInto) -> Size { let bits = bits.try_into().ok().unwrap(); - - #[cold] - fn overflow(bits: u64) -> ! { - panic!("Size::from_bits({}) has overflowed", bits); - } - - // This is the largest value of `bits` that does not cause overflow - // during rounding, and guarantees that the resulting number of bytes - // cannot cause overflow when multiplied by 8. - if bits > 0xffff_ffff_ffff_fff8 { - overflow(bits); - } - // Avoid potential overflow from `bits + 7`. Size { raw: bits / 8 + ((bits % 8) + 7) / 8 } } @@ -325,7 +311,12 @@ impl Size { #[inline] pub fn bits(self) -> u64 { - self.raw << 3 + #[cold] + fn overflow(bytes: u64) -> ! { + panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes) + } + + self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes())) } #[inline] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 36eddf7784b32..d95512bb88f36 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -5,6 +5,7 @@ use super::*; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; +use crate::traits::project::ProjectAndUnifyResult; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{Region, RegionVid, Term}; @@ -751,7 +752,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { debug!("Projecting and unifying projection predicate {:?}", predicate); match project::poly_project_and_unify_type(select, &obligation.with(p)) { - Err(e) => { + ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { debug!( "evaluate_nested_obligations: Unable to unify predicate \ '{:?}' '{:?}', bailing out", @@ -759,11 +760,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { ); return false; } - Ok(Err(project::InProgress)) => { + ProjectAndUnifyResult::Recursive => { debug!("evaluate_nested_obligations: recursive projection predicate"); return false; } - Ok(Ok(Some(v))) => { + ProjectAndUnifyResult::Holds(v) => { // We only care about sub-obligations // when we started out trying to unify // some inference variables. See the comment above @@ -782,7 +783,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } } } - Ok(Ok(None)) => { + ProjectAndUnifyResult::FailedNormalization => { // It's ok not to make progress when have no inference variables - // in that case, we were only performing unification to check if an // error occurred (which would indicate that it's impossible for our diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 1b8628344671d..d0b8b0281c5bf 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable}; use std::marker::PhantomData; use super::const_evaluatable; -use super::project; +use super::project::{self, ProjectAndUnifyResult}; use super::select::SelectionContext; use super::wf; use super::CodeAmbiguity; @@ -753,8 +753,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } match project::poly_project_and_unify_type(self.selcx, &project_obligation) { - Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)), - Ok(Ok(None)) => { + ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)), + ProjectAndUnifyResult::FailedNormalization => { stalled_on.clear(); stalled_on.extend(substs_infer_vars( self.selcx, @@ -763,10 +763,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ProcessResult::Unchanged } // Let the caller handle the recursion - Ok(Err(project::InProgress)) => ProcessResult::Changed(mk_pending(vec![ + ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![ project_obligation.with(project_obligation.predicate.to_predicate(tcx)), ])), - Err(e) => ProcessResult::Error(CodeProjectionError(e)), + ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { + ProcessResult::Error(CodeProjectionError(e)) + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d4ec677a0b1c5..2251f992e4dc6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,7 +28,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::traits::select::OverflowError; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; +use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -144,6 +144,18 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { } } +/// Takes the place of a +/// Result< +/// Result>>, InProgress>, +/// MismatchedProjectionTypes<'tcx>, +/// > +pub(super) enum ProjectAndUnifyResult<'tcx> { + Holds(Vec>), + FailedNormalization, + Recursive, + MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>), +} + /// Evaluates constraints of the form: /// /// for<...> ::U == V @@ -167,19 +179,47 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, -) -> Result< - Result>>, InProgress>, - MismatchedProjectionTypes<'tcx>, -> { +) -> ProjectAndUnifyResult<'tcx> { let infcx = selcx.infcx(); - infcx.commit_if_ok(|_snapshot| { + let r = infcx.commit_if_ok(|_snapshot| { + let old_universe = infcx.universe(); let placeholder_predicate = infcx.replace_bound_vars_with_placeholders(obligation.predicate); + let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(placeholder_predicate); - let result = project_and_unify_type(selcx, &placeholder_obligation)?; - Ok(result) - }) + match project_and_unify_type(selcx, &placeholder_obligation) { + ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), + ProjectAndUnifyResult::Holds(obligations) + if old_universe != new_universe + && selcx.tcx().features().generic_associated_types_extended => + { + // If the `generic_associated_types_extended` feature is active, then we ignore any + // obligations references lifetimes from any universe greater than or equal to the + // universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`, + // which isn't quite what we want. Ideally, we want either an implied + // `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we + // substitute concrete regions. There is design work to be done here; until then, + // however, this allows experimenting potential GAT features without running into + // well-formedness issues. + let new_obligations = obligations + .into_iter() + .filter(|obligation| { + let mut visitor = MaxUniverse::new(); + obligation.predicate.visit_with(&mut visitor); + visitor.max_universe() < new_universe + }) + .collect(); + Ok(ProjectAndUnifyResult::Holds(new_obligations)) + } + other => Ok(other), + } + }); + + match r { + Ok(inner) => inner, + Err(err) => ProjectAndUnifyResult::MismatchedProjectionTypes(err), + } } /// Evaluates constraints of the form: @@ -189,15 +229,11 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( /// If successful, this may result in additional obligations. /// /// See [poly_project_and_unify_type] for an explanation of the return value. +#[tracing::instrument(level = "debug", skip(selcx))] fn project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, -) -> Result< - Result>>, InProgress>, - MismatchedProjectionTypes<'tcx>, -> { - debug!(?obligation, "project_and_unify_type"); - +) -> ProjectAndUnifyResult<'tcx> { let mut obligations = vec![]; let infcx = selcx.infcx(); @@ -210,8 +246,8 @@ fn project_and_unify_type<'cx, 'tcx>( &mut obligations, ) { Ok(Some(n)) => n, - Ok(None) => return Ok(Ok(None)), - Err(InProgress) => return Ok(Err(InProgress)), + Ok(None) => return ProjectAndUnifyResult::FailedNormalization, + Err(InProgress) => return ProjectAndUnifyResult::Recursive, }; debug!(?normalized, ?obligations, "project_and_unify_type result"); let actual = obligation.predicate.term; @@ -231,11 +267,11 @@ fn project_and_unify_type<'cx, 'tcx>( match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); - Ok(Ok(Some(obligations))) + ProjectAndUnifyResult::Holds(obligations) } Err(err) => { - debug!("project_and_unify_type: equating types encountered error {:?}", err); - Err(MismatchedProjectionTypes { err }) + debug!("equating types encountered error {:?}", err); + ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err }) } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 42f17721f9b54..4f033d45c1f32 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -21,6 +21,7 @@ use super::{ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -525,7 +526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let data = bound_predicate.rebind(data); let project_obligation = obligation.with(data); match project::poly_project_and_unify_type(self, &project_obligation) { - Ok(Ok(Some(mut subobligations))) => { + ProjectAndUnifyResult::Holds(mut subobligations) => { 'compute_res: { // If we've previously marked this projection as 'complete', then // use the final cached result (either `EvaluatedToOk` or @@ -573,9 +574,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { res } } - Ok(Ok(None)) => Ok(EvaluatedToAmbig), - Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur), - Err(_) => Ok(EvaluatedToErr), + ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig), + ProjectAndUnifyResult::Recursive => Ok(EvaluatedToRecur), + ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr), } } 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/lib.rs b/library/std/src/lib.rs index 133ced5f26cfb..d4420cc42304a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -218,111 +218,120 @@ feature(slice_index_methods, coerce_unsized, sgx_platform) )] #![deny(rustc::existing_doc_keyword)] -// std is implemented with unstable features, many of which are internal -// compiler details that will never be stable -// NB: the following list is sorted to minimize merge conflicts. +// +// Language features: #![feature(alloc_error_handler)] -#![feature(alloc_layout_extra)] -#![feature(allocator_api)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(array_error_internals)] -#![feature(assert_matches)] -#![feature(associated_type_bounds)] -#![feature(async_iterator)] -#![feature(atomic_mut_ptr)] -#![feature(bench_black_box)] #![feature(box_syntax)] #![feature(c_unwind)] -#![feature(c_variadic)] -#![feature(cfg_accessible)] -#![feature(cfg_eval)] #![feature(cfg_target_thread_local)] -#![feature(char_error_internals)] -#![feature(char_internals)] -#![feature(concat_bytes)] #![feature(concat_idents)] #![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] #![cfg_attr(bootstrap, feature(const_fn_trait_bound))] -#![feature(const_format_args)] -#![feature(const_io_structs)] -#![feature(const_ip)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(const_mut_refs)] -#![feature(const_option)] -#![feature(const_socketaddr)] #![feature(const_trait_impl)] -#![feature(c_size_t)] -#![feature(core_ffi_c)] -#![feature(core_intrinsics)] -#![feature(core_panic)] -#![feature(custom_test_frameworks)] #![feature(decl_macro)] +#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] -#![feature(rustdoc_internals)] -#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))] #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(duration_checked_float)] -#![feature(duration_constants)] -#![feature(edition_panic)] -#![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] -#![feature(extend_one)] -#![feature(float_minimum_maximum)] -#![feature(format_args_nl)] -#![feature(strict_provenance)] -#![feature(get_mut_unchecked)] -#![feature(hashmap_internals)] -#![feature(int_error_internals)] #![feature(intra_doc_pointers)] #![feature(lang_items)] #![feature(linkage)] -#![feature(log_syntax)] -#![feature(map_try_insert)] -#![feature(maybe_uninit_slice)] -#![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] -#![feature(mixed_integer_ops)] #![feature(must_not_suspend)] #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] -#![feature(new_uninit)] #![feature(nll)] +#![feature(platform_intrinsics)] +#![feature(prelude_import)] +#![feature(rustc_attrs)] +#![feature(rustdoc_internals)] +#![feature(staged_api)] +#![feature(thread_local)] +#![feature(try_blocks)] +// +// Library features (core): +#![feature(array_error_internals)] +#![feature(char_error_internals)] +#![feature(char_internals)] +#![feature(core_intrinsics)] +#![feature(duration_checked_float)] +#![feature(duration_constants)] +#![feature(exact_size_is_empty)] +#![feature(extend_one)] +#![feature(float_minimum_maximum)] +#![feature(hashmap_internals)] +#![feature(int_error_internals)] +#![feature(maybe_uninit_slice)] +#![feature(maybe_uninit_write_slice)] +#![feature(mixed_integer_ops)] #![feature(nonnull_slice_from_raw_parts)] -#![feature(once_cell)] +#![feature(panic_can_unwind)] #![feature(panic_info_message)] #![feature(panic_internals)] -#![feature(panic_can_unwind)] -#![feature(panic_unwind)] -#![feature(platform_intrinsics)] #![feature(portable_simd)] -#![feature(prelude_import)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] -#![feature(rustc_attrs)] -#![feature(saturating_int_impl)] #![feature(slice_internals)] #![feature(slice_ptr_get)] -#![feature(staged_api)] #![feature(std_internals)] -#![feature(stdsimd)] #![feature(str_internals)] -#![feature(test)] -#![feature(thread_local)] -#![feature(thread_local_internals)] -#![feature(toowned_clone_into)] +#![feature(strict_provenance)] #![feature(total_cmp)] -#![feature(trace_macros)] -#![feature(try_blocks)] +// +// Library features (alloc): +#![feature(alloc_layout_extra)] +#![feature(allocator_api)] +#![feature(get_mut_unchecked)] +#![feature(map_try_insert)] +#![feature(new_uninit)] +#![feature(toowned_clone_into)] #![feature(try_reserve_kind)] #![feature(vec_into_raw_parts)] -// NB: the above list is sorted to minimize merge conflicts. +// +// Library features (unwind): +#![feature(panic_unwind)] +// +// Only for re-exporting: +#![feature(assert_matches)] +#![feature(async_iterator)] +#![feature(c_size_t)] +#![feature(c_variadic)] +#![feature(cfg_accessible)] +#![feature(cfg_eval)] +#![feature(concat_bytes)] +#![feature(const_format_args)] +#![feature(core_ffi_c)] +#![feature(core_panic)] +#![feature(custom_test_frameworks)] +#![feature(edition_panic)] +#![feature(format_args_nl)] +#![feature(log_syntax)] +#![feature(once_cell)] +#![feature(saturating_int_impl)] +#![feature(stdsimd)] +#![feature(test)] +#![feature(trace_macros)] +// +// Only used in tests/benchmarks: +#![feature(bench_black_box)] +// +// Only for const-ness: +#![feature(const_io_structs)] +#![feature(const_ip)] +#![feature(const_ipv4)] +#![feature(const_ipv6)] +#![feature(const_option)] +#![feature(const_socketaddr)] +#![feature(thread_local_internals)] +// #![default_lib_allocator] // Explicitly import the prelude. The compiler uses this same unstable attribute 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/ui/feature-gates/feature-gate-generic_associated_types_extended.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.rs new file mode 100644 index 0000000000000..258b8cd35c777 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.rs @@ -0,0 +1,6 @@ +#![feature(generic_associated_types)] + +// This feature doesn't *currently* fire on any specific code; it's just a +// behavior change. Future changes might. +#[rustc_error] //~ the +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr new file mode 100644 index 0000000000000..6a5eba38cacc6 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable + --> $DIR/feature-gate-generic_associated_types_extended.rs:5:1 + | +LL | #[rustc_error] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr new file mode 100644 index 0000000000000..c5588b0912ba8 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -0,0 +1,26 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator.rs:14:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` + +error[E0311]: the parameter type `Self` may not live long enough + --> $DIR/lending_iterator.rs:35:9 + | +LL | >::from_iter(self) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Self: 'a`... + = note: ...so that the type `Self` will meet its required lifetime bounds... +note: ...that is required by this bound + --> $DIR/lending_iterator.rs:10:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator.rs b/src/test/ui/generic-associated-types/extended/lending_iterator.rs new file mode 100644 index 0000000000000..df11ab2124986 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator.rs @@ -0,0 +1,40 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait FromLendingIterator: Sized { + fn from_iter LendingIterator = A>>(iter: T) -> Self; +} + +impl FromLendingIterator for Vec { + fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + //[base]~^ impl has stricter + let mut v = vec![]; + while let Some(item) = iter.next() { + v.push(item); + } + v + } +} + +pub trait LendingIterator { + type Item<'z> + where + Self: 'z; + fn next(&mut self) -> Option>; + + fn collect>(self) -> B + where + Self: Sized, + Self: for<'q> LendingIterator = A>, + { + >::from_iter(self) + //[base]~^ the parameter type + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr new file mode 100644 index 0000000000000..6c2a624ca11d5 --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator_2.base.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator_2.rs:14:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs b/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs new file mode 100644 index 0000000000000..3c4a2184db90c --- /dev/null +++ b/src/test/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -0,0 +1,31 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait FromLendingIterator: Sized { + fn from_iter LendingIterator = A>>(iter: T) -> Self; +} + +impl FromLendingIterator for Vec { + fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + //[base]~^ impl has stricter + let mut v = vec![]; + while let Some(item) = iter.next() { + v.push(item); + } + v + } +} + +pub trait LendingIterator { + type Item<'a> + where + Self: 'a; + fn next(&mut self) -> Option>; +} + +fn main() {}