diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index f5a3d0cd4af87..159f45ffce1a0 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -65,7 +65,7 @@ use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{self, Index, IndexMut, RangeBounds}; use core::ptr::{self, NonNull}; @@ -1525,6 +1525,47 @@ impl Vec { { Box::leak(vec.into_boxed_slice()) } + + /// Returns the remaining spare capacity of the vector as a slice of + /// `MaybeUninit`. + /// + /// The returned slice can be used to fill the vector with data (e.g. by + /// reading from a file) before marking the data as initialized using the + /// [`set_len`] method. + /// + /// [`set_len`]: #method.set_len + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_spare_capacity, maybe_uninit_extra)] + /// + /// // Allocate vector big enough for 10 elements. + /// let mut v = Vec::with_capacity(10); + /// + /// // Fill in the first 3 elements. + /// let uninit = v.spare_capacity_mut(); + /// uninit[0].write(0); + /// uninit[1].write(1); + /// uninit[2].write(2); + /// + /// // Mark the first 3 elements of the vector as being initialized. + /// unsafe { + /// v.set_len(3); + /// } + /// + /// assert_eq!(&v, &[0, 1, 2]); + /// ``` + #[unstable(feature = "vec_spare_capacity", issue = "75017")] + #[inline] + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len) as *mut MaybeUninit, + self.buf.capacity() - self.len, + ) + } + } } impl Vec { diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 7732525a0fc28..cf721b01ce3c6 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -336,8 +336,8 @@ impl MaybeUninit { /// assert_eq!(x, (0, false)); /// ``` /// - /// *Incorrect* usage of this function: initializing a struct with zero, where some fields - /// cannot hold 0 as a valid value. + /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` + /// when `0` is not a valid bit-pattern for the type: /// /// ```rust,no_run /// use std::mem::MaybeUninit; diff --git a/src/librustc_error_codes/error_codes/E0728.md b/src/librustc_error_codes/error_codes/E0728.md index 1afbedab0cabb..f4968a4f00e38 100644 --- a/src/librustc_error_codes/error_codes/E0728.md +++ b/src/librustc_error_codes/error_codes/E0728.md @@ -1,6 +1,6 @@ -[`await`] has been used outside [`async`] function or block. +[`await`] has been used outside [`async`] function or [`async`] block. -Erroneous code examples: +Erroneous code example: ```edition2018,compile_fail,E0728 # use std::pin::Pin; @@ -33,7 +33,7 @@ fn foo() { [`await`] is used to suspend the current computation until the given future is ready to produce a value. So it is legal only within -an [`async`] context, like an `async fn` or an `async` block. +an [`async`] context, like an `async` function or an `async` block. ```edition2018 # use std::pin::Pin; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9c5fb4ce73450..fc00050f40518 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -637,7 +637,7 @@ impl EmbargoVisitor<'tcx> { &mut self, segments: &[hir::PathSegment<'_>], ) { - if let Some([module, segment]) = segments.rchunks_exact(2).next() { + if let [.., module, segment] = segments { if let Some(item) = module .res .and_then(|res| res.mod_def_id()) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index b170b4131464a..9c44d27447db8 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -480,6 +480,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .clean(self.cx) .params; + debug!( + "param_env_to_generics({:?}): generic_params={:?}", + param_env_def_id, generic_params + ); + let mut has_sized = FxHashSet::default(); let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cc3a60c596ae7..5b048372624a4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -716,11 +716,11 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens + let stripped_params = gens .params .iter() .filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => None, + ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), ty::GenericParamDefKind::Type { synthetic, .. } => { if param.name == kw::SelfUpper { assert_eq!(param.index, 0); @@ -732,7 +732,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx } Some(param.clean(cx)) } - ty::GenericParamDefKind::Const { .. } => None, + ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)), }) .collect::>(); @@ -844,8 +844,10 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx // Run through the type parameters again and insert a ?Sized // unbound for any we didn't find to be Sized. - for tp in &stripped_typarams { - if !sized_params.contains(&tp.name) { + for tp in &stripped_params { + if matches!(tp.kind, types::GenericParamDefKind::Type { .. }) + && !sized_params.contains(&tp.name) + { where_predicates.push(WP::BoundPredicate { ty: Type::Generic(tp.name.clone()), bounds: vec![GenericBound::maybe_sized(cx)], @@ -858,16 +860,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx // and instead see `where T: Foo + Bar + Sized + 'a` Generics { - params: gens - .params - .iter() - .flat_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), - ty::GenericParamDefKind::Type { .. } => None, - ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)), - }) - .chain(simplify::ty_params(stripped_typarams).into_iter()) - .collect(), + params: stripped_params, where_predicates: simplify::where_clauses(cx, where_predicates), } } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 0f995a60c22fd..990189f6ea04d 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -12,7 +12,6 @@ //! bounds by special casing scenarios such as these. Fun! use std::collections::BTreeMap; -use std::mem; use rustc_hir::def_id::DefId; use rustc_middle::ty; @@ -118,18 +117,6 @@ pub fn merge_bounds( }) } -pub fn ty_params(mut params: Vec) -> Vec { - for param in &mut params { - match param.kind { - clean::GenericParamDefKind::Type { ref mut bounds, .. } => { - *bounds = mem::take(bounds); - } - _ => panic!("expected only type parameters"), - } - } - params -} - fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool { if child == trait_ { return true; diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index 7361b22b74798..03f5bb2ca4374 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -11,8 +11,8 @@ pub enum Order { } // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet' -// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl Send for VSet' -// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl Sync for VSet' +// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl Send for VSet' +// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl Sync for VSet' pub struct VSet { inner: Vec, }