From 4aae7814075ffe94486e2cc04ff5d08351eb8fd3 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sat, 29 Aug 2020 19:53:06 -0700 Subject: Add info about `!` and `impl Trait` --- library/std/src/primitive_docs.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 2339ca527bd..d88a9cbd0ac 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -194,14 +194,47 @@ mod prim_bool {} /// # `!` and traits /// /// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl` -/// which doesn't `panic!`. As it turns out, most traits can have an `impl` for `!`. Take [`Debug`] +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` cannot have +/// divergence, i.e., returning `!`, as their only possible code path. As an example, this code +/// doesn't compile: +/// +/// ```compile_fail +/// use core::ops::Add; +/// +/// fn foo() -> impl Add { +/// unimplemented!() +/// } +/// ``` +/// +/// While this code does: +/// +/// ``` +/// use core::ops::Add; +/// +/// fn foo() -> impl Add { +/// if true { +/// unimplemented!() +/// } else { +/// 0 +/// } +/// } +/// ``` +/// +/// The reason is that, in the first example, there are many possible types for `!` to coerce +/// to, because the function's return value is polymorphic. However, in the second example, the +/// other branch returns `0` which has a concrete type that `!` can be coerced to. See issue +/// [#36375] for more information on this quirk of `!`. +/// +/// [#36375]: https://github.com/rust-lang/rust/issues/36375 +/// +/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`] /// for example: /// /// ``` /// #![feature(never_type)] /// # use std::fmt; /// # trait Debug { -/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; +/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; /// # } /// impl Debug for ! { /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { -- cgit 1.4.1-3-g733a5 From fd985e29dd97f053f31a2e282fb59363f6b6db3f Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:35:58 -0700 Subject: cannot have divergence -> cannot diverge --- library/std/src/primitive_docs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index d88a9cbd0ac..a577a0a51c9 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -194,9 +194,9 @@ mod prim_bool {} /// # `!` and traits /// /// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl` -/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` cannot have -/// divergence, i.e., returning `!`, as their only possible code path. As an example, this code -/// doesn't compile: +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` cannot diverge, +/// i.e., returning `!`, as their only possible code path. As an example, this code doesn't +/// compile: /// /// ```compile_fail /// use core::ops::Add; -- cgit 1.4.1-3-g733a5 From 0d9a2abe698e84c8b3c473659db321606d7d5c02 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:41:36 -0700 Subject: It's only an issue without an `impl Trait for !` --- library/std/src/primitive_docs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index a577a0a51c9..df64287bc7d 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -194,9 +194,9 @@ mod prim_bool {} /// # `!` and traits /// /// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl` -/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` cannot diverge, -/// i.e., returning `!`, as their only possible code path. As an example, this code doesn't -/// compile: +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!` +/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other +/// words, they can't return `!` from every code path. As an example, this code doesn't compile: /// /// ```compile_fail /// use core::ops::Add; @@ -206,7 +206,7 @@ mod prim_bool {} /// } /// ``` /// -/// While this code does: +/// But this code does: /// /// ``` /// use core::ops::Add; -- cgit 1.4.1-3-g733a5 From 26eab6a0d51b9a023471210e35fdec969c662363 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:48:53 -0700 Subject: Specify `0` of type `u32` --- library/std/src/primitive_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index df64287bc7d..710d91b6ee7 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -222,8 +222,8 @@ mod prim_bool {} /// /// The reason is that, in the first example, there are many possible types for `!` to coerce /// to, because the function's return value is polymorphic. However, in the second example, the -/// other branch returns `0` which has a concrete type that `!` can be coerced to. See issue -/// [#36375] for more information on this quirk of `!`. +/// other branch returns a `0` of type `u32`, which is a concrete type that `!` can be coerced to. +/// See issue [#36375] for more information on this quirk of `!`. /// /// [#36375]: https://github.com/rust-lang/rust/issues/36375 /// -- cgit 1.4.1-3-g733a5 From 80dcad9e5b060ba6f9e06499c799423037ce7733 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:52:09 -0700 Subject: Be more specific about polymorphic return types I no longer say "polymorphic" since it's a bit ambiguous here. --- library/std/src/primitive_docs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 710d91b6ee7..fc5036a1893 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -220,10 +220,10 @@ mod prim_bool {} /// } /// ``` /// -/// The reason is that, in the first example, there are many possible types for `!` to coerce -/// to, because the function's return value is polymorphic. However, in the second example, the -/// other branch returns a `0` of type `u32`, which is a concrete type that `!` can be coerced to. -/// See issue [#36375] for more information on this quirk of `!`. +/// The reason is that, in the first example, there are many possible types that `!` could coerce +/// to, because the function can return one of many concrete types. However, in the second example, +/// the other branch returns a `0` of type `u32`, which is a concrete type that `!` can be coerced +/// to. See issue [#36375] for more information on this quirk of `!`. /// /// [#36375]: https://github.com/rust-lang/rust/issues/36375 /// -- cgit 1.4.1-3-g733a5 From bd3196282ba61ba284f4e176db3537f61b11892c Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:53:40 -0700 Subject: other branch -> `else` branch --- library/std/src/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index fc5036a1893..dfc026fb84f 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -222,7 +222,7 @@ mod prim_bool {} /// /// The reason is that, in the first example, there are many possible types that `!` could coerce /// to, because the function can return one of many concrete types. However, in the second example, -/// the other branch returns a `0` of type `u32`, which is a concrete type that `!` can be coerced +/// the `else` branch returns a `0` of type `u32`, which is a concrete type that `!` can be coerced /// to. See issue [#36375] for more information on this quirk of `!`. /// /// [#36375]: https://github.com/rust-lang/rust/issues/36375 -- cgit 1.4.1-3-g733a5 From 7e2548fe69ff5ec4e5e06c8c28351cbf2ebf7eee Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sun, 30 Aug 2020 11:39:45 -0700 Subject: Import `Debug` instead of redefining it --- library/std/src/primitive_docs.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index dfc026fb84f..0a0aa6785ed 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -232,10 +232,7 @@ mod prim_bool {} /// /// ``` /// #![feature(never_type)] -/// # use std::fmt; -/// # trait Debug { -/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; -/// # } +/// # use std::fmt::{self, Debug}; /// impl Debug for ! { /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// *self -- cgit 1.4.1-3-g733a5 From 37ea97cc10212711411e6dbb6b260e668b7ac2b5 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Sun, 30 Aug 2020 11:43:16 -0700 Subject: Explain why the `0` is a `u32` --- library/std/src/primitive_docs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 0a0aa6785ed..79621d46f0e 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -222,8 +222,9 @@ mod prim_bool {} /// /// The reason is that, in the first example, there are many possible types that `!` could coerce /// to, because the function can return one of many concrete types. However, in the second example, -/// the `else` branch returns a `0` of type `u32`, which is a concrete type that `!` can be coerced -/// to. See issue [#36375] for more information on this quirk of `!`. +/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type +/// `u32`, which is a concrete type that `!` can be coerced to. See issue [#36375] for more +/// information on this quirk of `!`. /// /// [#36375]: https://github.com/rust-lang/rust/issues/36375 /// -- cgit 1.4.1-3-g733a5 From e13a70122d380579840cec13d151870495f776ac Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 31 Aug 2020 16:32:56 -0700 Subject: Redefine `Debug` instead of importing it This reverts commit 7e2548fe69ff5ec4e5e06c8c28351cbf2ebf7eee. Now I know why it was redefined: it seems like it's potentially because of the orphan rule. Here are the error messages: error[E0119]: conflicting implementations of trait `std::fmt::Debug` for type `!`: --> src/primitive_docs.rs:236:1 | 6 | impl Debug for ! { | ^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - impl std::fmt::Debug for !; error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> src/primitive_docs.rs:236:1 | 6 | impl Debug for ! { | ^^^^^^^^^^^^^^^- | | | | | `!` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead --- library/std/src/primitive_docs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 79621d46f0e..4525d8a543a 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -233,7 +233,10 @@ mod prim_bool {} /// /// ``` /// #![feature(never_type)] -/// # use std::fmt::{self, Debug}; +/// # use std::fmt; +/// # trait Debug { +/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; +/// # } /// impl Debug for ! { /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { /// *self -- cgit 1.4.1-3-g733a5 From cdd6f110125971a0d7ab1457c0ea7eb30304d5f3 Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 31 Aug 2020 16:35:00 -0700 Subject: Remove empty comment --- library/std/src/primitive_docs.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 4525d8a543a..cba39c3eb14 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1,7 +1,6 @@ #[doc(primitive = "bool")] #[doc(alias = "true")] #[doc(alias = "false")] -// /// The boolean type. /// /// The `bool` represents a value, which could only be either `true` or `false`. If you cast -- cgit 1.4.1-3-g733a5 From c4c058c7167c44eacbc2f7734619c26d68eb1426 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:30:03 -0700 Subject: Improve wording Co-authored-by: Joshua Nelson --- library/std/src/primitive_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index cba39c3eb14..2ca86a42bff 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -220,9 +220,9 @@ mod prim_bool {} /// ``` /// /// The reason is that, in the first example, there are many possible types that `!` could coerce -/// to, because the function can return one of many concrete types. However, in the second example, +/// to, because many types implement `Add`. However, in the second example, /// the `else` branch returns a `0`, which the compiler infers from the return type to be of type -/// `u32`, which is a concrete type that `!` can be coerced to. See issue [#36375] for more +/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375] for more /// information on this quirk of `!`. /// /// [#36375]: https://github.com/rust-lang/rust/issues/36375 -- cgit 1.4.1-3-g733a5 From 913354b8463a82497ebe586cfb9f5a4a218767ad Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:41:27 -0700 Subject: Improve `assert!` section in `bool` docs --- library/std/src/primitive_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 2ca86a42bff..682ca3068ee 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -11,8 +11,8 @@ /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc., /// which allow us to perform boolean operations using `&`, `|` and `!`. /// -/// `if` always demands a `bool` value. [`assert!`], being an important macro in testing, -/// checks whether an expression returns `true`. +/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing, +/// checks whether an expression returns `true` and panics if it isn't. /// /// ``` /// let bool_val = true & false | false; -- cgit 1.4.1-3-g733a5 From 55637f566993e2f8659aa09288bfc00b9965c524 Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:44:21 -0700 Subject: Break line at 100 characters --- library/std/src/primitive_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 682ca3068ee..d00824cfb3e 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -222,8 +222,8 @@ mod prim_bool {} /// The reason is that, in the first example, there are many possible types that `!` could coerce /// to, because many types implement `Add`. However, in the second example, /// the `else` branch returns a `0`, which the compiler infers from the return type to be of type -/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375] for more -/// information on this quirk of `!`. +/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375] +/// for more information on this quirk of `!`. /// /// [#36375]: https://github.com/rust-lang/rust/issues/36375 /// -- cgit 1.4.1-3-g733a5 From b31cc8f83e7f50f54bffa93e909d51cdabf9f5fa Mon Sep 17 00:00:00 2001 From: CDirkx Date: Tue, 1 Sep 2020 19:00:20 +0200 Subject: 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` Changed the implementation of `is_unspecified` and `is_loopback` to use a `match` instead of `==`. Part of #76205 --- library/std/src/lib.rs | 1 + library/std/src/net/ip.rs | 46 ++++++++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 16 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 0797585e3df..3141b3b9526 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -238,6 +238,7 @@ #![feature(concat_idents)] #![feature(const_cstr_unchecked)] #![feature(const_fn_transmute)] +#![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] #![feature(container_error_extra)] #![feature(core_intrinsics)] diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 10676b49d43..8e3dbf8fcb4 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1102,8 +1102,9 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(feature = "rust1", since = "1.0.0")] - pub fn segments(&self) -> [u16; 8] { + pub const fn segments(&self) -> [u16; 8] { // All elements in `s6_addr` must be big endian. // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) }; @@ -1135,9 +1136,10 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_unspecified(&self) -> bool { - self.segments() == [0, 0, 0, 0, 0, 0, 0, 0] + pub const fn is_unspecified(&self) -> bool { + matches!(self.segments(), [0, 0, 0, 0, 0, 0, 0, 0]) } /// Returns [`true`] if this is a loopback address (::1). @@ -1155,9 +1157,10 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_loopback(&self) -> bool { - self.segments() == [0, 0, 0, 0, 0, 0, 0, 1] + pub const fn is_loopback(&self) -> bool { + matches!(self.segments(), [0, 0, 0, 0, 0, 0, 0, 1]) } /// Returns [`true`] if the address appears to be globally routable. @@ -1182,7 +1185,8 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); /// ``` - pub fn is_global(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_global(&self) -> bool { match self.multicast_scope() { Some(Ipv6MulticastScope::Global) => true, None => self.is_unicast_global(), @@ -1208,7 +1212,8 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); /// ``` - pub fn is_unique_local(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 } @@ -1263,7 +1268,8 @@ impl Ipv6Addr { /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 - pub fn is_unicast_link_local_strict(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_unicast_link_local_strict(&self) -> bool { (self.segments()[0] & 0xffff) == 0xfe80 && (self.segments()[1] & 0xffff) == 0 && (self.segments()[2] & 0xffff) == 0 @@ -1320,7 +1326,8 @@ impl Ipv6Addr { /// /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 - pub fn is_unicast_link_local(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } @@ -1359,7 +1366,8 @@ impl Ipv6Addr { /// addresses. /// /// [RFC 3879]: https://tools.ietf.org/html/rfc3879 - pub fn is_unicast_site_local(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_unicast_site_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfec0 } @@ -1381,7 +1389,8 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); /// ``` - pub fn is_documentation(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) } @@ -1416,7 +1425,8 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); /// ``` - pub fn is_unicast_global(&self) -> bool { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn is_unicast_global(&self) -> bool { !self.is_multicast() && !self.is_loopback() && !self.is_unicast_link_local() @@ -1440,7 +1450,8 @@ impl Ipv6Addr { /// ); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); /// ``` - pub fn multicast_scope(&self) -> Option { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn multicast_scope(&self) -> Option { if self.is_multicast() { match self.segments()[0] & 0x000f { 1 => Some(Ipv6MulticastScope::InterfaceLocal), @@ -1472,8 +1483,9 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] - pub fn is_multicast(&self) -> bool { + pub const fn is_multicast(&self) -> bool { (self.segments()[0] & 0xff00) == 0xff00 } @@ -1498,7 +1510,8 @@ 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); /// ``` - pub fn to_ipv4_mapped(&self) -> Option { + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + pub const fn to_ipv4_mapped(&self) -> Option { match self.octets() { [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { Some(Ipv4Addr::new(a, b, c, d)) @@ -1525,8 +1538,9 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), /// Some(Ipv4Addr::new(0, 0, 0, 1))); /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(feature = "rust1", since = "1.0.0")] - pub fn to_ipv4(&self) -> Option { + pub const fn to_ipv4(&self) -> Option { if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { let [a, b] = ab.to_be_bytes(); let [c, d] = cd.to_be_bytes(); -- cgit 1.4.1-3-g733a5 From a43dd4f4014af0f70c032eb23c5cbf4c2829b7c8 Mon Sep 17 00:00:00 2001 From: CDirkx Date: Tue, 1 Sep 2020 21:05:26 +0200 Subject: Change implementation of `Ipv6Addr::is_unspecified` and `is_loopback` from `matches!` to `u128` comparison Done because `matches!` doesn't optimize well with array comparisons --- library/std/src/net/ip.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 8e3dbf8fcb4..341a112df71 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1139,7 +1139,7 @@ impl Ipv6Addr { #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_unspecified(&self) -> bool { - matches!(self.segments(), [0, 0, 0, 0, 0, 0, 0, 0]) + u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) } /// Returns [`true`] if this is a loopback address (::1). @@ -1160,7 +1160,7 @@ impl Ipv6Addr { #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[stable(since = "1.7.0", feature = "ip_17")] pub const fn is_loopback(&self) -> bool { - matches!(self.segments(), [0, 0, 0, 0, 0, 0, 0, 1]) + u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) } /// Returns [`true`] if the address appears to be globally routable. -- cgit 1.4.1-3-g733a5