@@ -3485,6 +3485,10 @@ impl<T> [T] {
34853485 /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
34863486 /// in a default (debug or release) execution *will* return a maximal middle part.
34873487 ///
3488+ /// If this behavior is not what you desire, as you don't want fallback paths for the bytes
3489+ /// outside the aligned part, consider using [aligned_subslice] or [transmute_elements] instead,
3490+ /// as these have stronger guarantees.
3491+ ///
34883492 /// This method has no purpose when either input element `T` or output element `U` are
34893493 /// zero-sized and will return the original slice without splitting anything.
34903494 ///
@@ -3547,6 +3551,10 @@ impl<T> [T] {
35473551 /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
35483552 /// in a default (debug or release) execution *will* return a maximal middle part.
35493553 ///
3554+ /// If this behavior is not what you desire, as you don't want fallback paths for the bytes
3555+ /// outside the aligned part, consider using [aligned_subslice_mut] or [transmute_elements_mut]
3556+ /// instead, as these have stronger guarantees.
3557+ ///
35503558 /// This method has no purpose when either input element `T` or output element `U` are
35513559 /// zero-sized and will return the original slice without splitting anything.
35523560 ///
@@ -3607,6 +3615,200 @@ impl<T> [T] {
36073615 }
36083616 }
36093617
3618+ /// Get a subslice where the first element is aligned to a given alignment and the size
3619+ /// of the slice is a multiple of the alignment.
3620+ ///
3621+ /// # Panics
3622+ ///
3623+ /// This method requires the alignment to be a multiple (larger than 1) of the alignment of
3624+ /// the slice element's alignment.
3625+ ///
3626+ /// # Examples
3627+ ///
3628+ /// Basic usage:
3629+ ///
3630+ /// ```
3631+ /// #![feature(slice_align_to_ish)]
3632+ /// let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
3633+ /// let ints = bytes.aligned_subslice(std::mem::align_of::<u32>());
3634+ /// assert_eq!(ints.len(), 1);
3635+ /// ```
3636+ #[ must_use]
3637+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3638+ #[ inline]
3639+ pub fn aligned_subslice ( & self , align : usize ) -> & [ T ] {
3640+ let size = crate :: mem:: size_of :: < T > ( ) ;
3641+ assert ! (
3642+ size < align,
3643+ "aligned_subslice does nothing for alignments below or at the element type's alignment"
3644+ ) ;
3645+ assert ! (
3646+ align % size == 0 ,
3647+ "aligned_subslice only works for alignments that are multiples of the element's size"
3648+ ) ;
3649+ let offset = self . as_ptr ( ) . addr ( ) % align;
3650+ // SAFETY: See the `align_to_mut` method for the detailed safety comment.
3651+ let end_offset = unsafe { self . as_ptr ( ) . offset ( self . len ( ) as isize ) } . addr ( ) % align;
3652+ let end = self . len ( ) - ( align / size - end_offset) ;
3653+ & self [ offset..end]
3654+ }
3655+
3656+ /// Get a subslice where the first element is aligned to a given alignment and the size
3657+ /// of the slice is a multiple of the alignment.
3658+ ///
3659+ /// # Panics
3660+ ///
3661+ /// This method requires the alignment to be a multiple (larger than 1) of the alignment of
3662+ /// the slice element's alignment.
3663+ ///
3664+ /// # Examples
3665+ ///
3666+ /// Basic usage:
3667+ ///
3668+ /// ```
3669+ /// #![feature(slice_align_to_ish)]
3670+ /// let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
3671+ /// let ints = bytes.aligned_subslice_mut(std::mem::align_of::<u32>());
3672+ /// assert_eq!(ints.len(), 1);
3673+ /// ```
3674+ #[ must_use]
3675+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3676+ #[ inline]
3677+ pub fn aligned_subslice_mut ( & mut self , align : usize ) -> & mut [ T ] {
3678+ let size = crate :: mem:: size_of :: < T > ( ) ;
3679+ assert ! (
3680+ size < align,
3681+ "aligned_subslice does nothing for alignments below or at the element type's alignment"
3682+ ) ;
3683+ assert ! (
3684+ align % size == 0 ,
3685+ "aligned_subslice only works for alignments that are multiples of the element's size"
3686+ ) ;
3687+ let offset = self . as_ptr ( ) . addr ( ) % align;
3688+ // SAFETY: See the `align_to_mut` method for the detailed safety comment.
3689+ let end_offset = unsafe { self . as_ptr ( ) . offset ( self . len ( ) as isize ) } . addr ( ) % align;
3690+ let end = self . len ( ) - ( align / size - end_offset) ;
3691+ & mut self [ offset..end]
3692+ }
3693+
3694+ /// Transmute the slice elements to another type.
3695+ ///
3696+ /// If the target element type is smaller than the source element type, the
3697+ /// returned slice will have multiple elements per element of the original slice.
3698+ ///
3699+ /// Cannot be used to go to an element type with higher alignment requirements.
3700+ /// Use `aligned_subslice` for that instead.
3701+ ///
3702+ /// # Panics
3703+ ///
3704+ /// The element sizes and the slice length must be such that all elements of the source
3705+ /// slice fit exactly into a slice of the destination element type. Resize your input slice
3706+ /// before invoking `transmute_elements` to uphold this checked requirement.
3707+ ///
3708+ /// # Safety
3709+ ///
3710+ /// This method is essentially a `transmute` between different elements, and even from
3711+ /// multiple elements into a single one or vice versa, so all the usual caveats
3712+ /// pertaining to `transmute::<T, U>` also apply here.
3713+ ///
3714+ /// # Examples
3715+ ///
3716+ /// Basic usage:
3717+ ///
3718+ /// ```
3719+ /// unsafe {
3720+ /// let ints: [u32; 2] = [1, 2];
3721+ /// let smaller_ints = ints.transmute_elements::<u16>();
3722+ /// assert_eq!(smaller_ints.len(), 4);
3723+ /// }
3724+ /// ```
3725+ #[ must_use]
3726+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3727+ #[ track_caller]
3728+ pub const unsafe fn transmute_elements < U > ( & self ) -> & [ U ] {
3729+ const {
3730+ let align_u = crate :: mem:: align_of :: < U > ( ) ;
3731+ let align_t = crate :: mem:: align_of :: < T > ( ) ;
3732+ assert ! ( align_u <= align_t, "use `aligned_subslice` instead" ) ;
3733+ } ;
3734+ let size_u = crate :: mem:: size_of :: < U > ( ) ;
3735+ let size_t = crate :: mem:: size_of :: < T > ( ) ;
3736+ if size_u > size_t {
3737+ assert ! (
3738+ self . len( ) * size_u % size_t == 0 ,
3739+ "input slice does not fit exactly into a slice of the output element type"
3740+ ) ;
3741+ } else {
3742+ assert ! (
3743+ self . len( ) * size_t % size_u == 0 ,
3744+ "input slice does not fit exactly into a slice of the output element type"
3745+ ) ;
3746+ }
3747+ // SAFETY: The size of the slice is such that with the new element size, all new
3748+ // elements are still within the bounds of the original slice. The change in element
3749+ // type is something the caller needs to make sure is sound.
3750+ unsafe { from_raw_parts ( self . as_ptr ( ) as * const _ , self . len ( ) * size_t / size_u) }
3751+ }
3752+
3753+ /// Transmute the slice elements to another type.
3754+ ///
3755+ /// If the target element type is smaller than the source element type, the
3756+ /// returned slice will have multiple elements per element of the original slice.
3757+ ///
3758+ /// Cannot be used to go to an element type with higher alignment requirements.
3759+ /// Use `aligned_subslice_mut` for that instead.
3760+ ///
3761+ /// # Panics
3762+ ///
3763+ /// The element sizes and the slice length must be such that all elements of the source
3764+ /// slice fit exactly into a slice of the destination element type. Resize your input slice
3765+ /// before invoking `transmute_elements_mut` to uphold this checked requirement.
3766+ ///
3767+ /// # Safety
3768+ ///
3769+ /// This method is essentially a `transmute` between different elements, and even from
3770+ /// multiple elements into a single one or vice versa, so all the usual caveats
3771+ /// pertaining to `transmute::<T, U>` also apply here.
3772+ ///
3773+ /// # Examples
3774+ ///
3775+ /// Basic usage:
3776+ ///
3777+ /// ```
3778+ /// unsafe {
3779+ /// let mut ints: [u32; 2] = [1, 2];
3780+ /// let smaller_ints = ints.transmute_elements_mut::<u16>();
3781+ /// assert_eq!(smaller_ints.len(), 4);
3782+ /// }
3783+ /// ```
3784+ #[ must_use]
3785+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3786+ #[ track_caller]
3787+ pub const unsafe fn transmute_elements_mut < U > ( & mut self ) -> & mut [ U ] {
3788+ const {
3789+ let align_u = crate :: mem:: align_of :: < U > ( ) ;
3790+ let align_t = crate :: mem:: align_of :: < T > ( ) ;
3791+ assert ! ( align_u <= align_t, "use `aligned_subslice_mut` instead" ) ;
3792+ } ;
3793+ let size_u = crate :: mem:: size_of :: < U > ( ) ;
3794+ let size_t = crate :: mem:: size_of :: < T > ( ) ;
3795+ if size_u > size_t {
3796+ assert ! (
3797+ self . len( ) * size_u % size_t == 0 ,
3798+ "input slice does not fit exactly into a slice of the output element type"
3799+ ) ;
3800+ } else {
3801+ assert ! (
3802+ self . len( ) * size_t % size_u == 0 ,
3803+ "input slice does not fit exactly into a slice of the output element type"
3804+ ) ;
3805+ }
3806+ // SAFETY: The size of the slice is such that with the new element size, all new
3807+ // elements are still within the bounds of the original slice. The change in element
3808+ // type is something the caller needs to make sure is sound.
3809+ unsafe { from_raw_parts_mut ( self . as_mut_ptr ( ) as * mut _ , self . len ( ) * size_t / size_u) }
3810+ }
3811+
36103812 /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
36113813 ///
36123814 /// This is a safe wrapper around [`slice::align_to`], so has the same weak
0 commit comments