Skip to content

Commit bd2f1cb

Browse files
committed
Auto merge of #79342 - CDirkx:ipaddr-const, r=oli-obk
Stabilize all stable methods of `Ipv4Addr`, `Ipv6Addr` and `IpAddr` as const This PR stabilizes all currently stable methods of `Ipv4Addr`, `Ipv6Addr` and `IpAddr` as const. Tracking issue: #76205 `Ipv4Addr` (`const_ipv4`): - `octets` - `is_loopback` - `is_private` - `is_link_local` - `is_multicast` - `is_broadcast` - `is_docmentation` - `to_ipv6_compatible` - `to_ipv6_mapped` `Ipv6Addr` (`const_ipv6`): - `segments` - `is_unspecified` - `is_loopback` - `is_multicast` - `to_ipv4` `IpAddr` (`const_ip`): - `is_unspecified` - `is_loopback` - `is_multicast` ## Motivation The ip methods seem like prime candidates to be made const: their behavior is defined by an external spec, and based solely on the byte contents of an address. These methods have been made unstable const in the beginning of September, after the necessary const integer arithmetic was stabilized. There is currently a PR open (#78802) to change the internal representation of `IpAddr{4,6}` from `libc` types to a byte array. This does not have any impact on the constness of the methods. ## Implementation Most of the stabilizations are straightforward, with the exception of `Ipv6Addr::segments`, which uses the unstable feature `const_fn_transmute`. The code could be rewritten to equivalent stable code, but this leads to worse code generation (#75085). This is why `segments` gets marked with `#[rustc_allow_const_fn_unstable(const_fn_transmute)]`, like the already const-stable `Ipv6Addr::new`, the justification being that a const-stable alternative implementation exists #76206 (comment). ## Future posibilities This PR const-stabilizes all currently stable ip methods, however there are also a number of unstable methods under the `ip` feature (#27709). These methods are already unstable const. There is a PR open (#76098) to stabilize those methods, which could include const-stabilization. However, stabilizing those methods as const is dependent on `Ipv4Addr::octets` and `Ipv6Addr::segments` (covered by this PR).
2 parents 8bb302d + 4fcef4b commit bd2f1cb

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

library/std/src/net/ip.rs

