From 27a28c7c37cb2cd7f66e2934b6de7d13b488d208 Mon Sep 17 00:00:00 2001 From: tower120 Date: Wed, 28 Jan 2026 21:53:20 +0200 Subject: [PATCH 01/12] Vec::from_array now const --- src/len_type.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/vec/mod.rs | 26 ++++++++++++++++---------- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/len_type.rs b/src/len_type.rs index 0eb6ff6a56..58ee1b55ca 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -1,4 +1,5 @@ use core::{ + mem, fmt::{Debug, Display}, ops::{Add, AddAssign, Sub, SubAssign}, }; @@ -100,3 +101,40 @@ impl_lentype!( pub const fn check_capacity_fits() { assert!(LenT::MAX_USIZE >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity"); } + +#[inline] +pub(crate) const fn to_len_type(n: usize) -> L { + try_to_len_type(n).unwrap() +} + +#[inline] +pub(crate) const fn try_to_len_type(n: usize) -> Option { + if n > L::MAX_USIZE { + return None; + } + // The following "select" is safe, since we have fixed number of types + // implementing LenType - all with distinctive size "signature". + unsafe{ + // ALWAYS compiletime switch. + Some(match size_of::(){ + // transmute_copy, instead of transmute - because `L` + // is a "dependent type". + 8 => mem::transmute_copy(&(n as u64)), + 4 => mem::transmute_copy(&(n as u32)), + 2 => mem::transmute_copy(&(n as u16)), + 1 => mem::transmute_copy(&(n as u8)), + _ => unreachable!() + }) + } +} + +#[cfg(test)] +mod tests{ + use super::*; + + #[test] + fn test_len_cast(){ + const{ assert!(to_len_type::(15000) == 15000); } + } +} + diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 093bdb13d2..70e3279136 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -16,7 +16,7 @@ use core::{ use zeroize::Zeroize; use crate::{ - len_type::{check_capacity_fits, LenType}, + len_type::{check_capacity_fits, LenType, to_len_type}, CapacityError, }; @@ -355,7 +355,7 @@ impl Vec { /// /// If the length of the provided array is greater than the capacity of the /// vector a compile-time error will be produced. - pub fn from_array(src: [T; M]) -> Self { + pub const fn from_array(src: [T; M]) -> Self { const { assert!(N >= M); } @@ -363,25 +363,31 @@ impl Vec { // We've got to copy `src`, but we're functionally moving it. Don't run // any Drop code for T. let src = ManuallyDrop::new(src); + + let len: LenT = to_len_type(M); if N == M { + // TODO: Do we need this? Self { phantom: PhantomData, - len: LenT::from_usize(N), + len, // NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit; N] // have the same layout when N == M. buffer: unsafe { mem::transmute_copy(&src) }, } } else { let mut v = Self::new(); - - for (src_elem, dst_elem) in src.iter().zip(v.buffer.buffer.iter_mut()) { - // NOTE(unsafe) src element is not going to drop as src itself - // is wrapped in a ManuallyDrop. - dst_elem.write(unsafe { ptr::read(src_elem) }); + unsafe{ + // MaybeUninit::deref is non-const, so we just cast it through. + // Casting to internal value of MaybeUninit is safe since it is transparent. + let src_ptr: *const T = &src as *const _ as *const _; + + // Cast from [MaybeUninit] to [T] is safe since it is transparent. + let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); + + ptr::copy_nonoverlapping(src_ptr, dst_ptr, M); + v.len = len; } - - unsafe { v.set_len(M) }; v } } From bd67600f077641e91bbe069bae1d319eb2f43d7f Mon Sep 17 00:00:00 2001 From: tower120 Date: Wed, 28 Jan 2026 22:05:43 +0200 Subject: [PATCH 02/12] CI's clippy fix --- src/len_type.rs | 4 ++-- src/vec/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/len_type.rs b/src/len_type.rs index 58ee1b55ca..adb58dbff1 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -103,12 +103,12 @@ pub const fn check_capacity_fits() { } #[inline] -pub(crate) const fn to_len_type(n: usize) -> L { +pub const fn to_len_type(n: usize) -> L { try_to_len_type(n).unwrap() } #[inline] -pub(crate) const fn try_to_len_type(n: usize) -> Option { +pub const fn try_to_len_type(n: usize) -> Option { if n > L::MAX_USIZE { return None; } diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 70e3279136..920187b4d7 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -380,7 +380,7 @@ impl Vec { unsafe{ // MaybeUninit::deref is non-const, so we just cast it through. // Casting to internal value of MaybeUninit is safe since it is transparent. - let src_ptr: *const T = &src as *const _ as *const _; + let src_ptr: *const T = ptr::from_ref(&src).cast(); // Cast from [MaybeUninit] to [T] is safe since it is transparent. let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); From 785935952d658f678b86e98f3e3075f17888248c Mon Sep 17 00:00:00 2001 From: tower120 Date: Wed, 28 Jan 2026 22:10:30 +0200 Subject: [PATCH 03/12] changelog updated --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a282124f4..4d679f5b78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `from_bytes_truncating_at_nul` to `CString` - Added `CString::{into_bytes, into_bytes_with_nul, into_string}` - Added `pop_front_if` and `pop_back_if` to `Deque` +- Made `Vec::from_array` const. ## [v0.9.2] 2025-11-12 From 889592b310e3854882efe7de56029541fecf1d6b Mon Sep 17 00:00:00 2001 From: tower120 Date: Wed, 28 Jan 2026 22:15:46 +0200 Subject: [PATCH 04/12] file formatting --- .gitignore | 3 +++ src/vec/mod.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e64a511ae8..4f6992fc3e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ .#* Cargo.lock target/ + +# IDE files +.idea \ No newline at end of file diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 920187b4d7..63c4da2f45 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -16,7 +16,7 @@ use core::{ use zeroize::Zeroize; use crate::{ - len_type::{check_capacity_fits, LenType, to_len_type}, + len_type::{check_capacity_fits, to_len_type, LenType}, CapacityError, }; @@ -363,7 +363,7 @@ impl Vec { // We've got to copy `src`, but we're functionally moving it. Don't run // any Drop code for T. let src = ManuallyDrop::new(src); - + let len: LenT = to_len_type(M); if N == M { @@ -377,14 +377,14 @@ impl Vec { } } else { let mut v = Self::new(); - unsafe{ + unsafe { // MaybeUninit::deref is non-const, so we just cast it through. // Casting to internal value of MaybeUninit is safe since it is transparent. let src_ptr: *const T = ptr::from_ref(&src).cast(); - + // Cast from [MaybeUninit] to [T] is safe since it is transparent. - let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); - + let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); + ptr::copy_nonoverlapping(src_ptr, dst_ptr, M); v.len = len; } From 33485307128e37df1c7594cb8fa09480d3ede2d8 Mon Sep 17 00:00:00 2001 From: tower120 Date: Wed, 28 Jan 2026 22:17:23 +0200 Subject: [PATCH 05/12] CI's style complaince --- src/len_type.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/len_type.rs b/src/len_type.rs index adb58dbff1..7f842d60f1 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -1,6 +1,6 @@ use core::{ - mem, fmt::{Debug, Display}, + mem, ops::{Add, AddAssign, Sub, SubAssign}, }; @@ -114,27 +114,28 @@ pub const fn try_to_len_type(n: usize) -> Option { } // The following "select" is safe, since we have fixed number of types // implementing LenType - all with distinctive size "signature". - unsafe{ + unsafe { // ALWAYS compiletime switch. - Some(match size_of::(){ - // transmute_copy, instead of transmute - because `L` - // is a "dependent type". + Some(match size_of::() { + // transmute_copy, instead of transmute - because `L` + // is a "dependent type". 8 => mem::transmute_copy(&(n as u64)), 4 => mem::transmute_copy(&(n as u32)), 2 => mem::transmute_copy(&(n as u16)), 1 => mem::transmute_copy(&(n as u8)), - _ => unreachable!() + _ => unreachable!(), }) } } #[cfg(test)] -mod tests{ +mod tests { use super::*; #[test] - fn test_len_cast(){ - const{ assert!(to_len_type::(15000) == 15000); } + fn test_len_cast() { + const { + assert!(to_len_type::(15000) == 15000); + } } } - From b9558f0f27d061c9e0e3229311fa328f2af7b612 Mon Sep 17 00:00:00 2001 From: tower120 Date: Thu, 29 Jan 2026 02:51:51 +0200 Subject: [PATCH 06/12] limit unsafe scope --- src/vec/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 63c4da2f45..d261b2b29d 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -377,17 +377,17 @@ impl Vec { } } else { let mut v = Self::new(); - unsafe { - // MaybeUninit::deref is non-const, so we just cast it through. - // Casting to internal value of MaybeUninit is safe since it is transparent. - let src_ptr: *const T = ptr::from_ref(&src).cast(); - // Cast from [MaybeUninit] to [T] is safe since it is transparent. - let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); + // MaybeUninit::deref is non-const, so we just cast it through. + // Casting to internal value of MaybeUninit is safe since it is transparent. + let src_ptr: *const T = ptr::from_ref(&src).cast(); + + // Cast from [MaybeUninit] to [T] is safe since it is transparent. + let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); + + unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; + v.len = len; - ptr::copy_nonoverlapping(src_ptr, dst_ptr, M); - v.len = len; - } v } } From b1a09fcb383a87ccedeaf4ef860e2bbc54b12b34 Mon Sep 17 00:00:00 2001 From: tower120 Date: Thu, 29 Jan 2026 21:18:18 +0200 Subject: [PATCH 07/12] Removed unnecessary optimization branch --- src/vec/mod.rs | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/vec/mod.rs b/src/vec/mod.rs index d261b2b29d..852f9418b3 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -6,7 +6,7 @@ use core::{ fmt, hash, iter::FusedIterator, marker::PhantomData, - mem::{self, ManuallyDrop, MaybeUninit}, + mem::{ManuallyDrop, MaybeUninit}, ops::{self, Range, RangeBounds}, ptr::{self, NonNull}, slice, @@ -365,31 +365,21 @@ impl Vec { let src = ManuallyDrop::new(src); let len: LenT = to_len_type(M); + + let mut v = Self::new(); - if N == M { - // TODO: Do we need this? - Self { - phantom: PhantomData, - len, - // NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit; N] - // have the same layout when N == M. - buffer: unsafe { mem::transmute_copy(&src) }, - } - } else { - let mut v = Self::new(); - - // MaybeUninit::deref is non-const, so we just cast it through. - // Casting to internal value of MaybeUninit is safe since it is transparent. - let src_ptr: *const T = ptr::from_ref(&src).cast(); + // MaybeUninit::deref is non-const, so we just cast it through. + // Casting to internal value of MaybeUninit is safe since it is transparent. + let src_ptr: *const T = ptr::from_ref(&src).cast(); - // Cast from [MaybeUninit] to [T] is safe since it is transparent. - let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); + // Cast from [MaybeUninit] to [T] is safe since it is transparent. + let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); - unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; - v.len = len; + // Move/copy data from input array to output Self buffer. + unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; + v.len = len; - v - } + v } /// Returns the contents of the vector as an array of length `M` if the length From 95d764ec41b601a43ef230e453d81b7076f52789 Mon Sep 17 00:00:00 2001 From: tower120 Date: Thu, 29 Jan 2026 22:11:21 +0200 Subject: [PATCH 08/12] to_len_type remade with enum technique. --- src/len_type.rs | 70 ++++++++++++++++++++++++++++++++++++++----------- src/vec/mod.rs | 2 +- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/len_type.rs b/src/len_type.rs index 7f842d60f1..195475fb13 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -4,6 +4,14 @@ use core::{ ops::{Add, AddAssign, Sub, SubAssign}, }; +#[allow(non_camel_case_types)] +pub enum TypeEnum{ + u8, + u16, + u32, + usize +} + #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -28,6 +36,8 @@ pub trait Sealed: const MAX: Self; /// The maximum value of this type, as a `usize`. const MAX_USIZE: usize; + /// This type as an enum. + const TYPE: TypeEnum; /// The one value of the integer type. /// @@ -59,12 +69,13 @@ pub trait Sealed: } macro_rules! impl_lentype { - ($($(#[$meta:meta])* $LenT:ty),*) => {$( + ($($(#[$meta:meta])* $LenT:ident),*) => {$( $(#[$meta])* impl Sealed for $LenT { const ZERO: Self = 0; const MAX: Self = Self::MAX; const MAX_USIZE: usize = Self::MAX as _; + const TYPE: TypeEnum = TypeEnum::$LenT; fn one() -> Self { 1 @@ -102,30 +113,41 @@ pub const fn check_capacity_fits() { assert!(LenT::MAX_USIZE >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity"); } +/// Const cast from `usize` to [LenType] with `as`. +#[inline] +pub const fn as_len_type(n: usize) -> L { + unsafe { + // ALWAYS compiletime switch. + match L::TYPE{ + // transmute_copy, instead of transmute - because `L` + // is a "dependent type". + TypeEnum::u8 => mem::transmute_copy(&(n as u8)), + TypeEnum::u16 => mem::transmute_copy(&(n as u16)), + TypeEnum::u32 => mem::transmute_copy(&(n as u32)), + TypeEnum::usize => mem::transmute_copy(&n), + } + } +} + +/// Checked cast to [LenType]. +/// +/// # Panic +/// +/// Panics if `n` is outside of `L` range. #[inline] pub const fn to_len_type(n: usize) -> L { try_to_len_type(n).unwrap() } +/// Checked cast to [LenType]. +/// +/// Returns `None` if `n` is outside of `L` range. #[inline] pub const fn try_to_len_type(n: usize) -> Option { if n > L::MAX_USIZE { return None; } - // The following "select" is safe, since we have fixed number of types - // implementing LenType - all with distinctive size "signature". - unsafe { - // ALWAYS compiletime switch. - Some(match size_of::() { - // transmute_copy, instead of transmute - because `L` - // is a "dependent type". - 8 => mem::transmute_copy(&(n as u64)), - 4 => mem::transmute_copy(&(n as u32)), - 2 => mem::transmute_copy(&(n as u16)), - 1 => mem::transmute_copy(&(n as u8)), - _ => unreachable!(), - }) - } + Some(as_len_type(n)) } #[cfg(test)] @@ -134,8 +156,24 @@ mod tests { #[test] fn test_len_cast() { + // 1. Check constness const { - assert!(to_len_type::(15000) == 15000); + assert!(to_len_type::(150) == 150); + assert!(to_len_type::(15_000) == 15_000); + assert!(to_len_type::(1_500_000) == 1_500_000); + assert!(to_len_type::(usize::MAX) == usize::MAX); } + // 2. Check correctness + fn check(){ + const COUNT: usize = 1000; + for i in 0..COUNT { + let n = i * (T::MAX_USIZE/COUNT); + assert_eq!(to_len_type::(n).into_usize(), n); + } + } + check::(); + check::(); + check::(); + check::(); } } diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 852f9418b3..0d66899002 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -375,7 +375,7 @@ impl Vec { // Cast from [MaybeUninit] to [T] is safe since it is transparent. let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); - // Move/copy data from input array to output Self buffer. + // NOTE(unsafe): Move/copy data from input array to output Self buffer. unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; v.len = len; From 352b4150ca235a054c7bdbac2890811e769f4fb6 Mon Sep 17 00:00:00 2001 From: tower120 Date: Thu, 29 Jan 2026 22:21:26 +0200 Subject: [PATCH 09/12] doc fixes --- src/len_type.rs | 28 ++++++++++++++-------------- src/vec/mod.rs | 6 ++++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/len_type.rs b/src/len_type.rs index 195475fb13..30294660ed 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -5,11 +5,11 @@ use core::{ }; #[allow(non_camel_case_types)] -pub enum TypeEnum{ +pub enum TypeEnum { u8, u16, u32, - usize + usize, } #[cfg(feature = "zeroize")] @@ -36,7 +36,7 @@ pub trait Sealed: const MAX: Self; /// The maximum value of this type, as a `usize`. const MAX_USIZE: usize; - /// This type as an enum. + /// This type as an enum. const TYPE: TypeEnum; /// The one value of the integer type. @@ -113,12 +113,12 @@ pub const fn check_capacity_fits() { assert!(LenT::MAX_USIZE >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity"); } -/// Const cast from `usize` to [LenType] with `as`. +/// Const cast from [`usize`] to [`LenType`] with `as`. #[inline] pub const fn as_len_type(n: usize) -> L { unsafe { // ALWAYS compiletime switch. - match L::TYPE{ + match L::TYPE { // transmute_copy, instead of transmute - because `L` // is a "dependent type". TypeEnum::u8 => mem::transmute_copy(&(n as u8)), @@ -129,18 +129,18 @@ pub const fn as_len_type(n: usize) -> L { } } -/// Checked cast to [LenType]. -/// +/// Checked cast to [`LenType`]. +/// /// # Panic -/// +/// /// Panics if `n` is outside of `L` range. #[inline] pub const fn to_len_type(n: usize) -> L { try_to_len_type(n).unwrap() } -/// Checked cast to [LenType]. -/// +/// Checked cast to [`LenType`]. +/// /// Returns `None` if `n` is outside of `L` range. #[inline] pub const fn try_to_len_type(n: usize) -> Option { @@ -164,13 +164,13 @@ mod tests { assert!(to_len_type::(usize::MAX) == usize::MAX); } // 2. Check correctness - fn check(){ + fn check() { const COUNT: usize = 1000; for i in 0..COUNT { - let n = i * (T::MAX_USIZE/COUNT); - assert_eq!(to_len_type::(n).into_usize(), n); + let n = i * (T::MAX_USIZE / COUNT); + assert_eq!(to_len_type::(n).into_usize(), n); } - } + } check::(); check::(); check::(); diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 0d66899002..ed3003a946 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -365,7 +365,7 @@ impl Vec { let src = ManuallyDrop::new(src); let len: LenT = to_len_type(M); - + let mut v = Self::new(); // MaybeUninit::deref is non-const, so we just cast it through. @@ -375,7 +375,7 @@ impl Vec { // Cast from [MaybeUninit] to [T] is safe since it is transparent. let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); - // NOTE(unsafe): Move/copy data from input array to output Self buffer. + // NOTE(unsafe): Move/copy data from input array to output Self buffer. unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; v.len = len; @@ -462,6 +462,8 @@ impl + ?Sized> VecInner { /// [`mem::forget`], for example), the vector may have lost and leaked /// elements arbitrarily, including elements outside the range. /// + /// [`mem::forget`]: core::mem::forget + /// /// # Examples /// /// ``` From 9b0089222a950d43da5f037c23363f728155f1d5 Mon Sep 17 00:00:00 2001 From: tower120 Date: Fri, 30 Jan 2026 01:34:32 +0200 Subject: [PATCH 10/12] small test fix --- src/len_type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/len_type.rs b/src/len_type.rs index 30294660ed..6c92df612f 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -165,7 +165,7 @@ mod tests { } // 2. Check correctness fn check() { - const COUNT: usize = 1000; + const COUNT: usize = 100; for i in 0..COUNT { let n = i * (T::MAX_USIZE / COUNT); assert_eq!(to_len_type::(n).into_usize(), n); From 1283c09cc191eeb7f04493f3a382ec3ff3a8208b Mon Sep 17 00:00:00 2001 From: tower120 Date: Fri, 30 Jan 2026 18:16:53 +0200 Subject: [PATCH 11/12] Apply suggestion from @reitermarkus Co-authored-by: Markus Reiter --- src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vec/mod.rs b/src/vec/mod.rs index ed3003a946..db93ef0bec 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -375,7 +375,7 @@ impl Vec { // Cast from [MaybeUninit] to [T] is safe since it is transparent. let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); - // NOTE(unsafe): Move/copy data from input array to output Self buffer. + // SAFETY: Move/copy data from input array to output Self buffer. unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; v.len = len; From e930cc6d177368108c5f08f3ed8748392c977f94 Mon Sep 17 00:00:00 2001 From: tower120 Date: Fri, 30 Jan 2026 18:40:27 +0200 Subject: [PATCH 12/12] SAFETY comments added --- src/len_type.rs | 1 + src/vec/mod.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/len_type.rs b/src/len_type.rs index 6c92df612f..7dd45c9102 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -116,6 +116,7 @@ pub const fn check_capacity_fits() { /// Const cast from [`usize`] to [`LenType`] with `as`. #[inline] pub const fn as_len_type(n: usize) -> L { + // SAFETY: transmute is safe since after cast we cast to the same type. unsafe { // ALWAYS compiletime switch. match L::TYPE { diff --git a/src/vec/mod.rs b/src/vec/mod.rs index db93ef0bec..37d0ba820c 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -368,14 +368,16 @@ impl Vec { let mut v = Self::new(); - // MaybeUninit::deref is non-const, so we just cast it through. - // Casting to internal value of MaybeUninit is safe since it is transparent. + // MaybeUninit::deref is non-const, so we just cast to it's internal value. let src_ptr: *const T = ptr::from_ref(&src).cast(); - // Cast from [MaybeUninit] to [T] is safe since it is transparent. + // Cast from buffer's [MaybeUninit] to [T]. let dst_ptr: *mut T = v.buffer.buffer.as_mut_ptr().cast(); - // SAFETY: Move/copy data from input array to output Self buffer. + // SAFETY: Move/copy data from src to v's internal buffer. + // * Using src_ptr as `*const T` is safe since src's ManuallyDrop<[T; M]> is transparent. + // * Using dst_ptr as `*mut T` is safe since v's [MaybeUninit; N] is an array of + // transparent types. unsafe { ptr::copy_nonoverlapping(src_ptr, dst_ptr, M) }; v.len = len;