Rollup merge of #115955 - tgross35:ip-to-canonical, r=dtolnay

Stabilize `{IpAddr, Ipv6Addr}::to_canonical`

Make `IpAddr::to_canonical` and `IpV6Addr::to_canonical` stable (+const), as well as const stabilize `Ipv6Addr::to_ipv4_mapped`.

Newly stable API:

```rust
impl IpAddr {
    // Newly stable under `ip_to_canonical`
    const fn to_canonical(&self) -> IpAddr;
}

impl Ipv6Addr {
    // Newly stable under `ip_to_canonical`
    const fn to_canonical(&self) -> IpAddr;

    // Already stable, this makes it const stable under
    // `const_ipv6_to_ipv4_mapped`
    const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr>
}
```

These stabilize a subset of the following tracking issues:

- https://github.com/rust-lang/rust/issues/27709
- https://github.com/rust-lang/rust/issues/76205

Stabilization of all methods under the `ip` gate was attempted once at https://github.com/rust-lang/rust/pull/66584 then again at https://github.com/rust-lang/rust/pull/76098. These were not successful because there are still unknowns about `is_documentation` `is_benchmarking` and similar; `to_canonical` is much more straightforward.

I have looked and could not find any known issues with `to_canonical`. These were added in 2021 in https://github.com/rust-lang/rust/pull/87708

cc implementor ``@the8472``

r? libs-api
``@rustbot`` label +T-libs-api +needs-fcp
This commit is contained in:
Matthias Krüger 2023-10-16 06:26:20 +02:00 committed by GitHub
commit 17113f7db6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -412,9 +412,12 @@ impl IpAddr {
/// # Examples
///
/// ```
/// #![feature(ip)]
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// let localhost_v4 = Ipv4Addr::new(127, 0, 0, 1);
///
/// assert_eq!(IpAddr::V4(localhost_v4).to_canonical(), localhost_v4);
/// assert_eq!(IpAddr::V6(localhost_v4.to_ipv6_mapped()).to_canonical(), localhost_v4);
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
@ -422,11 +425,11 @@ impl IpAddr {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
#[unstable(feature = "ip", issue = "27709")]
#[stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")]
pub const fn to_canonical(&self) -> IpAddr {
match self {
&v4 @ IpAddr::V4(_) => v4,
IpAddr::V4(_) => *self,
IpAddr::V6(v6) => v6.to_canonical(),
}
}
@ -1750,11 +1753,11 @@ impl Ipv6Addr {
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
#[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "CURRENT_RUSTC_VERSION")]
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
match self.octets() {
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
@ -1819,11 +1822,11 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[unstable(feature = "ip", issue = "27709")]
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")]
pub const fn to_canonical(&self) -> IpAddr {
if let Some(mapped) = self.to_ipv4_mapped() {
return IpAddr::V4(mapped);