From fcf1571e162fd38014d27a35077ba40e127b432c Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 19 Jul 2020 20:57:04 +0200 Subject: [PATCH 01/23] Add Atomic*::from_mut. The atomic equivalent of Cell::from_mut. --- library/core/src/sync/atomic.rs | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index f31a4a0b7518d..0d2adbb0f8435 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -358,6 +358,26 @@ impl AtomicBool { unsafe { &mut *(self.v.get() as *mut bool) } } + /// Get atomic access to a `&mut bool`. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bool = true; + /// let a = AtomicBool::from_mut(&mut some_bool); + /// a.store(false, Ordering::Relaxed); + /// assert_eq!(some_bool, false); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "none")] + pub fn from_mut(v: &mut bool) -> &Self { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &*(v as *mut bool as *mut Self) } + } + /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are @@ -914,6 +934,26 @@ impl AtomicPtr { unsafe { &mut *self.p.get() } } + /// Get atomic access to a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut)] + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut some_ptr = &mut 123 as *mut i32; + /// let a = AtomicPtr::from_mut(&mut some_ptr); + /// a.store(&mut 456, Ordering::Relaxed); + /// assert_eq!(unsafe { *some_ptr }, 456); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "none")] + pub fn from_mut(v: &mut *mut T) -> &Self { + // SAFETY: the mutable reference guarantees unique ownership, + unsafe { &*(v as *mut *mut T as *mut Self) } + } + /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are @@ -1358,6 +1398,29 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5); } } + doc_comment! { + concat!("Get atomic access to a `&mut ", stringify!($int_type), "`. + +# Examples + +``` +#![feature(atomic_from_mut)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let mut some_int = 123; +let a = ", stringify!($atomic_type), "::from_mut(&mut some_int); +a.store(100, Ordering::Relaxed); +assert_eq!(some_int, 100); +``` + "), + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "none")] + pub fn from_mut(v: &mut $int_type) -> &Self { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &*(v as *mut $int_type as *mut Self) } + } + } + doc_comment! { concat!("Consumes the atomic and returns the contained value. From 09fff5fa43e1e19b2848714faa814f9bb78e119a Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 13 Aug 2020 20:52:21 +0200 Subject: [PATCH 02/23] Disable Atomic*::from_mut when alignment is wrong. --- library/core/src/sync/atomic.rs | 39 +++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 0d2adbb0f8435..2cdb4f16c024a 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -121,6 +121,7 @@ use self::Ordering::*; use crate::cell::UnsafeCell; use crate::fmt; use crate::intrinsics; +use crate::mem::align_of; use crate::hint::spin_loop; @@ -374,7 +375,8 @@ impl AtomicBool { #[inline] #[unstable(feature = "atomic_from_mut", issue = "none")] pub fn from_mut(v: &mut bool) -> &Self { - // SAFETY: the mutable reference guarantees unique ownership. + // SAFETY: the mutable reference guarantees unique ownership, and + // alignment of both `bool` and `Self` is 1. unsafe { &*(v as *mut bool as *mut Self) } } @@ -950,7 +952,11 @@ impl AtomicPtr { #[inline] #[unstable(feature = "atomic_from_mut", issue = "none")] pub fn from_mut(v: &mut *mut T) -> &Self { - // SAFETY: the mutable reference guarantees unique ownership, + let [] = [(); align_of::() - align_of::<*mut T>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `*mut T` and `Self` is the same on all platforms + // supported by rust, as verified above. unsafe { &*(v as *mut *mut T as *mut Self) } } @@ -1276,6 +1282,12 @@ impl From<*mut T> for AtomicPtr { } } +macro_rules! if_not_8_bit { + (u8, $($tt:tt)*) => { "" }; + (i8, $($tt:tt)*) => { "" }; + ($_:ident, $($tt:tt)*) => { $($tt)* }; +} + #[cfg(target_has_atomic_load_store = "8")] macro_rules! atomic_int { ($cfg_cas:meta, @@ -1287,7 +1299,8 @@ macro_rules! atomic_int { $stable_nand:meta, $const_stable:meta, $stable_init_const:meta, - $s_int_type:expr, $int_ref:expr, + $(from_mut: cfg($from_mut_cfg:meta),)? + $s_int_type:literal, $int_ref:expr, $extra_feature:expr, $min_fn:ident, $max_fn:ident, $align:expr, @@ -1401,6 +1414,16 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5); doc_comment! { concat!("Get atomic access to a `&mut ", stringify!($int_type), "`. +", +if_not_8_bit! { + $int_type, + concat!( + "**Note:** This function is only available on targets where `", + stringify!($int_type), "` has an alignment of ", $align, " bytes." + ) +}, +" + # Examples ``` @@ -1414,9 +1437,15 @@ assert_eq!(some_int, 100); ``` "), #[inline] + $(#[cfg($from_mut_cfg)])? #[unstable(feature = "atomic_from_mut", issue = "none")] pub fn from_mut(v: &mut $int_type) -> &Self { - // SAFETY: the mutable reference guarantees unique ownership. + let [] = [(); align_of::() - align_of::<$int_type>()]; + // SAFETY: + // - the mutable reference guarantees unique ownership. + // - the alignment of `$int_type` and `Self` is the + // same on all platforms enabled by `$from_mut_cfg` + // as verified above. unsafe { &*(v as *mut $int_type as *mut Self) } } } @@ -2265,6 +2294,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86")), "i64", "../../../std/primitive.i64.html", "", atomic_min, atomic_max, @@ -2283,6 +2313,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), + from_mut: cfg(not(target_arch = "x86")), "u64", "../../../std/primitive.u64.html", "", atomic_umin, atomic_umax, From 814245779c7e5f3cda80c0befb841bbf8700ca6f Mon Sep 17 00:00:00 2001 From: Arkadiusz Piekarz Date: Mon, 31 Aug 2020 14:38:15 +0200 Subject: [PATCH 03/23] Update tracking issue for const_caller_location --- library/core/src/intrinsics.rs | 2 +- library/core/src/panic.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 25951e2f58235..dd9af2d07e770 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -831,7 +831,7 @@ extern "rust-intrinsic" { /// Gets a reference to a static `Location` indicating where it was called. /// /// Consider using [`crate::panic::Location::caller`] instead. - #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] + #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] pub fn caller_location() -> &'static crate::panic::Location<'static>; /// Moves a value out of scope without running drop glue. diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 316ecafe572c5..4a70dec3c6cf8 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -232,7 +232,7 @@ impl<'a> Location<'a> { /// assert_ne!(this_location.column(), another_location.column()); /// ``` #[stable(feature = "track_caller", since = "1.46.0")] - #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] + #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] #[track_caller] pub const fn caller() -> &'static Location<'static> { crate::intrinsics::caller_location() From 8783c62f0c8641ef56094fae13e2fed193b60d1f Mon Sep 17 00:00:00 2001 From: Camelid <37223377+camelid@users.noreply.github.com> Date: Tue, 1 Sep 2020 17:48:15 -0700 Subject: [PATCH 04/23] Add missing link in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a7e23d8ac2caa..6cf9577d3330e 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,8 @@ The Rust community congregates in a few places: If you are interested in contributing to the Rust project, please take a look at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide]. +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org + ## License Rust is primarily distributed under the terms of both the MIT license From 3e29fdb0fb3be5a35d3e2d55d902be8b4ecbe7bb Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 3 Sep 2020 01:37:40 -0400 Subject: [PATCH 05/23] Remove a number of vec UI tests, make them unit tests in the alloc library --- library/alloc/tests/vec.rs | 53 +++++++++++++++++++++++ src/test/ui/array-slice-vec/vec-concat.rs | 14 ------ src/test/ui/array-slice-vec/vec-growth.rs | 16 ------- src/test/ui/array-slice-vec/vec-push.rs | 3 -- src/test/ui/array-slice-vec/vec-slice.rs | 9 ---- src/test/ui/array-slice-vec/vec-to_str.rs | 5 --- src/test/ui/array-slice-vec/vec.rs | 15 ------- 7 files changed, 53 insertions(+), 62 deletions(-) delete mode 100644 src/test/ui/array-slice-vec/vec-concat.rs delete mode 100644 src/test/ui/array-slice-vec/vec-growth.rs delete mode 100644 src/test/ui/array-slice-vec/vec-push.rs delete mode 100644 src/test/ui/array-slice-vec/vec-slice.rs delete mode 100644 src/test/ui/array-slice-vec/vec.rs diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ffff543b07fe5..b422960c19982 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -72,6 +72,39 @@ fn test_zst_capacity() { assert_eq!(Vec::<()>::new().capacity(), usize::MAX); } +#[test] +fn test_indexing() { + let v: Vec = vec![10, 20]; + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); + let mut x: usize = 0; + assert_eq!(v[x], 10); + assert_eq!(v[x + 1], 20); + x = x + 1; + assert_eq!(v[x], 20); + assert_eq!(v[x - 1], 10); +} + +#[test] +fn test_debug_fmt() { + let vec1: Vec = vec![]; + assert_eq!("[]", format!("{:?}", vec1)); + + let vec2 = vec![0, 1]; + assert_eq!("[0, 1]", format!("{:?}", vec2)); +} + +#[test] +fn test_push() { + let mut v = vec![]; + v.push(1); + assert_eq!(v, [1]); + v.push(2); + assert_eq!(v, [1, 2]); + v.push(3); + assert_eq!(v, [1, 2, 3]); +} + #[test] fn test_extend() { let mut v = Vec::new(); @@ -117,6 +150,18 @@ fn test_extend() { assert_eq!(count_x, 1); } +#[test] +fn test_extend_from_slice() { + let a: Vec = vec![1, 2, 3, 4, 5]; + let b: Vec = vec![6, 7, 8, 9, 0]; + + let mut v: Vec = a; + + v.extend_from_slice(&b); + + assert_eq!(v, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); +} + #[test] fn test_extend_ref() { let mut v = vec![1, 2]; @@ -132,6 +177,14 @@ fn test_extend_ref() { assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]); } +#[test] +fn test_slice_from_ref() { + let values = vec![1, 2, 3, 4, 5]; + let slice = &values[1..3]; + + assert_eq!(slice, [2, 3]); +} + #[test] fn test_slice_from_mut() { let mut values = vec![1, 2, 3, 4, 5]; diff --git a/src/test/ui/array-slice-vec/vec-concat.rs b/src/test/ui/array-slice-vec/vec-concat.rs deleted file mode 100644 index 1f493679b7947..0000000000000 --- a/src/test/ui/array-slice-vec/vec-concat.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-pass - -use std::vec; - -pub fn main() { - let a: Vec = vec![1, 2, 3, 4, 5]; - let b: Vec = vec![6, 7, 8, 9, 0]; - let mut v: Vec = a; - v.extend_from_slice(&b); - println!("{}", v[9]); - assert_eq!(v[0], 1); - assert_eq!(v[7], 8); - assert_eq!(v[9], 0); -} diff --git a/src/test/ui/array-slice-vec/vec-growth.rs b/src/test/ui/array-slice-vec/vec-growth.rs deleted file mode 100644 index b09f08bb85a82..0000000000000 --- a/src/test/ui/array-slice-vec/vec-growth.rs +++ /dev/null @@ -1,16 +0,0 @@ -// run-pass - - - -pub fn main() { - let mut v = vec![1]; - v.push(2); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - assert_eq!(v[2], 3); - assert_eq!(v[3], 4); - assert_eq!(v[4], 5); -} diff --git a/src/test/ui/array-slice-vec/vec-push.rs b/src/test/ui/array-slice-vec/vec-push.rs deleted file mode 100644 index 466ab3fab1cab..0000000000000 --- a/src/test/ui/array-slice-vec/vec-push.rs +++ /dev/null @@ -1,3 +0,0 @@ -// run-pass - -pub fn main() { let mut v = vec![1, 2, 3]; v.push(1); } diff --git a/src/test/ui/array-slice-vec/vec-slice.rs b/src/test/ui/array-slice-vec/vec-slice.rs deleted file mode 100644 index 1f090ddd9c97d..0000000000000 --- a/src/test/ui/array-slice-vec/vec-slice.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass - - -pub fn main() { - let v = vec![1,2,3,4,5]; - let v2 = &v[1..3]; - assert_eq!(v2[0], 2); - assert_eq!(v2[1], 3); -} diff --git a/src/test/ui/array-slice-vec/vec-to_str.rs b/src/test/ui/array-slice-vec/vec-to_str.rs index a11cfc8e9b5c9..fbff19b862283 100644 --- a/src/test/ui/array-slice-vec/vec-to_str.rs +++ b/src/test/ui/array-slice-vec/vec-to_str.rs @@ -2,11 +2,6 @@ pub fn main() { - assert_eq!(format!("{:?}", vec![0, 1]), "[0, 1]".to_string()); - - let foo = vec![3, 4]; let bar: &[isize] = &[4, 5]; - - assert_eq!(format!("{:?}", foo), "[3, 4]"); assert_eq!(format!("{:?}", bar), "[4, 5]"); } diff --git a/src/test/ui/array-slice-vec/vec.rs b/src/test/ui/array-slice-vec/vec.rs deleted file mode 100644 index e76c1ab440e6e..0000000000000 --- a/src/test/ui/array-slice-vec/vec.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - - - -pub fn main() { - let v: Vec = vec![10, 20]; - assert_eq!(v[0], 10); - assert_eq!(v[1], 20); - let mut x: usize = 0; - assert_eq!(v[x], 10); - assert_eq!(v[x + 1], 20); - x = x + 1; - assert_eq!(v[x], 20); - assert_eq!(v[x - 1], 10); -} From 791f93c796f7b4f0346eee276baf6e31ed3c81ea Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 2 Sep 2020 23:39:50 -0700 Subject: [PATCH 06/23] Allow try blocks as the argument to return expressions Fixes 76271 --- compiler/rustc_ast/src/token.rs | 1 + src/test/ui/try-block/try-block-in-return.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/ui/try-block/try-block-in-return.rs diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index c6cc890b47f79..f3da0ec130a52 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -173,6 +173,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool { kw::Move, kw::Return, kw::True, + kw::Try, kw::Unsafe, kw::While, kw::Yield, diff --git a/src/test/ui/try-block/try-block-in-return.rs b/src/test/ui/try-block/try-block-in-return.rs new file mode 100644 index 0000000000000..a15bfeef1c12d --- /dev/null +++ b/src/test/ui/try-block/try-block-in-return.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn issue_76271() -> Option { + return try { 4 } +} + +fn main() { + assert_eq!(issue_76271(), Some(4)); +} From 2278c7255a1423b12d0efee3de43b23fa0d5b892 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 3 Sep 2020 15:43:07 -0400 Subject: [PATCH 07/23] Remove vec-to_str.rs, merge the remaining test in with vec --- library/alloc/tests/vec.rs | 3 +++ src/test/ui/array-slice-vec/vec-to_str.rs | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 src/test/ui/array-slice-vec/vec-to_str.rs diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index b422960c19982..f1c6af46d3103 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -92,6 +92,9 @@ fn test_debug_fmt() { let vec2 = vec![0, 1]; assert_eq!("[0, 1]", format!("{:?}", vec2)); + + let slice: &[isize] = &[4, 5]; + assert_eq!("[4, 5]", format!("{:?}", slice)); } #[test] diff --git a/src/test/ui/array-slice-vec/vec-to_str.rs b/src/test/ui/array-slice-vec/vec-to_str.rs deleted file mode 100644 index fbff19b862283..0000000000000 --- a/src/test/ui/array-slice-vec/vec-to_str.rs +++ /dev/null @@ -1,7 +0,0 @@ -// run-pass - - -pub fn main() { - let bar: &[isize] = &[4, 5]; - assert_eq!(format!("{:?}", bar), "[4, 5]"); -} From a2e077e405f9538b42d32e18082d50d0102d2334 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Thu, 3 Sep 2020 23:17:21 +0200 Subject: [PATCH 08/23] Make `Ipv4Addr` and `Ipv6Addr` const tests unit tests under `library` These tests are about the standard library, not the compiler itself, thus should live in `library`, see #76268. --- library/std/src/net/ip/tests.rs | 109 +++++++++++++++++++++++++++++ src/test/ui/consts/std/net/ipv4.rs | 58 --------------- src/test/ui/consts/std/net/ipv6.rs | 53 -------------- 3 files changed, 109 insertions(+), 111 deletions(-) delete mode 100644 src/test/ui/consts/std/net/ipv4.rs delete mode 100644 src/test/ui/consts/std/net/ipv6.rs diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index a2fba4b4cca95..76a0ae8b9454d 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -809,3 +809,112 @@ fn is_v6() { assert!(!ip.is_ipv4()); assert!(ip.is_ipv6()); } + +#[test] +fn ipv4_const() { + // test that the methods of `Ipv4Addr` are usable in a const context + + 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_GLOBAL: bool = IP_ADDRESS.is_global(); + assert!(!IS_GLOBAL); + + 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_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]) + ); +} + +#[test] +fn ipv6_const() { + // test that the methods of `Ipv6Addr` are usable in a const context + + const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST); + + const SEGMENTS: [u16; 8] = IP_ADDRESS.segments(); + assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]); + + const OCTETS: [u8; 16] = IP_ADDRESS.octets(); + assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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_GLOBAL: bool = IP_ADDRESS.is_global(); + assert!(!IS_GLOBAL); + + const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local(); + assert!(!IS_UNIQUE_LOCAL); + + const IS_UNICAST_LINK_LOCAL_STRICT: bool = IP_ADDRESS.is_unicast_link_local_strict(); + assert!(!IS_UNICAST_LINK_LOCAL_STRICT); + + const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local(); + assert!(!IS_UNICAST_LINK_LOCAL); + + const IS_UNICAST_SITE_LOCAL: bool = IP_ADDRESS.is_unicast_site_local(); + assert!(!IS_UNICAST_SITE_LOCAL); + + const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); + assert!(!IS_DOCUMENTATION); + + const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global(); + assert!(!IS_UNICAST_GLOBAL); + + const MULTICAST_SCOPE: Option = IP_ADDRESS.multicast_scope(); + assert_eq!(MULTICAST_SCOPE, None); + + const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); + assert!(!IS_MULTICAST); + + const IP_V4: Option = IP_ADDRESS.to_ipv4(); + assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1)); +} diff --git a/src/test/ui/consts/std/net/ipv4.rs b/src/test/ui/consts/std/net/ipv4.rs deleted file mode 100644 index 8c676999ae734..0000000000000 --- a/src/test/ui/consts/std/net/ipv4.rs +++ /dev/null @@ -1,58 +0,0 @@ -// run-pass - -#![feature(ip)] -#![feature(const_ipv4)] - -use std::net::{Ipv4Addr, Ipv6Addr}; - -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_GLOBAL : bool = IP_ADDRESS.is_global(); - assert!(!IS_GLOBAL); - - 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_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])); -} diff --git a/src/test/ui/consts/std/net/ipv6.rs b/src/test/ui/consts/std/net/ipv6.rs deleted file mode 100644 index e3841c38c2231..0000000000000 --- a/src/test/ui/consts/std/net/ipv6.rs +++ /dev/null @@ -1,53 +0,0 @@ -// run-pass - -#![feature(ip)] -#![feature(const_ipv6)] - -use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; - -fn main() { - const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); - assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST); - - const SEGMENTS : [u16; 8] = IP_ADDRESS.segments(); - assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]); - - const OCTETS : [u8; 16] = IP_ADDRESS.octets(); - assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,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_GLOBAL : bool = IP_ADDRESS.is_global(); - assert!(!IS_GLOBAL); - - const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local(); - assert!(!IS_UNIQUE_LOCAL); - - const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict(); - assert!(!IS_UNICAST_LINK_LOCAL_STRICT); - - const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local(); - assert!(!IS_UNICAST_LINK_LOCAL); - - const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local(); - assert!(!IS_UNICAST_SITE_LOCAL); - - const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation(); - assert!(!IS_DOCUMENTATION); - - const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global(); - assert!(!IS_UNICAST_GLOBAL); - - const MULTICAST_SCOPE : Option = IP_ADDRESS.multicast_scope(); - assert_eq!(MULTICAST_SCOPE, None); - - const IS_MULTICAST : bool = IP_ADDRESS.is_multicast(); - assert!(!IS_MULTICAST); - - const IP_V4 : Option = IP_ADDRESS.to_ipv4(); - assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1)); -} From 8c93125c17aeb9e9252054d4ddd0095ff4e60a2e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 3 Sep 2020 18:03:33 -0400 Subject: [PATCH 09/23] Address review comments on `Peekable::next_if` --- library/core/src/iter/adapters/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index f32c3963abea2..46dc77ba35c1a 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1628,7 +1628,7 @@ impl Peekable { self.peeked.get_or_insert_with(|| iter.next()).as_ref() } - /// Consume the next value of this iterator if a condition is true. + /// Consume and return the next value of this iterator if a condition is true. /// /// If `func` returns `true` for the next value of this iterator, consume and return it. /// Otherwise, return `None`. @@ -1668,7 +1668,7 @@ impl Peekable { } } - /// Consume the next item if it is equal to `expected`. + /// Consume and return the next item if it is equal to `expected`. /// /// # Example /// Consume a number if it's equal to 0. @@ -1683,10 +1683,10 @@ impl Peekable { /// assert_eq!(iter.next(), Some(1)); /// ``` #[unstable(feature = "peekable_next_if", issue = "72480")] - pub fn next_if_eq(&mut self, expected: &R) -> Option + pub fn next_if_eq(&mut self, expected: &T) -> Option where - R: ?Sized, - I::Item: PartialEq, + T: ?Sized, + I::Item: PartialEq, { self.next_if(|next| next == expected) } From 7b823df489e89d0ba3f6acd1cb788d3d8fbbf1e7 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 3 Sep 2020 18:08:25 -0400 Subject: [PATCH 10/23] Link to `#capacity-and-reallocation` when using with_capacity --- library/alloc/src/vec.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 27eefb0584216..a9215eb2dbc1b 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -119,6 +119,9 @@ use crate::raw_vec::RawVec; /// assert_eq!(vec, [0, 0, 0, 0, 0]); /// ``` /// +/// For more information, see +/// [Capacity and Reallocation](#capacity-and-reallocation). +/// /// Use a `Vec` as an efficient stack: /// /// ``` From 538e198193451e680cc95b66c82baac3ac687c8c Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Fri, 4 Sep 2020 02:35:27 +0200 Subject: [PATCH 11/23] Move various ui const tests to `library` Move: - `src\test\ui\consts\const-nonzero.rs` to `library\core` - `src\test\ui\consts\ascii.rs` to `library\core` - `src\test\ui\consts\cow-is-borrowed` to `library\alloc` Part of #76268 --- library/alloc/tests/borrow.rs | 13 +++++++++++++ library/alloc/tests/lib.rs | 1 + library/core/tests/ascii.rs | 11 +++++++++++ library/core/tests/nonzero.rs | 17 +++++++++++++++++ src/test/ui/consts/const-nonzero.rs | 16 ---------------- src/test/ui/consts/cow-is-borrowed.rs | 15 --------------- src/test/ui/consts/is_ascii.rs | 15 --------------- 7 files changed, 42 insertions(+), 46 deletions(-) delete mode 100644 src/test/ui/consts/const-nonzero.rs delete mode 100644 src/test/ui/consts/cow-is-borrowed.rs delete mode 100644 src/test/ui/consts/is_ascii.rs diff --git a/library/alloc/tests/borrow.rs b/library/alloc/tests/borrow.rs index 8bfcf323f674a..57976aa6cdfdf 100644 --- a/library/alloc/tests/borrow.rs +++ b/library/alloc/tests/borrow.rs @@ -45,3 +45,16 @@ fn test_from_cow_path() { let path = Path::new("hello"); test_from_cow!(path: &Path); } + +#[test] +fn cow_const() { + // test that the methods of `Cow` are usable in a const context + + const COW: Cow<'_, str> = Cow::Borrowed("moo"); + + const IS_BORROWED: bool = COW.is_borrowed(); + assert!(IS_BORROWED); + + const IS_OWNED: bool = COW.is_owned(); + assert!(!IS_OWNED); +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index b1513d1b05655..590639d983481 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -1,5 +1,6 @@ #![feature(allocator_api)] #![feature(box_syntax)] +#![feature(cow_is_borrowed)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(new_uninit)] diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index 0b97508394789..3244bbc2d670d 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -397,3 +397,14 @@ fn test_is_ascii_align_size_thoroughly() { } } } + +#[test] +fn ascii_const() { + // test that the `is_ascii` methods of `char` and `u8` are usable in a const context + + const CHAR_IS_ASCII: bool = 'a'.is_ascii(); + assert!(CHAR_IS_ASCII); + + const BYTE_IS_ASCII: bool = 97u8.is_ascii(); + assert!(BYTE_IS_ASCII); +} diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index 48aec6d718d3d..825e5e63b59bc 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -195,3 +195,20 @@ fn test_nonzero_from_int_on_err() { assert!(NonZeroI8::try_from(0).is_err()); assert!(NonZeroI32::try_from(0).is_err()); } + +#[test] +fn nonzero_const() { + // test that the methods of `NonZeroX>` are usable in a const context + // Note: only tests NonZero8 + + const NONZERO: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; + + const GET: u8 = NONZERO.get(); + assert_eq!(GET, 5); + + const ZERO: Option = NonZeroU8::new(0); + assert!(ZERO.is_none()); + + const ONE: Option = NonZeroU8::new(1); + assert!(ONE.is_some()); +} diff --git a/src/test/ui/consts/const-nonzero.rs b/src/test/ui/consts/const-nonzero.rs deleted file mode 100644 index cf6f8c8d69a26..0000000000000 --- a/src/test/ui/consts/const-nonzero.rs +++ /dev/null @@ -1,16 +0,0 @@ -// run-pass - -use std::num::NonZeroU8; - -const X: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; -const Y: u8 = X.get(); - -const ZERO: Option = NonZeroU8::new(0); -const ONE: Option = NonZeroU8::new(1); - -fn main() { - assert_eq!(Y, 5); - - assert!(ZERO.is_none()); - assert_eq!(ONE.unwrap().get(), 1); -} diff --git a/src/test/ui/consts/cow-is-borrowed.rs b/src/test/ui/consts/cow-is-borrowed.rs deleted file mode 100644 index adebe20f5a255..0000000000000 --- a/src/test/ui/consts/cow-is-borrowed.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -#![feature(cow_is_borrowed)] - -use std::borrow::Cow; - -fn main() { - const COW: Cow = Cow::Borrowed("moo"); - - const IS_BORROWED: bool = COW.is_borrowed(); - assert!(IS_BORROWED); - - const IS_OWNED: bool = COW.is_owned(); - assert!(!IS_OWNED); -} diff --git a/src/test/ui/consts/is_ascii.rs b/src/test/ui/consts/is_ascii.rs deleted file mode 100644 index d8424549f93e6..0000000000000 --- a/src/test/ui/consts/is_ascii.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -static X: bool = 'a'.is_ascii(); -static Y: bool = 'รค'.is_ascii(); - -static BX: bool = b'a'.is_ascii(); -static BY: bool = 192u8.is_ascii(); - -fn main() { - assert!(X); - assert!(!Y); - - assert!(BX); - assert!(!BY); -} From a3ee65f87e2138191cd855968c136f6ee6e35c16 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 4 Sep 2020 02:42:50 +0000 Subject: [PATCH 12/23] Remove a useless allowed attr --- library/core/src/slice/mod.rs | 1 - library/std/src/os/raw/mod.rs | 1 - library/std/src/os/raw/tests.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 503f015e76a68..4a4cf9cfc17dc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -66,7 +66,6 @@ impl [T] { #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { // SAFETY: this is safe because `&[T]` and `FatPtr` have the same layout. diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 1fe27a3460000..83e8853fe7923 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -9,7 +9,6 @@ #![stable(feature = "raw_os", since = "1.1.0")] #[cfg(test)] -#[allow(unused_imports)] mod tests; #[doc(include = "char.md")] diff --git a/library/std/src/os/raw/tests.rs b/library/std/src/os/raw/tests.rs index e808faf81d657..e7bb7d7e73e80 100644 --- a/library/std/src/os/raw/tests.rs +++ b/library/std/src/os/raw/tests.rs @@ -1,5 +1,4 @@ use crate::any::TypeId; -use crate::mem; macro_rules! ok { ($($t:ident)*) => {$( From 8f11127d893bb46228c2ce5bb1753e28a6dc4a47 Mon Sep 17 00:00:00 2001 From: numbermaniac <5206120+numbermaniac@users.noreply.github.com> Date: Fri, 4 Sep 2020 14:21:52 +1000 Subject: [PATCH 13/23] time.rs: Make spelling of "Darwin" consistent --- library/std/src/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 73c0a7b403a7b..575882eb459fc 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -159,7 +159,7 @@ pub struct Instant(time::Instant); /// | CloudABI | [clock_time_get (Realtime Clock)] | /// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | /// | UNIX | [clock_gettime (Realtime Clock)] | -/// | DARWIN | [gettimeofday] | +/// | Darwin | [gettimeofday] | /// | VXWorks | [clock_gettime (Realtime Clock)] | /// | WASI | [__wasi_clock_time_get (Realtime Clock)] | /// | Windows | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime] | From fac272688e9d561b1fff71621323682d23e4c31d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 4 Sep 2020 00:59:41 -0700 Subject: [PATCH 14/23] Use ops::ControlFlow in graph::iterate --- .../rustc_data_structures/src/graph/iterate/mod.rs | 13 +++++-------- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_mir_build/src/lib.rs | 1 + compiler/rustc_mir_build/src/lints.rs | 6 +++--- library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/traits/double_ended.rs | 2 +- library/core/src/ops/control_flow.rs | 7 +++++++ 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index 64ff6130ddffb..8946666d96142 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -87,11 +87,8 @@ where } /// Allows searches to terminate early with a value. -#[derive(Clone, Copy, Debug)] -pub enum ControlFlow { - Break(T), - Continue, -} +// FIXME (#75744): remove the alias once the generics are in a better order and `C=()`. +pub type ControlFlow = std::ops::ControlFlow<(), T>; /// The status of a node in the depth-first search. /// @@ -260,12 +257,12 @@ where _node: G::Node, _prior_status: Option, ) -> ControlFlow { - ControlFlow::Continue + ControlFlow::CONTINUE } /// Called after all nodes reachable from this one have been examined. fn node_settled(&mut self, _node: G::Node) -> ControlFlow { - ControlFlow::Continue + ControlFlow::CONTINUE } /// Behave as if no edges exist from `source` to `target`. @@ -290,7 +287,7 @@ where ) -> ControlFlow { match prior_status { Some(NodeStatus::Visited) => ControlFlow::Break(()), - _ => ControlFlow::Continue, + _ => ControlFlow::CONTINUE, } } } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index de4e7a1342431..88c160e93b66a 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -8,6 +8,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![allow(incomplete_features)] +#![feature(control_flow_enum)] #![feature(in_band_lifetimes)] #![feature(unboxed_closures)] #![feature(generators)] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 313bb979a5161..e55180ff4be52 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -6,6 +6,7 @@ #![feature(box_syntax)] #![feature(const_fn)] #![feature(const_panic)] +#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] #![feature(or_patterns)] diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index fd2d5a4abd424..b85ada15ed51c 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -117,7 +117,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> { // A diverging InlineAsm is treated as non-recursing TerminatorKind::InlineAsm { destination, .. } => { if destination.is_some() { - ControlFlow::Continue + ControlFlow::CONTINUE } else { ControlFlow::Break(NonRecursive) } @@ -131,7 +131,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> { | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Goto { .. } - | TerminatorKind::SwitchInt { .. } => ControlFlow::Continue, + | TerminatorKind::SwitchInt { .. } => ControlFlow::CONTINUE, } } @@ -144,7 +144,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> { } } - ControlFlow::Continue + ControlFlow::CONTINUE } fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool { diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index c3f1269401aa9..d89874eb7a913 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1273,7 +1273,7 @@ where ) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ { move |(), x| match f(x) { Some(x) => ControlFlow::Break(x), - None => ControlFlow::Continue(()), + None => ControlFlow::CONTINUE, } } diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index f50807116bd09..a025bc8b56049 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -310,7 +310,7 @@ pub trait DoubleEndedIterator: Iterator { mut predicate: impl FnMut(&T) -> bool, ) -> impl FnMut((), T) -> ControlFlow<(), T> { move |(), x| { - if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) } + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } } } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 687d423dcb635..3f0cce4e18ac9 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -65,3 +65,10 @@ impl ControlFlow { } } } + +impl ControlFlow<(), B> { + /// It's frequently the case that there's no value needed with `Continue`, + /// so this provides a way to avoid typing `(())`, if you prefer it. + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub const CONTINUE: Self = ControlFlow::Continue(()); +} From d16bbd1cb0673713fe9a524c092f7d0ff93c81a6 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Fri, 4 Sep 2020 17:18:26 +0530 Subject: [PATCH 15/23] Move Vec slice UI tests in library --- library/alloc/tests/vec.rs | 23 ++++++++++ src/test/ui/array-slice-vec/slice-2.rs | 62 -------------------------- 2 files changed, 23 insertions(+), 62 deletions(-) delete mode 100644 src/test/ui/array-slice-vec/slice-2.rs diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 8e66c8a22cec5..df86a775e5a51 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -345,6 +345,29 @@ fn test_zip_unzip() { assert_eq!((3, 6), (left[2], right[2])); } +#[test] +fn test_cmp() { + let x: &[isize] = &[1, 2, 3, 4, 5]; + let cmp: &[isize] = &[1, 2, 3, 4, 5]; + assert_eq!(&x[..], cmp); + let cmp: &[isize] = &[3, 4, 5]; + assert_eq!(&x[2..], cmp); + let cmp: &[isize] = &[1, 2, 3]; + assert_eq!(&x[..3], cmp); + let cmp: &[isize] = &[2, 3, 4]; + assert_eq!(&x[1..4], cmp); + + let x: Vec = vec![1, 2, 3, 4, 5]; + let cmp: &[isize] = &[1, 2, 3, 4, 5]; + assert_eq!(&x[..], cmp); + let cmp: &[isize] = &[3, 4, 5]; + assert_eq!(&x[2..], cmp); + let cmp: &[isize] = &[1, 2, 3]; + assert_eq!(&x[..3], cmp); + let cmp: &[isize] = &[2, 3, 4]; + assert_eq!(&x[1..4], cmp); +} + #[test] fn test_vec_truncate_drop() { static mut DROPS: u32 = 0; diff --git a/src/test/ui/array-slice-vec/slice-2.rs b/src/test/ui/array-slice-vec/slice-2.rs deleted file mode 100644 index 01733f48234f9..0000000000000 --- a/src/test/ui/array-slice-vec/slice-2.rs +++ /dev/null @@ -1,62 +0,0 @@ -// run-pass - -// Test slicing expressions on slices and Vecs. - - -fn main() { - let x: &[isize] = &[1, 2, 3, 4, 5]; - let cmp: &[isize] = &[1, 2, 3, 4, 5]; - assert_eq!(&x[..], cmp); - let cmp: &[isize] = &[3, 4, 5]; - assert_eq!(&x[2..], cmp); - let cmp: &[isize] = &[1, 2, 3]; - assert_eq!(&x[..3], cmp); - let cmp: &[isize] = &[2, 3, 4]; - assert_eq!(&x[1..4], cmp); - - let x: Vec = vec![1, 2, 3, 4, 5]; - let cmp: &[isize] = &[1, 2, 3, 4, 5]; - assert_eq!(&x[..], cmp); - let cmp: &[isize] = &[3, 4, 5]; - assert_eq!(&x[2..], cmp); - let cmp: &[isize] = &[1, 2, 3]; - assert_eq!(&x[..3], cmp); - let cmp: &[isize] = &[2, 3, 4]; - assert_eq!(&x[1..4], cmp); - - let x: &mut [isize] = &mut [1, 2, 3, 4, 5]; - { - let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5]; - assert_eq!(&mut x[..], cmp); - } - { - let cmp: &mut [isize] = &mut [3, 4, 5]; - assert_eq!(&mut x[2..], cmp); - } - { - let cmp: &mut [isize] = &mut [1, 2, 3]; - assert_eq!(&mut x[..3], cmp); - } - { - let cmp: &mut [isize] = &mut [2, 3, 4]; - assert_eq!(&mut x[1..4], cmp); - } - - let mut x: Vec = vec![1, 2, 3, 4, 5]; - { - let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5]; - assert_eq!(&mut x[..], cmp); - } - { - let cmp: &mut [isize] = &mut [3, 4, 5]; - assert_eq!(&mut x[2..], cmp); - } - { - let cmp: &mut [isize] = &mut [1, 2, 3]; - assert_eq!(&mut x[..3], cmp); - } - { - let cmp: &mut [isize] = &mut [2, 3, 4]; - assert_eq!(&mut x[1..4], cmp); - } -} From 8f2d9069a8c19c5471c4f3490ce21eb910cf3074 Mon Sep 17 00:00:00 2001 From: Amjad Alsharafi Date: Fri, 4 Sep 2020 01:47:35 +0800 Subject: [PATCH 16/23] Implementation of incompatible features error If two features are defined as incompatible, using them together would result in an error --- compiler/rustc_ast_passes/src/feature_gate.rs | 34 +++++++++++++++++++ compiler/rustc_feature/src/active.rs | 5 +++ compiler/rustc_feature/src/lib.rs | 2 +- .../const-generics/min-and-full-same-time.rs | 7 ++++ .../min-and-full-same-time.stderr | 13 +++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const-generics/min-and-full-same-time.rs create mode 100644 src/test/ui/const-generics/min-and-full-same-time.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0ee8ef55e61bf..97e6b363eff60 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -608,6 +608,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { pub fn check_crate(krate: &ast::Crate, sess: &Session) { maybe_stage_features(sess, krate); + check_incompatible_features(sess); let mut visitor = PostExpansionVisitor { sess, features: &sess.features_untracked() }; let spans = sess.parse_sess.gated_spans.spans.borrow(); @@ -677,3 +678,36 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { } } } + +fn check_incompatible_features(sess: &Session) { + let features = sess.features_untracked(); + + let declared_features = features + .declared_lang_features + .iter() + .copied() + .map(|(name, span, _)| (name, span)) + .chain(features.declared_lib_features.iter().copied()); + + for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES + .iter() + .filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2)) + { + if let Some((f1_name, f1_span)) = declared_features.clone().find(|(name, _)| name == f1) { + if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2) + { + let spans = vec![f1_span, f2_span]; + sess.struct_span_err( + spans.clone(), + &format!( + "features `{}` and `{}` are incompatible, using them at the same time \ + is not allowed", + f1_name, f2_name + ), + ) + .help("remove one of these features") + .emit(); + } + } + } +} diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index e858980738d71..3d7b3da45ccb9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -605,3 +605,8 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::lazy_normalization_consts, sym::specialization, ]; + +/// Some features are not allowed to be used together at the same time, if +/// the two are present, produce an error +pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = + &[(sym::const_generics, sym::min_const_generics)]; diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 4393368cd4524..15564a59658cb 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -131,7 +131,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option $DIR/min-and-full-same-time.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ +... +LL | #![feature(min_const_generics)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: remove one of these features + +error: aborting due to previous error + From 2ed1a217902134850907e4c98b7fc01670df8c39 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Fri, 4 Sep 2020 15:51:58 -0400 Subject: [PATCH 17/23] add some intra-doc links to `Iterator` --- library/core/src/iter/traits/iterator.rs | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 46ef12cd938b3..527c3872dda53 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -819,7 +819,7 @@ pub trait Iterator { Enumerate::new(self) } - /// Creates an iterator which can use `peek` to look at the next element of + /// Creates an iterator which can use [`peek`] to look at the next element of /// the iterator without consuming it. /// /// Adds a [`peek`] method to an iterator. See its documentation for @@ -2002,7 +2002,7 @@ pub trait Iterator { /// The same as [`fold()`], but uses the first element in the /// iterator as the initial value, folding every subsequent element into it. - /// If the iterator is empty, return `None`; otherwise, return the result + /// If the iterator is empty, return [`None`]; otherwise, return the result /// of the fold. /// /// [`fold()`]: Iterator::fold @@ -2831,7 +2831,7 @@ pub trait Iterator { Product::product(self) } - /// Lexicographically compares the elements of this `Iterator` with those + /// Lexicographically compares the elements of this [`Iterator`] with those /// of another. /// /// # Examples @@ -2853,7 +2853,7 @@ pub trait Iterator { self.cmp_by(other, |x, y| x.cmp(&y)) } - /// Lexicographically compares the elements of this `Iterator` with those + /// Lexicographically compares the elements of this [`Iterator`] with those /// of another with respect to the specified comparison function. /// /// # Examples @@ -2905,7 +2905,7 @@ pub trait Iterator { } } - /// Lexicographically compares the elements of this `Iterator` with those + /// Lexicographically compares the elements of this [`Iterator`] with those /// of another. /// /// # Examples @@ -2929,7 +2929,7 @@ pub trait Iterator { self.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) } - /// Lexicographically compares the elements of this `Iterator` with those + /// Lexicographically compares the elements of this [`Iterator`] with those /// of another with respect to the specified comparison function. /// /// # Examples @@ -2990,7 +2990,7 @@ pub trait Iterator { } } - /// Determines if the elements of this `Iterator` are equal to those of + /// Determines if the elements of this [`Iterator`] are equal to those of /// another. /// /// # Examples @@ -3009,7 +3009,7 @@ pub trait Iterator { self.eq_by(other, |x, y| x == y) } - /// Determines if the elements of this `Iterator` are equal to those of + /// Determines if the elements of this [`Iterator`] are equal to those of /// another with respect to the specified equality function. /// /// # Examples @@ -3050,7 +3050,7 @@ pub trait Iterator { } } - /// Determines if the elements of this `Iterator` are unequal to those of + /// Determines if the elements of this [`Iterator`] are unequal to those of /// another. /// /// # Examples @@ -3069,7 +3069,7 @@ pub trait Iterator { !self.eq(other) } - /// Determines if the elements of this `Iterator` are lexicographically + /// Determines if the elements of this [`Iterator`] are lexicographically /// less than those of another. /// /// # Examples @@ -3090,7 +3090,7 @@ pub trait Iterator { self.partial_cmp(other) == Some(Ordering::Less) } - /// Determines if the elements of this `Iterator` are lexicographically + /// Determines if the elements of this [`Iterator`] are lexicographically /// less or equal to those of another. /// /// # Examples @@ -3111,7 +3111,7 @@ pub trait Iterator { matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal)) } - /// Determines if the elements of this `Iterator` are lexicographically + /// Determines if the elements of this [`Iterator`] are lexicographically /// greater than those of another. /// /// # Examples @@ -3132,7 +3132,7 @@ pub trait Iterator { self.partial_cmp(other) == Some(Ordering::Greater) } - /// Determines if the elements of this `Iterator` are lexicographically + /// Determines if the elements of this [`Iterator`] are lexicographically /// greater than or equal to those of another. /// /// # Examples From 59e37332b0d2d0c5e43bea1184ec0387fb07cc80 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 4 Sep 2020 16:28:23 -0700 Subject: [PATCH 18/23] Add `BREAK` too, and improve the comments --- .../src/graph/iterate/mod.rs | 2 +- library/core/src/iter/traits/iterator.rs | 14 ++++---- library/core/src/ops/control_flow.rs | 36 +++++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index 8946666d96142..bc3d1ce53bac5 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -286,7 +286,7 @@ where prior_status: Option, ) -> ControlFlow { match prior_status { - Some(NodeStatus::Visited) => ControlFlow::Break(()), + Some(NodeStatus::Visited) => ControlFlow::BREAK, _ => ControlFlow::CONTINUE, } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 46ef12cd938b3..ceeae2371e130 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2086,10 +2086,10 @@ pub trait Iterator { #[inline] fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> { move |(), x| { - if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } + if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } } - self.try_fold((), check(f)) == ControlFlow::Continue(()) + self.try_fold((), check(f)) == ControlFlow::CONTINUE } /// Tests if any element of the iterator matches a predicate. @@ -2139,11 +2139,11 @@ pub trait Iterator { #[inline] fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> { move |(), x| { - if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } + if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } } } - self.try_fold((), check(f)) == ControlFlow::Break(()) + self.try_fold((), check(f)) == ControlFlow::BREAK } /// Searches for an element of an iterator that satisfies a predicate. @@ -2201,7 +2201,7 @@ pub trait Iterator { mut predicate: impl FnMut(&T) -> bool, ) -> impl FnMut((), T) -> ControlFlow<(), T> { move |(), x| { - if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) } + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } } } @@ -2236,7 +2236,7 @@ pub trait Iterator { ) -> impl FnMut((), T) -> ControlFlow<(), B> { move |(), x| match f(x) { Some(x) => ControlFlow::Break(x), - None => ControlFlow::Continue(()), + None => ControlFlow::CONTINUE, } } @@ -2278,7 +2278,7 @@ pub trait Iterator { R: Try, { move |(), x| match f(&x).into_result() { - Ok(false) => ControlFlow::Continue(()), + Ok(false) => ControlFlow::CONTINUE, Ok(true) => ControlFlow::Break(Ok(x)), Err(x) => ControlFlow::Break(Err(x)), } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 3f0cce4e18ac9..b0c7dc1a51875 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -69,6 +69,42 @@ impl ControlFlow { impl ControlFlow<(), B> { /// It's frequently the case that there's no value needed with `Continue`, /// so this provides a way to avoid typing `(())`, if you prefer it. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_enum)] + /// use std::ops::ControlFlow; + /// + /// let mut partial_sum = 0; + /// let last_used = (1..10).chain(20..25).try_for_each(|x| { + /// partial_sum += x; + /// if partial_sum > 100 { ControlFlow::Break(x) } + /// else { ControlFlow::CONTINUE } + /// }); + /// assert_eq!(last_used.break_value(), Some(22)); + /// ``` #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub const CONTINUE: Self = ControlFlow::Continue(()); } + +impl ControlFlow { + /// APIs like `try_for_each` don't need values with `Break`, + /// so this provides a way to avoid typing `(())`, if you prefer it. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_enum)] + /// use std::ops::ControlFlow; + /// + /// let mut partial_sum = 0; + /// (1..10).chain(20..25).try_for_each(|x| { + /// if partial_sum > 100 { ControlFlow::BREAK } + /// else { partial_sum += x; ControlFlow::CONTINUE } + /// }); + /// assert_eq!(partial_sum, 108); + /// ``` + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub const BREAK: Self = ControlFlow::Break(()); +} From dfd219d6e77311a19a630461b08f6fb3e06b0dd2 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 5 Sep 2020 02:17:22 +0000 Subject: [PATCH 19/23] Indent a note to make folding work nicer Co-authored-by: Joshua Nelson --- library/core/src/slice/mod.rs | 5 +++-- src/test/ui/str/str-idx.stderr | 6 +++--- src/test/ui/str/str-mut-idx.stderr | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 68977a983aa37..17799309735c2 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3358,8 +3358,9 @@ mod private_slice_index { on(T = "str", label = "string indices are ranges of `usize`",), on( all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"), - note = "you can use `.chars().nth()` or `.bytes().nth()` -see chapter in The Book " + note = "you can use `.chars().nth()` or `.bytes().nth()`\n\ + for more information, see chapter 8 in The Book: \ + " ), message = "the type `{T}` cannot be indexed by `{Self}`", label = "slice indices are of type `usize` or ranges of `usize`" diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index ef7ce735868cb..f323ba03c012c 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -6,7 +6,7 @@ LL | let _: u8 = s[4]; | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` - see chapter in The Book + for more information, see chapter 8 in The Book: = note: required because of the requirements on the impl of `Index<{integer}>` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -17,7 +17,7 @@ LL | let _ = s.get(4); | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` - see chapter in The Book + for more information, see chapter 8 in The Book: error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-idx.rs:5:29 @@ -27,7 +27,7 @@ LL | let _ = s.get_unchecked(4); | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` - see chapter in The Book + for more information, see chapter 8 in The Book: error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-idx.rs:6:17 diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index abb9b09cf3871..405542820a394 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -39,7 +39,7 @@ LL | s.get_mut(1); | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` - see chapter in The Book + for more information, see chapter 8 in The Book: error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-mut-idx.rs:11:25 @@ -49,7 +49,7 @@ LL | s.get_unchecked_mut(1); | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` - see chapter in The Book + for more information, see chapter 8 in The Book: error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-mut-idx.rs:13:5 From 7cc2569731ddf1e64ec6a3216ea860aeb42d1b52 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 5 Sep 2020 12:18:19 +0200 Subject: [PATCH 20/23] Add tracking issue number for atomic_from_mut. --- library/core/src/sync/atomic.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 2cdb4f16c024a..051c93ee92203 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -373,7 +373,7 @@ impl AtomicBool { /// assert_eq!(some_bool, false); /// ``` #[inline] - #[unstable(feature = "atomic_from_mut", issue = "none")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut bool) -> &Self { // SAFETY: the mutable reference guarantees unique ownership, and // alignment of both `bool` and `Self` is 1. @@ -950,7 +950,7 @@ impl AtomicPtr { /// assert_eq!(unsafe { *some_ptr }, 456); /// ``` #[inline] - #[unstable(feature = "atomic_from_mut", issue = "none")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut *mut T) -> &Self { let [] = [(); align_of::() - align_of::<*mut T>()]; // SAFETY: @@ -1438,7 +1438,7 @@ assert_eq!(some_int, 100); "), #[inline] $(#[cfg($from_mut_cfg)])? - #[unstable(feature = "atomic_from_mut", issue = "none")] + #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut $int_type) -> &Self { let [] = [(); align_of::() - align_of::<$int_type>()]; // SAFETY: From 8af85fa1f73428888730b05e48291c73897dd44d Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Wed, 26 Aug 2020 17:39:43 +0100 Subject: [PATCH 21/23] Improve the documentation of `filter()` and `filter_map()`. I believe the documentation is currently a little misleading. For example, in the docs for `filter()`: > If the closure returns `false`, it will try again, and call the closure on > the next element, seeing if it passes the test. This kind of implies that if the closure returns true then we *don't* "try again" and no further elements are considered. In actuality that's not the case, every element is tried regardless of what happened with the previous element. This change tries to clarify that by removing the uses of "try again" altogether. --- library/core/src/iter/traits/iterator.rs | 26 ++++++++---------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 46ef12cd938b3..b5aa7257cf38e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -648,11 +648,9 @@ pub trait Iterator { /// Creates an iterator which uses a closure to determine if an element /// should be yielded. /// - /// The closure must return `true` or `false`. `filter()` creates an - /// iterator which calls this closure on each element. If the closure - /// returns `true`, then the element is returned. If the closure returns - /// `false`, it will try again, and call the closure on the next element, - /// seeing if it passes the test. + /// Given an element the closure must return `true` or `false`. The returned + /// iterator will yield only the elements for which the closure returns + /// true. /// /// # Examples /// @@ -719,24 +717,16 @@ pub trait Iterator { /// Creates an iterator that both filters and maps. /// - /// The closure must return an [`Option`]. `filter_map` creates an - /// iterator which calls this closure on each element. If the closure - /// returns [`Some(element)`][`Some`], then that element is returned. If the - /// closure returns [`None`], it will try again, and call the closure on the - /// next element, seeing if it will return [`Some`]. + /// The returned iterator yields only the `value`s for which the supplied + /// closure returns `Some(value)`. /// - /// Why `filter_map` and not just [`filter`] and [`map`]? The key is in this - /// part: + /// `filter_map` can be used to make chains of [`filter`] and [`map`] more + /// concise. The example below shows how a `map().filter().map()` can be + /// shortened to a single call to `filter_map`. /// /// [`filter`]: Iterator::filter /// [`map`]: Iterator::map /// - /// > If the closure returns [`Some(element)`][`Some`], then that element is returned. - /// - /// In other words, it removes the [`Option`] layer automatically. If your - /// mapping is already returning an [`Option`] and you want to skip over - /// [`None`]s, then `filter_map` is much, much nicer to use. - /// /// # Examples /// /// Basic usage: From 7cbfbd3ee7b328f57162edbaa92820401b040a03 Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Sat, 5 Sep 2020 14:46:22 -0700 Subject: [PATCH 22/23] compiletest: Introduce "min-cdb-version" --- src/tools/compiletest/src/common.rs | 3 +++ src/tools/compiletest/src/header.rs | 25 ++++++++++++++++++++++--- src/tools/compiletest/src/main.rs | 29 ++++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 848bd3a43e890..2f832b53a9039 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -261,6 +261,9 @@ pub struct Config { /// Path to / name of the Microsoft Console Debugger (CDB) executable pub cdb: Option, + /// Version of CDB + pub cdb_version: Option<[u16; 4]>, + /// Path to / name of the GDB executable pub gdb: Option, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 0efa668ecc88b..17649dfab3750 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -8,8 +8,8 @@ use std::path::{Path, PathBuf}; use tracing::*; use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode}; -use crate::extract_gdb_version; use crate::util; +use crate::{extract_cdb_version, extract_gdb_version}; #[cfg(test)] mod tests; @@ -105,6 +105,10 @@ impl EarlyProps { props.ignore = true; } + if config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln) { + props.ignore = true; + } + if config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln) { props.ignore = true; } @@ -131,6 +135,21 @@ impl EarlyProps { return props; + fn ignore_cdb(config: &Config, line: &str) -> bool { + if let Some(actual_version) = config.cdb_version { + if let Some(min_version) = line.strip_prefix("min-cdb-version:").map(str::trim) { + let min_version = extract_cdb_version(min_version).unwrap_or_else(|| { + panic!("couldn't parse version range: {:?}", min_version); + }); + + // Ignore if actual version is smaller than the minimum + // required version + return actual_version < min_version; + } + } + false + } + fn ignore_gdb(config: &Config, line: &str) -> bool { if let Some(actual_version) = config.gdb_version { if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) { @@ -142,8 +161,8 @@ impl EarlyProps { if start_ver != end_ver { panic!("Expected single GDB version") } - // Ignore if actual version is smaller the minimum required - // version + // Ignore if actual version is smaller than the minimum + // required version return actual_version < start_ver; } else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) { let (min_version, max_version) = diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index adf2fa7fd8ecc..190a9c6221060 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -163,7 +163,7 @@ pub fn parse_config(args: Vec) -> Config { let target = opt_str2(matches.opt_str("target")); let android_cross_path = opt_path(matches, "android-cross-path"); - let cdb = analyze_cdb(matches.opt_str("cdb"), &target); + let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target); let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); let (lldb_version, lldb_native_rust) = matches @@ -216,6 +216,7 @@ pub fn parse_config(args: Vec) -> Config { target, host: opt_str2(matches.opt_str("host")), cdb, + cdb_version, gdb, gdb_version, gdb_native_rust, @@ -773,8 +774,30 @@ fn find_cdb(target: &str) -> Option { } /// Returns Path to CDB -fn analyze_cdb(cdb: Option, target: &str) -> Option { - cdb.map(OsString::from).or_else(|| find_cdb(target)) +fn analyze_cdb(cdb: Option, target: &str) -> (Option, Option<[u16; 4]>) { + let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target)); + + let mut version = None; + if let Some(cdb) = cdb.as_ref() { + if let Ok(output) = Command::new(cdb).arg("/version").output() { + if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { + version = extract_cdb_version(&first_line); + } + } + } + + (cdb, version) +} + +fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { + // Example full_version_line: "cdb version 10.0.18362.1" + let version = full_version_line.rsplit(' ').next()?; + let mut components = version.split('.'); + let major: u16 = components.next().unwrap().parse().unwrap(); + let minor: u16 = components.next().unwrap().parse().unwrap(); + let patch: u16 = components.next().unwrap_or("0").parse().unwrap(); + let build: u16 = components.next().unwrap_or("0").parse().unwrap(); + Some([major, minor, patch, build]) } /// Returns (Path to GDB, GDB Version, GDB has Rust Support) From 4046f928d162e52e2e87e0a91e97aa1ea118f2aa Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Sat, 5 Sep 2020 14:47:16 -0700 Subject: [PATCH 23/23] debuginfo: Ignore HashMap tests before cdb 10.0.18362.1 cdb chokes on the cast and reports "Unable to find type 'tuple *' for cast." --- src/test/debuginfo/pretty-std-collections-hash.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/debuginfo/pretty-std-collections-hash.rs b/src/test/debuginfo/pretty-std-collections-hash.rs index e8f52deabd809..9f59936a92d10 100644 --- a/src/test/debuginfo/pretty-std-collections-hash.rs +++ b/src/test/debuginfo/pretty-std-collections-hash.rs @@ -1,3 +1,7 @@ +// CDB doesn't like how libstd.natvis casts to tuples before this version. +// https://github.com/rust-lang/rust/issues/76352#issuecomment-687640746 +// min-cdb-version: 10.0.18362.1 + // cdb-only // compile-flags:-g