@@ -1282,6 +1282,240 @@ impl<T: ?Sized> NonNull<T> {
1282
1282
unsafe { ptr:: align_offset ( self . pointer , align) }
1283
1283
}
1284
1284
}
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
+ }
1285
1519
}
1286
1520
1287
1521
impl < T > NonNull < [ T ] > {
0 commit comments