Skip to content

Commit 93313d1

Browse files
committed
Auto merge of rust-lang#95393 - Dylan-DPC:rollup-l72f39g, r=Dylan-DPC
Rollup of 4 pull requests Successful merges: - rust-lang#88375 (Clarify that ManuallyDrop<T> has same layout as T) - rust-lang#93755 (Allow comparing `Vec`s with different allocators using `==`) - rust-lang#95016 (Docs: make Vec::from_raw_parts documentation less strict) - rust-lang#95098 (impl From<&[T; N]> and From<&mut [T; N]> for Vec<T>) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3badf5c + 8bfc03f commit 93313d1

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

library/alloc/src/vec/mod.rs

+49-3
Original file line numberDiff line numberDiff line change
@@ -479,20 +479,24 @@ impl<T> Vec<T> {
479479
///
480480
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
481481
/// (at least, it's highly likely to be incorrect if it wasn't).
482-
/// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
482+
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
483483
/// (`T` having a less strict alignment is not sufficient, the alignment really
484484
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
485485
/// allocated and deallocated with the same layout.)
486+
/// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
487+
/// to be the same size as the pointer was allocated with. (Because similar to
488+
/// alignment, [`dealloc`] must be called with the same layout `size`.)
486489
/// * `length` needs to be less than or equal to `capacity`.
487-
/// * `capacity` needs to be the capacity that the pointer was allocated with.
488490
///
489491
/// Violating these may cause problems like corrupting the allocator's
490492
/// internal data structures. For example it is **not** safe
491493
/// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
492494
/// It's also not safe to build one from a `Vec<u16>` and its length, because
493495
/// the allocator cares about the alignment, and these two types have different
494496
/// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
495-
/// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
497+
/// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid
498+
/// these issues, it is often preferable to do casting/transmuting using
499+
/// [`slice::from_raw_parts`] instead.
496500
///
497501
/// The ownership of `ptr` is effectively transferred to the
498502
/// `Vec<T>` which may then deallocate, reallocate or change the
@@ -2929,6 +2933,48 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
29292933
}
29302934
}
29312935

2936+
#[cfg(not(no_global_oom_handling))]
2937+
#[stable(feature = "vec_from_array_ref", since = "1.61.0")]
2938+
impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> {
2939+
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
2940+
///
2941+
/// # Examples
2942+
///
2943+
/// ```
2944+
/// assert_eq!(Vec::from(b"raw"), vec![b'r', b'a', b'w']);
2945+
/// ```
2946+
#[cfg(not(test))]
2947+
fn from(s: &[T; N]) -> Vec<T> {
2948+
s.to_vec()
2949+
}
2950+
2951+
#[cfg(test)]
2952+
fn from(s: &[T; N]) -> Vec<T> {
2953+
crate::slice::to_vec(s, Global)
2954+
}
2955+
}
2956+
2957+
#[cfg(not(no_global_oom_handling))]
2958+
#[stable(feature = "vec_from_array_ref", since = "1.61.0")]
2959+
impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> {
2960+
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
2961+
///
2962+
/// # Examples
2963+
///
2964+
/// ```
2965+
/// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
2966+
/// ```
2967+
#[cfg(not(test))]
2968+
fn from(s: &mut [T; N]) -> Vec<T> {
2969+
s.to_vec()
2970+
}
2971+
2972+
#[cfg(test)]
2973+
fn from(s: &mut [T; N]) -> Vec<T> {
2974+
crate::slice::to_vec(s, Global)
2975+
}
2976+
}
2977+
29322978
#[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
29332979
impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
29342980
where

library/alloc/src/vec/partial_eq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ macro_rules! __impl_slice_eq1 {
2020
}
2121
}
2222

23-
__impl_slice_eq1! { [A: Allocator] Vec<T, A>, Vec<U, A>, #[stable(feature = "rust1", since = "1.0.0")] }
23+
__impl_slice_eq1! { [A1: Allocator, A2: Allocator] Vec<T, A1>, Vec<U, A2>, #[stable(feature = "rust1", since = "1.0.0")] }
2424
__impl_slice_eq1! { [A: Allocator] Vec<T, A>, &[U], #[stable(feature = "rust1", since = "1.0.0")] }
2525
__impl_slice_eq1! { [A: Allocator] Vec<T, A>, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] }
2626
__impl_slice_eq1! { [A: Allocator] &[T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }

library/core/src/mem/manually_drop.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use crate::ptr;
44
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
55
/// This wrapper is 0-cost.
66
///
7-
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
8-
/// As a consequence, it has *no effect* on the assumptions that the compiler makes
9-
/// about its contents. For example, initializing a `ManuallyDrop<&mut T>`
10-
/// with [`mem::zeroed`] is undefined behavior.
11-
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
7+
/// `ManuallyDrop<T>` is guaranteed to have the same layout as `T`, and is subject
8+
/// to the same layout optimizations as `T`. As a consequence, it has *no effect*
9+
/// on the assumptions that the compiler makes about its contents. For example,
10+
/// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined
11+
/// behavior. If you need to handle uninitialized data, use [`MaybeUninit<T>`]
12+
/// instead.
1213
///
1314
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
1415
/// This means that a `ManuallyDrop<T>` whose content has been dropped must not

0 commit comments

Comments
 (0)