@@ -1282,6 +1282,240 @@ impl<T: ?Sized> NonNull<T> {
12821282 unsafe { ptr:: align_offset ( self . pointer , align) }
12831283 }
12841284 }
1285+
1286+ /// Returns whether the pointer is properly aligned for `T`.
1287+ ///
1288+ /// # Examples
1289+ ///
1290+ /// ```
1291+ /// #![feature(pointer_is_aligned)]
1292+ /// use std::ptr::NonNull;
1293+ ///
1294+ /// // On some platforms, the alignment of i32 is less than 4.
1295+ /// #[repr(align(4))]
1296+ /// struct AlignedI32(i32);
1297+ ///
1298+ /// let data = AlignedI32(42);
1299+ /// let ptr = NonNull::<AlignedI32>::from(&data);
1300+ ///
1301+ /// assert!(ptr.is_aligned());
1302+ /// assert!(!NonNull::new(ptr.as_ptr().wrapping_byte_add(1)).unwrap().is_aligned());
1303+ /// ```
1304+ ///
1305+ /// # At compiletime
1306+ /// **Note: Alignment at compiletime is experimental and subject to change. See the
1307+ /// [tracking issue] for details.**
1308+ ///
1309+ /// At compiletime, the compiler may not know where a value will end up in memory.
1310+ /// Calling this function on a pointer created from a reference at compiletime will only
1311+ /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
1312+ /// is never aligned if cast to a type with a stricter alignment than the reference's
1313+ /// underlying allocation.
1314+ ///
1315+ /// ```
1316+ /// #![feature(pointer_is_aligned)]
1317+ /// #![feature(const_pointer_is_aligned)]
1318+ /// #![feature(non_null_convenience)]
1319+ /// #![feature(const_option)]
1320+ /// #![feature(const_nonnull_new)]
1321+ /// use std::ptr::NonNull;
1322+ ///
1323+ /// // On some platforms, the alignment of primitives is less than their size.
1324+ /// #[repr(align(4))]
1325+ /// struct AlignedI32(i32);
1326+ /// #[repr(align(8))]
1327+ /// struct AlignedI64(i64);
1328+ ///
1329+ /// const _: () = {
1330+ /// let data = [AlignedI32(42), AlignedI32(42)];
1331+ /// let ptr = NonNull::<AlignedI32>::new(&data[0] as *const _ as *mut _).unwrap();
1332+ /// assert!(ptr.is_aligned());
1333+ ///
1334+ /// // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
1335+ /// let ptr1 = ptr.cast::<AlignedI64>();
1336+ /// let ptr2 = unsafe { ptr.add(1).cast::<AlignedI64>() };
1337+ /// assert!(!ptr1.is_aligned());
1338+ /// assert!(!ptr2.is_aligned());
1339+ /// };
1340+ /// ```
1341+ ///
1342+ /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
1343+ /// pointer is aligned, even if the compiletime pointer wasn't aligned.
1344+ ///
1345+ /// ```
1346+ /// #![feature(pointer_is_aligned)]
1347+ /// #![feature(const_pointer_is_aligned)]
1348+ ///
1349+ /// // On some platforms, the alignment of primitives is less than their size.
1350+ /// #[repr(align(4))]
1351+ /// struct AlignedI32(i32);
1352+ /// #[repr(align(8))]
1353+ /// struct AlignedI64(i64);
1354+ ///
1355+ /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
1356+ /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
1357+ /// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
1358+ /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
1359+ ///
1360+ /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
1361+ /// let runtime_ptr = COMPTIME_PTR;
1362+ /// assert_ne!(
1363+ /// runtime_ptr.cast::<AlignedI64>().is_aligned(),
1364+ /// runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
1365+ /// );
1366+ /// ```
1367+ ///
1368+ /// If a pointer is created from a fixed address, this function behaves the same during
1369+ /// runtime and compiletime.
1370+ ///
1371+ /// ```
1372+ /// #![feature(pointer_is_aligned)]
1373+ /// #![feature(const_pointer_is_aligned)]
1374+ /// #![feature(const_option)]
1375+ /// #![feature(const_nonnull_new)]
1376+ /// use std::ptr::NonNull;
1377+ ///
1378+ /// // On some platforms, the alignment of primitives is less than their size.
1379+ /// #[repr(align(4))]
1380+ /// struct AlignedI32(i32);
1381+ /// #[repr(align(8))]
1382+ /// struct AlignedI64(i64);
1383+ ///
1384+ /// const _: () = {
1385+ /// let ptr = NonNull::new(40 as *mut AlignedI32).unwrap();
1386+ /// assert!(ptr.is_aligned());
1387+ ///
1388+ /// // For pointers with a known address, runtime and compiletime behavior are identical.
1389+ /// let ptr1 = ptr.cast::<AlignedI64>();
1390+ /// let ptr2 = NonNull::new(ptr.as_ptr().wrapping_add(1)).unwrap().cast::<AlignedI64>();
1391+ /// assert!(ptr1.is_aligned());
1392+ /// assert!(!ptr2.is_aligned());
1393+ /// };
1394+ /// ```
1395+ ///
1396+ /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
1397+ #[ unstable( feature = "pointer_is_aligned" , issue = "96284" ) ]
1398+ #[ rustc_const_unstable( feature = "const_pointer_is_aligned" , issue = "104203" ) ]
1399+ #[ must_use]
1400+ #[ inline]
1401+ pub const fn is_aligned ( self ) -> bool
1402+ where
1403+ T : Sized ,
1404+ {
1405+ self . pointer . is_aligned ( )
1406+ }
1407+
1408+ /// Returns whether the pointer is aligned to `align`.
1409+ ///
1410+ /// For non-`Sized` pointees this operation considers only the data pointer,
1411+ /// ignoring the metadata.
1412+ ///
1413+ /// # Panics
1414+ ///
1415+ /// The function panics if `align` is not a power-of-two (this includes 0).
1416+ ///
1417+ /// # Examples
1418+ ///
1419+ /// ```
1420+ /// #![feature(pointer_is_aligned)]
1421+ ///
1422+ /// // On some platforms, the alignment of i32 is less than 4.
1423+ /// #[repr(align(4))]
1424+ /// struct AlignedI32(i32);
1425+ ///
1426+ /// let data = AlignedI32(42);
1427+ /// let ptr = &data as *const AlignedI32;
1428+ ///
1429+ /// assert!(ptr.is_aligned_to(1));
1430+ /// assert!(ptr.is_aligned_to(2));
1431+ /// assert!(ptr.is_aligned_to(4));
1432+ ///
1433+ /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
1434+ /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
1435+ ///
1436+ /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
1437+ /// ```
1438+ ///
1439+ /// # At compiletime
1440+ /// **Note: Alignment at compiletime is experimental and subject to change. See the
1441+ /// [tracking issue] for details.**
1442+ ///
1443+ /// At compiletime, the compiler may not know where a value will end up in memory.
1444+ /// Calling this function on a pointer created from a reference at compiletime will only
1445+ /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
1446+ /// cannot be stricter aligned than the reference's underlying allocation.
1447+ ///
1448+ /// ```
1449+ /// #![feature(pointer_is_aligned)]
1450+ /// #![feature(const_pointer_is_aligned)]
1451+ ///
1452+ /// // On some platforms, the alignment of i32 is less than 4.
1453+ /// #[repr(align(4))]
1454+ /// struct AlignedI32(i32);
1455+ ///
1456+ /// const _: () = {
1457+ /// let data = AlignedI32(42);
1458+ /// let ptr = &data as *const AlignedI32;
1459+ ///
1460+ /// assert!(ptr.is_aligned_to(1));
1461+ /// assert!(ptr.is_aligned_to(2));
1462+ /// assert!(ptr.is_aligned_to(4));
1463+ ///
1464+ /// // At compiletime, we know for sure that the pointer isn't aligned to 8.
1465+ /// assert!(!ptr.is_aligned_to(8));
1466+ /// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
1467+ /// };
1468+ /// ```
1469+ ///
1470+ /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
1471+ /// pointer is aligned, even if the compiletime pointer wasn't aligned.
1472+ ///
1473+ /// ```
1474+ /// #![feature(pointer_is_aligned)]
1475+ /// #![feature(const_pointer_is_aligned)]
1476+ ///
1477+ /// // On some platforms, the alignment of i32 is less than 4.
1478+ /// #[repr(align(4))]
1479+ /// struct AlignedI32(i32);
1480+ ///
1481+ /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
1482+ /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
1483+ /// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
1484+ /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
1485+ ///
1486+ /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
1487+ /// let runtime_ptr = COMPTIME_PTR;
1488+ /// assert_ne!(
1489+ /// runtime_ptr.is_aligned_to(8),
1490+ /// runtime_ptr.wrapping_add(1).is_aligned_to(8),
1491+ /// );
1492+ /// ```
1493+ ///
1494+ /// If a pointer is created from a fixed address, this function behaves the same during
1495+ /// runtime and compiletime.
1496+ ///
1497+ /// ```
1498+ /// #![feature(pointer_is_aligned)]
1499+ /// #![feature(const_pointer_is_aligned)]
1500+ ///
1501+ /// const _: () = {
1502+ /// let ptr = 40 as *const u8;
1503+ /// assert!(ptr.is_aligned_to(1));
1504+ /// assert!(ptr.is_aligned_to(2));
1505+ /// assert!(ptr.is_aligned_to(4));
1506+ /// assert!(ptr.is_aligned_to(8));
1507+ /// assert!(!ptr.is_aligned_to(16));
1508+ /// };
1509+ /// ```
1510+ ///
1511+ /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
1512+ #[ unstable( feature = "pointer_is_aligned" , issue = "96284" ) ]
1513+ #[ rustc_const_unstable( feature = "const_pointer_is_aligned" , issue = "104203" ) ]
1514+ #[ must_use]
1515+ #[ inline]
1516+ pub const fn is_aligned_to ( self , align : usize ) -> bool {
1517+ self . pointer . is_aligned_to ( align)
1518+ }
12851519}
12861520
12871521impl < T > NonNull < [ T ] > {
0 commit comments