Skip to content

Commit 11ff32f

Browse files
authored
Rollup merge of #76206 - CDirkx:const-ipv6, r=ecstatic-morse
Make all methods of `std::net::Ipv6Addr` const Make the following methods of `std::net::Ipv6Addr` unstable const under the `const_ipv6` feature: - `segments` - `is_unspecified` - `is_loopback` - `is_global` (unstable) - `is_unique_local` - `is_unicast_link_local_strict` - `is_documentation` - `multicast_scope` - `is_multicast` - `to_ipv4_mapped` - `to_ipv4` This would make all methods of `Ipv6Addr` const. Changed the implementation of `is_unspecified` and `is_loopback` to use a `match` instead of `==`, all other methods did not require a change. All these methods are dependent on `segments`, the current implementation of which requires unstable `const_fn_transmute` ([PR#75085](#75085)). Part of #76205
2 parents 17fa733 + 9afe97c commit 11ff32f

File tree

3 files changed

+84
-16
lines changed

3 files changed

+84
-16
lines changed

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@
238238
#![feature(concat_idents)]
239239
#![feature(const_cstr_unchecked)]
240240
#![feature(const_fn_transmute)]
241+
#![feature(const_ipv6)]
241242
#![feature(const_raw_ptr_deref)]
242243
#![feature(container_error_extra)]
243244
#![feature(core_intrinsics)]

library/std/src/net/ip.rs

+30-16
Original file line numberDiff line numberDiff line change
@@ -1102,8 +1102,9 @@ impl Ipv6Addr {
11021102
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
11031103
/// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
11041104
/// ```
1105+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
11051106
#[stable(feature = "rust1", since = "1.0.0")]
1106-
pub fn segments(&self) -> [u16; 8] {
1107+
pub const fn segments(&self) -> [u16; 8] {
11071108
// All elements in `s6_addr` must be big endian.
11081109
// SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
11091110
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
@@ -1135,9 +1136,10 @@ impl Ipv6Addr {
11351136
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
11361137
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
11371138
/// ```
1139+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
11381140
#[stable(since = "1.7.0", feature = "ip_17")]
1139-
pub fn is_unspecified(&self) -> bool {
1140-
self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
1141+
pub const fn is_unspecified(&self) -> bool {
1142+
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
11411143
}
11421144

11431145
/// Returns [`true`] if this is a loopback address (::1).
@@ -1155,9 +1157,10 @@ impl Ipv6Addr {
11551157
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
11561158
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
11571159
/// ```
1160+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
11581161
#[stable(since = "1.7.0", feature = "ip_17")]
1159-
pub fn is_loopback(&self) -> bool {
1160-
self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
1162+
pub const fn is_loopback(&self) -> bool {
1163+
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
11611164
}
11621165

11631166
/// Returns [`true`] if the address appears to be globally routable.
@@ -1182,7 +1185,8 @@ impl Ipv6Addr {
11821185
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
11831186
/// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
11841187
/// ```
1185-
pub fn is_global(&self) -> bool {
1188+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1189+
pub const fn is_global(&self) -> bool {
11861190
match self.multicast_scope() {
11871191
Some(Ipv6MulticastScope::Global) => true,
11881192
None => self.is_unicast_global(),
@@ -1208,7 +1212,8 @@ impl Ipv6Addr {
12081212
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
12091213
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
12101214
/// ```
1211-
pub fn is_unique_local(&self) -> bool {
1215+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1216+
pub const fn is_unique_local(&self) -> bool {
12121217
(self.segments()[0] & 0xfe00) == 0xfc00
12131218
}
12141219

@@ -1263,7 +1268,8 @@ impl Ipv6Addr {
12631268
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
12641269
/// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
12651270
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1266-
pub fn is_unicast_link_local_strict(&self) -> bool {
1271+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1272+
pub const fn is_unicast_link_local_strict(&self) -> bool {
12671273
(self.segments()[0] & 0xffff) == 0xfe80
12681274
&& (self.segments()[1] & 0xffff) == 0
12691275
&& (self.segments()[2] & 0xffff) == 0
@@ -1320,7 +1326,8 @@ impl Ipv6Addr {
13201326
///
13211327
/// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
13221328
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1323-
pub fn is_unicast_link_local(&self) -> bool {
1329+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1330+
pub const fn is_unicast_link_local(&self) -> bool {
13241331
(self.segments()[0] & 0xffc0) == 0xfe80
13251332
}
13261333

@@ -1359,7 +1366,8 @@ impl Ipv6Addr {
13591366
/// addresses.
13601367
///
13611368
/// [RFC 3879]: https://tools.ietf.org/html/rfc3879
1362-
pub fn is_unicast_site_local(&self) -> bool {
1369+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1370+
pub const fn is_unicast_site_local(&self) -> bool {
13631371
(self.segments()[0] & 0xffc0) == 0xfec0
13641372
}
13651373

@@ -1381,7 +1389,8 @@ impl Ipv6Addr {
13811389
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
13821390
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
13831391
/// ```
1384-
pub fn is_documentation(&self) -> bool {
1392+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1393+
pub const fn is_documentation(&self) -> bool {
13851394
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
13861395
}
13871396

@@ -1416,7 +1425,8 @@ impl Ipv6Addr {
14161425
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
14171426
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
14181427
/// ```
1419-
pub fn is_unicast_global(&self) -> bool {
1428+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1429+
pub const fn is_unicast_global(&self) -> bool {
14201430
!self.is_multicast()
14211431
&& !self.is_loopback()
14221432
&& !self.is_unicast_link_local()
@@ -1440,7 +1450,8 @@ impl Ipv6Addr {
14401450
/// );
14411451
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
14421452
/// ```
1443-
pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1453+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1454+
pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
14441455
if self.is_multicast() {
14451456
match self.segments()[0] & 0x000f {
14461457
1 => Some(Ipv6MulticastScope::InterfaceLocal),
@@ -1472,8 +1483,9 @@ impl Ipv6Addr {
14721483
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
14731484
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
14741485
/// ```
1486+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
14751487
#[stable(since = "1.7.0", feature = "ip_17")]
1476-
pub fn is_multicast(&self) -> bool {
1488+
pub const fn is_multicast(&self) -> bool {
14771489
(self.segments()[0] & 0xff00) == 0xff00
14781490
}
14791491

@@ -1498,7 +1510,8 @@ impl Ipv6Addr {
14981510
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
14991511
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
15001512
/// ```
1501-
pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1513+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1514+
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
15021515
match self.octets() {
15031516
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
15041517
Some(Ipv4Addr::new(a, b, c, d))
@@ -1525,8 +1538,9 @@ impl Ipv6Addr {
15251538
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
15261539
/// Some(Ipv4Addr::new(0, 0, 0, 1)));
15271540
/// ```
1541+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
15281542
#[stable(feature = "rust1", since = "1.0.0")]
1529-
pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
1543+
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
15301544
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
15311545
let [a, b] = ab.to_be_bytes();
15321546
let [c, d] = cd.to_be_bytes();

src/test/ui/consts/std/net/ipv6.rs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// run-pass
2+
3+
#![feature(ip)]
4+
#![feature(const_ipv6)]
5+
6+
use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
7+
8+
fn main() {
9+
const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
10+
assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
11+
12+
const SEGMENTS : [u16; 8] = IP_ADDRESS.segments();
13+
assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]);
14+
15+
const OCTETS : [u8; 16] = IP_ADDRESS.octets();
16+
assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0, 0, 1]);
17+
18+
const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
19+
assert!(!IS_UNSPECIFIED);
20+
21+
const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
22+
assert!(IS_LOOPBACK);
23+
24+
const IS_GLOBAL : bool = IP_ADDRESS.is_global();
25+
assert!(!IS_GLOBAL);
26+
27+
const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local();
28+
assert!(!IS_UNIQUE_LOCAL);
29+
30+
const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict();
31+
assert!(!IS_UNICAST_LINK_LOCAL_STRICT);
32+
33+
const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local();
34+
assert!(!IS_UNICAST_LINK_LOCAL);
35+
36+
const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local();
37+
assert!(!IS_UNICAST_SITE_LOCAL);
38+
39+
const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
40+
assert!(!IS_DOCUMENTATION);
41+
42+
const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global();
43+
assert!(!IS_UNICAST_GLOBAL);
44+
45+
const MULTICAST_SCOPE : Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
46+
assert_eq!(MULTICAST_SCOPE, None);
47+
48+
const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
49+
assert!(!IS_MULTICAST);
50+
51+
const IP_V4 : Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
52+
assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
53+
}

0 commit comments

Comments
 (0)