Skip to content

Commit 481e6b5

Browse files
committed
downgrade ptr.is_aligned_to crate-private
Per rust-lang#96284 (comment) this API is a mess and is regarded as insufficiently motivated. Removing it from the public API is potentially the only blocker on stabilizing its pleasant brother .is_aligned(). I initially just deleted it completely but it's since become Heavily Used for the purposes of assert_unsafe_precondition, and there's clearly Some Stuff going on with that API that I have no interest in poking.
1 parent da02fff commit 481e6b5

File tree

9 files changed

+41
-380
lines changed

9 files changed

+41
-380
lines changed

library/core/src/ptr/const_ptr.rs

+13-104
Original file line numberDiff line numberDiff line change
@@ -1501,116 +1501,25 @@ impl<T: ?Sized> *const T {
15011501
/// For non-`Sized` pointees this operation considers only the data pointer,
15021502
/// ignoring the metadata.
15031503
///
1504-
/// # Panics
1505-
///
1506-
/// The function panics if `align` is not a power-of-two (this includes 0).
1507-
///
1508-
/// # Examples
1509-
///
1510-
/// ```
1511-
/// #![feature(pointer_is_aligned)]
1512-
///
1513-
/// // On some platforms, the alignment of i32 is less than 4.
1514-
/// #[repr(align(4))]
1515-
/// struct AlignedI32(i32);
1516-
///
1517-
/// let data = AlignedI32(42);
1518-
/// let ptr = &data as *const AlignedI32;
1519-
///
1520-
/// assert!(ptr.is_aligned_to(1));
1521-
/// assert!(ptr.is_aligned_to(2));
1522-
/// assert!(ptr.is_aligned_to(4));
1523-
///
1524-
/// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
1525-
/// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
1526-
///
1527-
/// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
1528-
/// ```
1529-
///
1530-
/// # At compiletime
1531-
/// **Note: Alignment at compiletime is experimental and subject to change. See the
1532-
/// [tracking issue] for details.**
1533-
///
1534-
/// At compiletime, the compiler may not know where a value will end up in memory.
1535-
/// Calling this function on a pointer created from a reference at compiletime will only
1536-
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
1537-
/// cannot be stricter aligned than the reference's underlying allocation.
1538-
///
1539-
/// ```
1540-
/// #![feature(pointer_is_aligned)]
1541-
/// #![feature(const_pointer_is_aligned)]
1504+
/// This is an internal implementation detail of the stdlib, for implementing
1505+
/// low-level things like assert_unsafe_precondition.
15421506
///
1543-
/// // On some platforms, the alignment of i32 is less than 4.
1544-
/// #[repr(align(4))]
1545-
/// struct AlignedI32(i32);
1546-
///
1547-
/// const _: () = {
1548-
/// let data = AlignedI32(42);
1549-
/// let ptr = &data as *const AlignedI32;
1550-
///
1551-
/// assert!(ptr.is_aligned_to(1));
1552-
/// assert!(ptr.is_aligned_to(2));
1553-
/// assert!(ptr.is_aligned_to(4));
1554-
///
1555-
/// // At compiletime, we know for sure that the pointer isn't aligned to 8.
1556-
/// assert!(!ptr.is_aligned_to(8));
1557-
/// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
1558-
/// };
1559-
/// ```
1560-
///
1561-
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
1562-
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
1563-
///
1564-
/// ```
1565-
/// #![feature(pointer_is_aligned)]
1566-
/// #![feature(const_pointer_is_aligned)]
1567-
///
1568-
/// // On some platforms, the alignment of i32 is less than 4.
1569-
/// #[repr(align(4))]
1570-
/// struct AlignedI32(i32);
1571-
///
1572-
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
1573-
/// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
1574-
/// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
1575-
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
1576-
///
1577-
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
1578-
/// let runtime_ptr = COMPTIME_PTR;
1579-
/// assert_ne!(
1580-
/// runtime_ptr.is_aligned_to(8),
1581-
/// runtime_ptr.wrapping_add(1).is_aligned_to(8),
1582-
/// );
1583-
/// ```
1584-
///
1585-
/// If a pointer is created from a fixed address, this function behaves the same during
1586-
/// runtime and compiletime.
1587-
///
1588-
/// ```
1589-
/// #![feature(pointer_is_aligned)]
1590-
/// #![feature(const_pointer_is_aligned)]
1591-
///
1592-
/// const _: () = {
1593-
/// let ptr = 40 as *const u8;
1594-
/// assert!(ptr.is_aligned_to(1));
1595-
/// assert!(ptr.is_aligned_to(2));
1596-
/// assert!(ptr.is_aligned_to(4));
1597-
/// assert!(ptr.is_aligned_to(8));
1598-
/// assert!(!ptr.is_aligned_to(16));
1599-
/// };
1600-
/// ```
1507+
/// # Safety
16011508
///
1602-
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
1509+
/// The return value is unspecified if `align` isn't a power of two.
16031510
#[must_use]
16041511
#[inline]
1605-
#[unstable(feature = "pointer_is_aligned", issue = "96284")]
1606-
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
1607-
pub const fn is_aligned_to(self, align: usize) -> bool {
1608-
if !align.is_power_of_two() {
1609-
panic!("is_aligned_to: align is not a power-of-two");
1610-
}
1611-
1512+
pub(crate) const fn is_aligned_to(self, align: usize) -> bool {
16121513
#[inline]
16131514
fn runtime_impl(ptr: *const (), align: usize) -> bool {
1515+
// classic bitmath magic trick:
1516+
//
1517+
// * a power of two is a single bit set like 00001000
1518+
// * multiples of that must have all those low 0's also clear
1519+
// * subtracting one from the power gets you 00000111
1520+
// * so if we AND that with a multiple, we should get 0
1521+
//
1522+
// Note we get to assume align is a power of two
16141523
ptr.addr() & (align - 1) == 0
16151524
}
16161525

library/core/src/ptr/mut_ptr.rs

+1-134
Original file line numberDiff line numberDiff line change
@@ -1764,140 +1764,7 @@ impl<T: ?Sized> *mut T {
17641764
where
17651765
T: Sized,
17661766
{
1767-
self.is_aligned_to(mem::align_of::<T>())
1768-
}
1769-
1770-
/// Returns whether the pointer is aligned to `align`.
1771-
///
1772-
/// For non-`Sized` pointees this operation considers only the data pointer,
1773-
/// ignoring the metadata.
1774-
///
1775-
/// # Panics
1776-
///
1777-
/// The function panics if `align` is not a power-of-two (this includes 0).
1778-
///
1779-
/// # Examples
1780-
///
1781-
/// ```
1782-
/// #![feature(pointer_is_aligned)]
1783-
///
1784-
/// // On some platforms, the alignment of i32 is less than 4.
1785-
/// #[repr(align(4))]
1786-
/// struct AlignedI32(i32);
1787-
///
1788-
/// let mut data = AlignedI32(42);
1789-
/// let ptr = &mut data as *mut AlignedI32;
1790-
///
1791-
/// assert!(ptr.is_aligned_to(1));
1792-
/// assert!(ptr.is_aligned_to(2));
1793-
/// assert!(ptr.is_aligned_to(4));
1794-
///
1795-
/// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
1796-
/// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
1797-
///
1798-
/// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
1799-
/// ```
1800-
///
1801-
/// # At compiletime
1802-
/// **Note: Alignment at compiletime is experimental and subject to change. See the
1803-
/// [tracking issue] for details.**
1804-
///
1805-
/// At compiletime, the compiler may not know where a value will end up in memory.
1806-
/// Calling this function on a pointer created from a reference at compiletime will only
1807-
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
1808-
/// cannot be stricter aligned than the reference's underlying allocation.
1809-
///
1810-
/// ```
1811-
/// #![feature(pointer_is_aligned)]
1812-
/// #![feature(const_pointer_is_aligned)]
1813-
/// #![feature(const_mut_refs)]
1814-
///
1815-
/// // On some platforms, the alignment of i32 is less than 4.
1816-
/// #[repr(align(4))]
1817-
/// struct AlignedI32(i32);
1818-
///
1819-
/// const _: () = {
1820-
/// let mut data = AlignedI32(42);
1821-
/// let ptr = &mut data as *mut AlignedI32;
1822-
///
1823-
/// assert!(ptr.is_aligned_to(1));
1824-
/// assert!(ptr.is_aligned_to(2));
1825-
/// assert!(ptr.is_aligned_to(4));
1826-
///
1827-
/// // At compiletime, we know for sure that the pointer isn't aligned to 8.
1828-
/// assert!(!ptr.is_aligned_to(8));
1829-
/// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
1830-
/// };
1831-
/// ```
1832-
///
1833-
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
1834-
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
1835-
///
1836-
/// ```
1837-
/// #![feature(pointer_is_aligned)]
1838-
/// #![feature(const_pointer_is_aligned)]
1839-
///
1840-
/// // On some platforms, the alignment of i32 is less than 4.
1841-
/// #[repr(align(4))]
1842-
/// struct AlignedI32(i32);
1843-
///
1844-
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
1845-
/// // Also, note that mutable references are not allowed in the final value of constants.
1846-
/// const COMPTIME_PTR: *mut AlignedI32 = (&AlignedI32(42) as *const AlignedI32).cast_mut();
1847-
/// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
1848-
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
1849-
///
1850-
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
1851-
/// let runtime_ptr = COMPTIME_PTR;
1852-
/// assert_ne!(
1853-
/// runtime_ptr.is_aligned_to(8),
1854-
/// runtime_ptr.wrapping_add(1).is_aligned_to(8),
1855-
/// );
1856-
/// ```
1857-
///
1858-
/// If a pointer is created from a fixed address, this function behaves the same during
1859-
/// runtime and compiletime.
1860-
///
1861-
/// ```
1862-
/// #![feature(pointer_is_aligned)]
1863-
/// #![feature(const_pointer_is_aligned)]
1864-
///
1865-
/// const _: () = {
1866-
/// let ptr = 40 as *mut u8;
1867-
/// assert!(ptr.is_aligned_to(1));
1868-
/// assert!(ptr.is_aligned_to(2));
1869-
/// assert!(ptr.is_aligned_to(4));
1870-
/// assert!(ptr.is_aligned_to(8));
1871-
/// assert!(!ptr.is_aligned_to(16));
1872-
/// };
1873-
/// ```
1874-
///
1875-
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
1876-
#[must_use]
1877-
#[inline]
1878-
#[unstable(feature = "pointer_is_aligned", issue = "96284")]
1879-
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
1880-
pub const fn is_aligned_to(self, align: usize) -> bool {
1881-
if !align.is_power_of_two() {
1882-
panic!("is_aligned_to: align is not a power-of-two");
1883-
}
1884-
1885-
#[inline]
1886-
fn runtime_impl(ptr: *mut (), align: usize) -> bool {
1887-
ptr.addr() & (align - 1) == 0
1888-
}
1889-
1890-
#[inline]
1891-
const fn const_impl(ptr: *mut (), align: usize) -> bool {
1892-
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
1893-
// The cast to `()` is used to
1894-
// 1. deal with fat pointers; and
1895-
// 2. ensure that `align_offset` doesn't actually try to compute an offset.
1896-
ptr.align_offset(align) == 0
1897-
}
1898-
1899-
// SAFETY: The two versions are equivalent at runtime.
1900-
unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) }
1767+
(self as *const T).is_aligned()
19011768
}
19021769
}
19031770

library/core/src/ptr/non_null.rs

-112
Original file line numberDiff line numberDiff line change
@@ -1405,118 +1405,6 @@ impl<T: ?Sized> NonNull<T> {
14051405
{
14061406
self.pointer.is_aligned()
14071407
}
1408-
1409-
/// Returns whether the pointer is aligned to `align`.
1410-
///
1411-
/// For non-`Sized` pointees this operation considers only the data pointer,
1412-
/// ignoring the metadata.
1413-
///
1414-
/// # Panics
1415-
///
1416-
/// The function panics if `align` is not a power-of-two (this includes 0).
1417-
///
1418-
/// # Examples
1419-
///
1420-
/// ```
1421-
/// #![feature(pointer_is_aligned)]
1422-
///
1423-
/// // On some platforms, the alignment of i32 is less than 4.
1424-
/// #[repr(align(4))]
1425-
/// struct AlignedI32(i32);
1426-
///
1427-
/// let data = AlignedI32(42);
1428-
/// let ptr = &data as *const AlignedI32;
1429-
///
1430-
/// assert!(ptr.is_aligned_to(1));
1431-
/// assert!(ptr.is_aligned_to(2));
1432-
/// assert!(ptr.is_aligned_to(4));
1433-
///
1434-
/// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
1435-
/// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
1436-
///
1437-
/// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
1438-
/// ```
1439-
///
1440-
/// # At compiletime
1441-
/// **Note: Alignment at compiletime is experimental and subject to change. See the
1442-
/// [tracking issue] for details.**
1443-
///
1444-
/// At compiletime, the compiler may not know where a value will end up in memory.
1445-
/// Calling this function on a pointer created from a reference at compiletime will only
1446-
/// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
1447-
/// cannot be stricter aligned than the reference's underlying allocation.
1448-
///
1449-
/// ```
1450-
/// #![feature(pointer_is_aligned)]
1451-
/// #![feature(const_pointer_is_aligned)]
1452-
///
1453-
/// // On some platforms, the alignment of i32 is less than 4.
1454-
/// #[repr(align(4))]
1455-
/// struct AlignedI32(i32);
1456-
///
1457-
/// const _: () = {
1458-
/// let data = AlignedI32(42);
1459-
/// let ptr = &data as *const AlignedI32;
1460-
///
1461-
/// assert!(ptr.is_aligned_to(1));
1462-
/// assert!(ptr.is_aligned_to(2));
1463-
/// assert!(ptr.is_aligned_to(4));
1464-
///
1465-
/// // At compiletime, we know for sure that the pointer isn't aligned to 8.
1466-
/// assert!(!ptr.is_aligned_to(8));
1467-
/// assert!(!ptr.wrapping_add(1).is_aligned_to(8));
1468-
/// };
1469-
/// ```
1470-
///
1471-
/// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
1472-
/// pointer is aligned, even if the compiletime pointer wasn't aligned.
1473-
///
1474-
/// ```
1475-
/// #![feature(pointer_is_aligned)]
1476-
/// #![feature(const_pointer_is_aligned)]
1477-
///
1478-
/// // On some platforms, the alignment of i32 is less than 4.
1479-
/// #[repr(align(4))]
1480-
/// struct AlignedI32(i32);
1481-
///
1482-
/// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
1483-
/// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
1484-
/// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
1485-
/// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
1486-
///
1487-
/// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
1488-
/// let runtime_ptr = COMPTIME_PTR;
1489-
/// assert_ne!(
1490-
/// runtime_ptr.is_aligned_to(8),
1491-
/// runtime_ptr.wrapping_add(1).is_aligned_to(8),
1492-
/// );
1493-
/// ```
1494-
///
1495-
/// If a pointer is created from a fixed address, this function behaves the same during
1496-
/// runtime and compiletime.
1497-
///
1498-
/// ```
1499-
/// #![feature(pointer_is_aligned)]
1500-
/// #![feature(const_pointer_is_aligned)]
1501-
///
1502-
/// const _: () = {
1503-
/// let ptr = 40 as *const u8;
1504-
/// assert!(ptr.is_aligned_to(1));
1505-
/// assert!(ptr.is_aligned_to(2));
1506-
/// assert!(ptr.is_aligned_to(4));
1507-
/// assert!(ptr.is_aligned_to(8));
1508-
/// assert!(!ptr.is_aligned_to(16));
1509-
/// };
1510-
/// ```
1511-
///
1512-
/// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
1513-
#[unstable(feature = "pointer_is_aligned", issue = "96284")]
1514-
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
1515-
#[must_use]
1516-
#[inline]
1517-
pub const fn is_aligned_to(self, align: usize) -> bool {
1518-
self.pointer.is_aligned_to(align)
1519-
}
15201408
}
15211409

15221410
impl<T> NonNull<[T]> {

library/core/src/slice/ascii.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ const fn is_ascii(s: &[u8]) -> bool {
386386
// have alignment information it should have given a `usize::MAX` for
387387
// `align_offset` earlier, sending things through the scalar path instead of
388388
// this one, so this check should pass if it's reachable.
389-
debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>()));
389+
debug_assert!(word_ptr.is_aligned());
390390

391391
// Read subsequent words until the last aligned word, excluding the last
392392
// aligned word by itself to be done in tail check later, to ensure that

0 commit comments

Comments
 (0)