+27-22
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl IpAddr {
148148
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
149149
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
150150
/// ```
151-
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
151+
#[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
152152
#[stable(feature = "ip_shared", since = "1.12.0")]
153153
pub const fn is_unspecified(&self) -> bool {
154154
match self {
@@ -170,7 +170,7 @@ impl IpAddr {
170170
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
171171
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
172172
/// ```
173-
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
173+
#[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
174174
#[stable(feature = "ip_shared", since = "1.12.0")]
175175
pub const fn is_loopback(&self) -> bool {
176176
match self {
@@ -215,7 +215,7 @@ impl IpAddr {
215215
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
216216
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
217217
/// ```
218-
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
218+
#[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
219219
#[stable(feature = "ip_shared", since = "1.12.0")]
220220
pub const fn is_multicast(&self) -> bool {
221221
match self {
@@ -301,8 +301,8 @@ impl Ipv4Addr {
301301
///
302302
/// let addr = Ipv4Addr::new(127, 0, 0, 1);
303303
/// ```
304-
#[stable(feature = "rust1", since = "1.0.0")]
305304
#[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
305+
#[stable(feature = "rust1", since = "1.0.0")]
306306
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
307307
// `s_addr` is stored as BE on all machine and the array is in BE order.
308308
// So the native endian conversion method is used so that it's never swapped.
@@ -358,7 +358,7 @@ impl Ipv4Addr {
358358
/// let addr = Ipv4Addr::new(127, 0, 0, 1);
359359
/// assert_eq!(addr.octets(), [127, 0, 0, 1]);
360360
/// ```
361-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
361+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
362362
#[stable(feature = "rust1", since = "1.0.0")]
363363
pub const fn octets(&self) -> [u8; 4] {
364364
// This returns the order we want because s_addr is stored in big-endian.
@@ -380,8 +380,8 @@ impl Ipv4Addr {
380380
/// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
381381
/// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
382382
/// ```
383-
#[stable(feature = "ip_shared", since = "1.12.0")]
384383
#[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
384+
#[stable(feature = "ip_shared", since = "1.12.0")]
385385
pub const fn is_unspecified(&self) -> bool {
386386
self.inner.s_addr == 0
387387
}
@@ -400,7 +400,7 @@ impl Ipv4Addr {
400400
/// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
401401
/// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
402402
/// ```
403-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
403+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
404404
#[stable(since = "1.7.0", feature = "ip_17")]
405405
pub const fn is_loopback(&self) -> bool {
406406
self.octets()[0] == 127
@@ -429,7 +429,7 @@ impl Ipv4Addr {
429429
/// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
430430
/// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
431431
/// ```
432-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
432+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
433433
#[stable(since = "1.7.0", feature = "ip_17")]
434434
pub const fn is_private(&self) -> bool {
435435
match self.octets() {
@@ -455,7 +455,7 @@ impl Ipv4Addr {
455455
/// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
456456
/// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
457457
/// ```
458-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
458+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
459459
#[stable(since = "1.7.0", feature = "ip_17")]
460460
pub const fn is_link_local(&self) -> bool {
461461
matches!(self.octets(), [169, 254, ..])
@@ -675,7 +675,7 @@ impl Ipv4Addr {
675675
/// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
676676
/// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
677677
/// ```
678-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
678+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
679679
#[stable(since = "1.7.0", feature = "ip_17")]
680680
pub const fn is_multicast(&self) -> bool {
681681
self.octets()[0] >= 224 && self.octets()[0] <= 239
@@ -695,7 +695,7 @@ impl Ipv4Addr {
695695
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
696696
/// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
697697
/// ```
698-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
698+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
699699
#[stable(since = "1.7.0", feature = "ip_17")]
700700
pub const fn is_broadcast(&self) -> bool {
701701
u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
@@ -721,7 +721,7 @@ impl Ipv4Addr {
721721
/// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
722722
/// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
723723
/// ```
724-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
724+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
725725
#[stable(since = "1.7.0", feature = "ip_17")]
726726
pub const fn is_documentation(&self) -> bool {
727727
match self.octets() {
@@ -751,7 +751,7 @@ impl Ipv4Addr {
751751
/// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
752752
/// );
753753
/// ```
754-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
754+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
755755
#[stable(feature = "rust1", since = "1.0.0")]
756756
pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
757757
let [a, b, c, d] = self.octets();
@@ -774,7 +774,7 @@ impl Ipv4Addr {
774774
/// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
775775
/// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
776776
/// ```
777-
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
777+
#[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
778778
#[stable(feature = "rust1", since = "1.0.0")]
779779
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
780780
let [a, b, c, d] = self.octets();
@@ -1043,9 +1043,9 @@ impl Ipv6Addr {
10431043
///
10441044
/// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
10451045
/// ```
1046-
#[stable(feature = "rust1", since = "1.0.0")]
1047-
#[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
10481046
#[rustc_allow_const_fn_unstable(const_fn_transmute)]
1047+
#[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1048+
#[stable(feature = "rust1", since = "1.0.0")]
10491049
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
10501050
let addr16 = [
10511051
a.to_be(),
@@ -1061,6 +1061,8 @@ impl Ipv6Addr {
10611061
inner: c::in6_addr {
10621062
// All elements in `addr16` are big endian.
10631063
// SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
1064+
// rustc_allow_const_fn_unstable: the transmute could be written as stable const
1065+
// code, but that leads to worse code generation (#75085)
10641066
s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
10651067
},
10661068
}
@@ -1102,11 +1104,14 @@ impl Ipv6Addr {
11021104
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
11031105
/// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
11041106
/// ```
1105-
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1107+
#[rustc_allow_const_fn_unstable(const_fn_transmute)]
1108+
#[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
11061109
#[stable(feature = "rust1", since = "1.0.0")]
11071110
pub const fn segments(&self) -> [u16; 8] {
11081111
// All elements in `s6_addr` must be big endian.
11091112
// SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
1113+
// rustc_allow_const_fn_unstable: the transmute could be written as stable const code, but
1114+
// that leads to worse code generation (#75085)
11101115
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
11111116
// We want native endian u16
11121117
[
@@ -1135,7 +1140,7 @@ impl Ipv6Addr {
11351140
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
11361141
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
11371142
/// ```
1138-
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1143+
#[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
11391144
#[stable(since = "1.7.0", feature = "ip_17")]
11401145
pub const fn is_unspecified(&self) -> bool {
11411146
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
@@ -1155,7 +1160,7 @@ impl Ipv6Addr {
11551160
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
11561161
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
11571162
/// ```
1158-
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1163+
#[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
11591164
#[stable(since = "1.7.0", feature = "ip_17")]
11601165
pub const fn is_loopback(&self) -> bool {
11611166
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
@@ -1465,7 +1470,7 @@ impl Ipv6Addr {
14651470
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
14661471
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
14671472
/// ```
1468-
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1473+
#[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
14691474
#[stable(since = "1.7.0", feature = "ip_17")]
14701475
pub const fn is_multicast(&self) -> bool {
14711476
(self.segments()[0] & 0xff00) == 0xff00
@@ -1520,7 +1525,7 @@ impl Ipv6Addr {
15201525
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
15211526
/// Some(Ipv4Addr::new(0, 0, 0, 1)));
15221527
/// ```
1523-
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1528+
#[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
15241529
#[stable(feature = "rust1", since = "1.0.0")]
15251530
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
15261531
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
@@ -1540,8 +1545,8 @@ impl Ipv6Addr {
15401545
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
15411546
/// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
15421547
/// ```
1543-
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
15441548
#[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1549+
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
15451550
pub const fn octets(&self) -> [u8; 16] {
15461551
self.inner.s6_addr
15471552
}

0 commit comments

Comments
 (0)