From fbb367333190128015d35c0211877d71796f8deb Mon Sep 17 00:00:00 2001 From: CDirkx Date: Mon, 31 Aug 2020 05:09:20 +0200 Subject: [PATCH 1/4] Make more Ipv4Addr methods const Constify the following methods of `std::net::Ipv4Addr`: - `octets` - `is_loopback` - `is_private` - `is_link_local` - `is_shared` - `is_ietf_protocol_assignment` - `is_benchmarking` - `is_multicast` - `is_documentation` Also insta-stabilizes these methods as const. Possible because of the stabilization of const integer arithmetic and control flow. --- library/std/src/net/ip.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 85bb6b60e6829..c37323b1bc48a 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -361,8 +361,9 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::new(127, 0, 0, 1); /// assert_eq!(addr.octets(), [127, 0, 0, 1]); /// ``` + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] #[stable(feature = "rust1", since = "1.0.0")] - pub fn octets(&self) -> [u8; 4] { + pub const fn octets(&self) -> [u8; 4] { // This returns the order we want because s_addr is stored in big-endian. self.inner.s_addr.to_ne_bytes() } @@ -404,8 +405,9 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); /// ``` + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_loopback(&self) -> bool { + pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 } @@ -433,8 +435,9 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); /// ``` + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_private(&self) -> bool { + pub const fn is_private(&self) -> bool { match self.octets() { [10, ..] => true, [172, b, ..] if b >= 16 && b <= 31 => true, @@ -459,8 +462,9 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); /// ``` + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_link_local(&self) -> bool { + pub const fn is_link_local(&self) -> bool { match self.octets() { [169, 254, ..] => true, _ => false, @@ -573,7 +577,8 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); /// ``` - pub fn is_shared(&self) -> bool { + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + pub const fn is_shared(&self) -> bool { self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) } @@ -605,7 +610,8 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); /// ``` - pub fn is_ietf_protocol_assignment(&self) -> bool { + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + pub const fn is_ietf_protocol_assignment(&self) -> bool { self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 } @@ -628,7 +634,8 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); /// ``` - pub fn is_benchmarking(&self) -> bool { + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + pub const fn is_benchmarking(&self) -> bool { self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 } @@ -681,8 +688,9 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); /// ``` + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_multicast(&self) -> bool { + pub const fn is_multicast(&self) -> bool { self.octets()[0] >= 224 && self.octets()[0] <= 239 } @@ -727,8 +735,9 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); /// ``` + #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_documentation(&self) -> bool { + pub const fn is_documentation(&self) -> bool { match self.octets() { [192, 0, 2, _] => true, [198, 51, 100, _] => true, From ee9e48bafcc9667f08027e50ed84578e9861a456 Mon Sep 17 00:00:00 2001 From: CDirkx Date: Tue, 1 Sep 2020 19:50:01 +0200 Subject: [PATCH 2/4] Make methods unstable const under `const_ipv4` --- library/std/src/lib.rs | 1 + library/std/src/net/ip.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 0797585e3df3f..c330e87e0b84c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -239,6 +239,7 @@ #![feature(const_cstr_unchecked)] #![feature(const_fn_transmute)] #![feature(const_raw_ptr_deref)] +#![feature(const_ipv4)] #![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index c37323b1bc48a..ecaef11ef5a56 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -361,7 +361,7 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::new(127, 0, 0, 1); /// assert_eq!(addr.octets(), [127, 0, 0, 1]); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn octets(&self) -> [u8; 4] { // This returns the order we want because s_addr is stored in big-endian. @@ -405,7 +405,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 @@ -435,7 +435,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_private(&self) -> bool { match self.octets() { @@ -462,7 +462,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_link_local(&self) -> bool { match self.octets() { @@ -577,7 +577,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] pub const fn is_shared(&self) -> bool { self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) } @@ -610,7 +610,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] pub const fn is_ietf_protocol_assignment(&self) -> bool { self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 } @@ -634,7 +634,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] pub const fn is_benchmarking(&self) -> bool { self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 } @@ -688,7 +688,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_multicast(&self) -> bool { self.octets()[0] >= 224 && self.octets()[0] <= 239 @@ -735,7 +735,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.48.0")] + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_documentation(&self) -> bool { match self.octets() { From fb64e6dcf0a7ea0518c8f2d499327a2b6974f859 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Tue, 1 Sep 2020 21:58:35 +0200 Subject: [PATCH 3/4] Add test for `Ipv4Addr` methods in a const context --- src/test/ui/consts/std/net/ipv4.rs | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/test/ui/consts/std/net/ipv4.rs diff --git a/src/test/ui/consts/std/net/ipv4.rs b/src/test/ui/consts/std/net/ipv4.rs new file mode 100644 index 0000000000000..eca42f297e5ee --- /dev/null +++ b/src/test/ui/consts/std/net/ipv4.rs @@ -0,0 +1,41 @@ +// run-pass + +#![feature(ip)] +#![feature(const_ipv4)] + +use std::net::Ipv4Addr; + +fn main() { + const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); + assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST); + + const OCTETS: [u8; 4] = IP_ADDRESS.octets(); + assert_eq!(OCTETS, [127, 0, 0, 1]); + + const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified(); + assert!(!IS_UNSPECIFIED); + + const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback(); + assert!(IS_LOOPBACK); + + const IS_PRIVATE : bool = IP_ADDRESS.is_private(); + assert!(!IS_PRIVATE); + + const IS_LINK_LOCAL : bool = IP_ADDRESS.is_link_local(); + assert!(!IS_LINK_LOCAL); + + const IS_SHARED : bool = IP_ADDRESS.is_shared(); + assert!(!IS_SHARED); + + const IS_IETF_PROTOCOL_ASSIGNMENT : bool = IP_ADDRESS.is_ietf_protocol_assignment(); + assert!(!IS_IETF_PROTOCOL_ASSIGNMENT); + + const IS_BENCHMARKING : bool = IP_ADDRESS.is_benchmarking(); + assert!(!IS_BENCHMARKING); + + const IS_MULTICAST : bool = IP_ADDRESS.is_multicast(); + assert!(!IS_MULTICAST); + + const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation(); + assert!(!IS_DOCUMENTATION); +} From 0c77257e56a20a81f5b4e4452cae5e460ad30140 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Tue, 1 Sep 2020 23:55:17 +0200 Subject: [PATCH 4/4] Make all remaining methods of `std::net::Ipv4Addr` const Makes the following methods of `std::net::Ipv4Addr` unstable const under the `const_ipv4` feature: - `is_global` - `is_reserved` - `is_broadcast` - `to_ipv6_compatible` - `to_ipv6_mapped` This results in all methods of `Ipv4Addr` being const. Also adds tests for these methods in a const context. --- library/std/src/net/ip.rs | 29 ++++++++++++++++++++--------- src/test/ui/consts/std/net/ipv4.rs | 19 ++++++++++++++++++- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index ecaef11ef5a56..125fc8d3488d0 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -542,10 +542,13 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); /// ``` - pub fn is_global(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] + pub const fn is_global(&self) -> bool { // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two // globally routable addresses in the 192.0.0.0/24 range. - if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a { + if u32::from_be_bytes(self.octets()) == 0xc0000009 + || u32::from_be_bytes(self.octets()) == 0xc000000a + { return true; } !self.is_private() @@ -667,7 +670,8 @@ impl Ipv4Addr { /// // The broadcast address is not considered as reserved for future use by this implementation /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); /// ``` - pub fn is_reserved(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] + pub const fn is_reserved(&self) -> bool { self.octets()[0] & 240 == 240 && !self.is_broadcast() } @@ -709,9 +713,10 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_broadcast(&self) -> bool { - self == &Self::BROADCAST + pub const fn is_broadcast(&self) -> bool { + u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) } /// Returns [`true`] if this address is in a range designated for documentation. @@ -762,10 +767,13 @@ impl Ipv4Addr { /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767) /// ); /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(feature = "rust1", since = "1.0.0")] - pub fn to_ipv6_compatible(&self) -> Ipv6Addr { + pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { let [a, b, c, d] = self.octets(); - Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d]) + Ipv6Addr { + inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }, + } } /// Converts this address to an IPv4-mapped [`IPv6` address]. @@ -782,10 +790,13 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), /// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767)); /// ``` + #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[stable(feature = "rust1", since = "1.0.0")] - pub fn to_ipv6_mapped(&self) -> Ipv6Addr { + pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { let [a, b, c, d] = self.octets(); - Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d]) + Ipv6Addr { + inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }, + } } } diff --git a/src/test/ui/consts/std/net/ipv4.rs b/src/test/ui/consts/std/net/ipv4.rs index eca42f297e5ee..8c676999ae734 100644 --- a/src/test/ui/consts/std/net/ipv4.rs +++ b/src/test/ui/consts/std/net/ipv4.rs @@ -3,7 +3,7 @@ #![feature(ip)] #![feature(const_ipv4)] -use std::net::Ipv4Addr; +use std::net::{Ipv4Addr, Ipv6Addr}; fn main() { const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); @@ -24,6 +24,9 @@ fn main() { const IS_LINK_LOCAL : bool = IP_ADDRESS.is_link_local(); assert!(!IS_LINK_LOCAL); + const IS_GLOBAL : bool = IP_ADDRESS.is_global(); + assert!(!IS_GLOBAL); + const IS_SHARED : bool = IP_ADDRESS.is_shared(); assert!(!IS_SHARED); @@ -33,9 +36,23 @@ fn main() { const IS_BENCHMARKING : bool = IP_ADDRESS.is_benchmarking(); assert!(!IS_BENCHMARKING); + const IS_RESERVED : bool = IP_ADDRESS.is_reserved(); + assert!(!IS_RESERVED); + const IS_MULTICAST : bool = IP_ADDRESS.is_multicast(); assert!(!IS_MULTICAST); + const IS_BROADCAST : bool = IP_ADDRESS.is_broadcast(); + assert!(!IS_BROADCAST); + const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation(); assert!(!IS_DOCUMENTATION); + + const IP_V6_COMPATIBLE : Ipv6Addr = IP_ADDRESS.to_ipv6_compatible(); + assert_eq!(IP_V6_COMPATIBLE, + Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1])); + + const IP_V6_MAPPED : Ipv6Addr = IP_ADDRESS.to_ipv6_mapped(); + assert_eq!(IP_V6_MAPPED, + Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1])); }