@@ -1222,6 +1222,66 @@ impl<T: ?Sized> NonNull<T> {
12221222 // SAFETY: the caller must uphold the safety contract for `swap`.
12231223 unsafe { ptr:: swap ( self . as_ptr ( ) , with. as_ptr ( ) ) }
12241224 }
1225+
1226+ /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
1227+ /// `align`.
1228+ ///
1229+ /// If it is not possible to align the pointer, the implementation returns
1230+ /// `usize::MAX`. It is permissible for the implementation to *always*
1231+ /// return `usize::MAX`. Only your algorithm's performance can depend
1232+ /// on getting a usable offset here, not its correctness.
1233+ ///
1234+ /// The offset is expressed in number of `T` elements, and not bytes.
1235+ ///
1236+ /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
1237+ /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
1238+ /// the returned offset is correct in all terms other than alignment.
1239+ ///
1240+ /// # Panics
1241+ ///
1242+ /// The function panics if `align` is not a power-of-two.
1243+ ///
1244+ /// # Examples
1245+ ///
1246+ /// Accessing adjacent `u8` as `u16`
1247+ ///
1248+ /// ```
1249+ /// #![feature(non_null_convenience)]
1250+ /// use std::mem::align_of;
1251+ /// use std::ptr::NonNull;
1252+ ///
1253+ /// # unsafe {
1254+ /// let x = [5_u8, 6, 7, 8, 9];
1255+ /// let ptr = NonNull::new(x.as_ptr() as *mut u8).unwrap();
1256+ /// let offset = ptr.align_offset(align_of::<u16>());
1257+ ///
1258+ /// if offset < x.len() - 1 {
1259+ /// let u16_ptr = ptr.add(offset).cast::<u16>();
1260+ /// assert!(u16_ptr.read() == u16::from_ne_bytes([5, 6]) || u16_ptr.read() == u16::from_ne_bytes([6, 7]));
1261+ /// } else {
1262+ /// // while the pointer can be aligned via `offset`, it would point
1263+ /// // outside the allocation
1264+ /// }
1265+ /// # }
1266+ /// ```
1267+ #[ unstable( feature = "non_null_convenience" , issue = "117691" ) ]
1268+ #[ rustc_const_unstable( feature = "non_null_convenience" , issue = "117691" ) ]
1269+ //#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
1270+ #[ must_use]
1271+ #[ inline]
1272+ pub const fn align_offset ( self , align : usize ) -> usize
1273+ where
1274+ T : Sized ,
1275+ {
1276+ if !align. is_power_of_two ( ) {
1277+ panic ! ( "align_offset: align is not a power-of-two" ) ;
1278+ }
1279+
1280+ {
1281+ // SAFETY: `align` has been checked to be a power of 2 above.
1282+ unsafe { ptr:: align_offset ( self . pointer , align) }
1283+ }
1284+ }
12251285}
12261286
12271287impl < T > NonNull < [ T ] > {
0 commit comments