From 62f98a2509df9d660524334c5ea02b6269d695f4 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 29 Jan 2021 16:21:12 +0100 Subject: [PATCH 01/10] btree: use Option's unwrap_unchecked() Now that https://github.com/rust-lang/rust/issues/81383 is available, start using it. Signed-off-by: Miguel Ojeda --- library/alloc/src/collections/btree/map.rs | 11 +++++------ library/alloc/src/collections/btree/mod.rs | 16 ---------------- library/alloc/src/collections/btree/navigate.rs | 11 +++++------ library/alloc/src/collections/btree/remove.rs | 5 ++--- library/alloc/src/lib.rs | 1 + 5 files changed, 13 insertions(+), 31 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 79dc694e6be82..bd5ed985404f5 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -11,7 +11,6 @@ use core::ptr; use super::borrow::DormantMutRef; use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root}; use super::search::SearchResult::*; -use super::unwrap_unchecked; mod entry; pub use entry::{Entry, OccupiedEntry, VacantEntry}; @@ -1386,7 +1385,7 @@ impl Drop for IntoIter { unsafe { let mut node = - unwrap_unchecked(ptr::read(&self.0.front)).into_node().forget_type(); + ptr::read(&self.0.front).unwrap_unchecked().into_node().forget_type(); while let Some(parent) = node.deallocate_and_ascend() { node = parent.into_node().forget_type(); } @@ -1711,7 +1710,7 @@ impl<'a, K, V> Range<'a, K, V> { } unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - unsafe { unwrap_unchecked(self.front.as_mut()).next_unchecked() } + unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() } } } @@ -1800,7 +1799,7 @@ impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { impl<'a, K, V> Range<'a, K, V> { unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { - unsafe { unwrap_unchecked(self.back.as_mut()).next_back_unchecked() } + unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() } } } @@ -1846,7 +1845,7 @@ impl<'a, K, V> RangeMut<'a, K, V> { } unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { - unsafe { unwrap_unchecked(self.front.as_mut()).next_unchecked() } + unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() } } /// Returns an iterator of references over the remaining items. @@ -1876,7 +1875,7 @@ impl FusedIterator for RangeMut<'_, K, V> {} impl<'a, K, V> RangeMut<'a, K, V> { unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { - unsafe { unwrap_unchecked(self.back.as_mut()).next_back_unchecked() } + unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() } } } diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index cdb39104047f0..cf91c17b511cc 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -19,22 +19,6 @@ trait Recover { fn replace(&mut self, key: Self::Key) -> Option; } -/// Same purpose as `Option::unwrap` but doesn't always guarantee a panic -/// if the option contains no value. -/// SAFETY: the caller must ensure that the option contains a value. -#[inline(always)] -pub unsafe fn unwrap_unchecked(val: Option) -> T { - val.unwrap_or_else(|| { - if cfg!(debug_assertions) { - panic!("'unchecked' unwrap on None in BTreeMap"); - } else { - unsafe { - core::intrinsics::unreachable(); - } - } - }) -} - #[cfg(test)] /// XorShiftRng struct DeterministicRng { diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index 2773b427fb133..1ef2a572ddd91 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -6,7 +6,6 @@ use core::ptr; use super::node::{marker, ForceResult::*, Handle, NodeRef}; use super::search::SearchResult; -use super::unwrap_unchecked; /// Finds the leaf edges delimiting a specified range in or underneath a node. /// @@ -310,7 +309,7 @@ macro_rules! def_next_kv_uncheched_dealloc { Err(last_edge) => { unsafe { let parent_edge = last_edge.into_node().deallocate_and_ascend(); - unwrap_unchecked(parent_edge).forget_node_type() + parent_edge.unwrap_unchecked().forget_node_type() } } } @@ -331,7 +330,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Ed pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { super::mem::replace(self, |leaf_edge| { let kv = leaf_edge.next_kv(); - let kv = unsafe { unwrap_unchecked(kv.ok()) }; + let kv = unsafe { kv.ok().unwrap_unchecked() }; (kv.next_leaf_edge(), kv.into_kv()) }) } @@ -344,7 +343,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Ed pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { super::mem::replace(self, |leaf_edge| { let kv = leaf_edge.next_back_kv(); - let kv = unsafe { unwrap_unchecked(kv.ok()) }; + let kv = unsafe { kv.ok().unwrap_unchecked() }; (kv.next_back_leaf_edge(), kv.into_kv()) }) } @@ -359,7 +358,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::E pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { let kv = super::mem::replace(self, |leaf_edge| { let kv = leaf_edge.next_kv(); - let kv = unsafe { unwrap_unchecked(kv.ok()) }; + let kv = unsafe { kv.ok().unwrap_unchecked() }; (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv) }); // Doing this last is faster, according to benchmarks. @@ -374,7 +373,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::E pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { let kv = super::mem::replace(self, |leaf_edge| { let kv = leaf_edge.next_back_kv(); - let kv = unsafe { unwrap_unchecked(kv.ok()) }; + let kv = unsafe { kv.ok().unwrap_unchecked() }; (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv) }); // Doing this last is faster, according to benchmarks. diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs index ff842197d1918..9cd016fa62f0e 100644 --- a/library/alloc/src/collections/btree/remove.rs +++ b/library/alloc/src/collections/btree/remove.rs @@ -1,6 +1,5 @@ use super::map::MIN_LEN; use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef}; -use super::unwrap_unchecked; impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { /// Removes a key-value pair from the tree, and returns that pair, as well as @@ -77,12 +76,12 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, // the element we were asked to remove. Prefer the left adjacent KV, // for the reasons listed in `choose_parent_kv`. let left_leaf_kv = self.left_edge().descend().last_leaf_edge().left_kv(); - let left_leaf_kv = unsafe { unwrap_unchecked(left_leaf_kv.ok()) }; + let left_leaf_kv = unsafe { left_leaf_kv.ok().unwrap_unchecked() }; let (left_kv, left_hole) = left_leaf_kv.remove_leaf_kv(handle_emptied_internal_root); // The internal node may have been stolen from or merged. Go back right // to find where the original KV ended up. - let mut internal = unsafe { unwrap_unchecked(left_hole.next_kv().ok()) }; + let mut internal = unsafe { left_hole.next_kv().ok().unwrap_unchecked() }; let old_kv = internal.replace_kv(left_kv.0, left_kv.1); let pos = internal.next_leaf_edge(); (old_kv, pos) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index d7ae353282e79..afbf6aad5d0a7 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -111,6 +111,7 @@ #![feature(nll)] #![feature(nonnull_slice_from_raw_parts)] #![feature(auto_traits)] +#![feature(option_result_unwrap_unchecked)] #![feature(or_patterns)] #![feature(pattern)] #![feature(ptr_internals)] From f436630ac85504da5c6ef802dbee658fa97a6f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 4 Feb 2021 10:40:20 +0200 Subject: [PATCH 02/10] Add a note about the correctness and the effect on unsafe code to the `ExactSizeIterator` docs As it is a safe trait it does not provide any guarantee that the returned length is correct and as such unsafe code must not rely on it. That's why `TrustedLen` exists. Fixes https://github.com/rust-lang/rust/issues/81739 --- library/core/src/iter/traits/exact_size.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index 996d62e2b4a42..167db3359f240 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -13,6 +13,12 @@ /// implement it. However, you may be able to provide a more performant /// implementation than the default, so overriding it in this case makes sense. /// +/// Note that this trait is a safe trait and as such does *not* and *cannot* +/// guarantee that the returned length is correct. This means that `unsafe` +/// code **must not** rely on the correctness of [`Iterator::size_hint`]. The +/// unstable and unsafe [`TrustedLen`](super::marker::TrustedLen) trait gives +/// this additional guarantee. +/// /// [`len`]: ExactSizeIterator::len /// /// # Examples From be159379f69ea86a1c7a9de2b39adbb699068fa5 Mon Sep 17 00:00:00 2001 From: Jesus Rubio Date: Sat, 6 Feb 2021 16:42:34 +0100 Subject: [PATCH 03/10] Add long error explanation for E0542 --- compiler/rustc_error_codes/src/error_codes.rs | 2 +- .../src/error_codes/E0542.md | 47 +++++++++++++++++++ .../stability-attribute-sanity.stderr | 2 +- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0542.md diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 1ed43669ad84b..849ef18fb90cb 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -285,6 +285,7 @@ E0537: include_str!("./error_codes/E0537.md"), E0538: include_str!("./error_codes/E0538.md"), E0539: include_str!("./error_codes/E0539.md"), E0541: include_str!("./error_codes/E0541.md"), +E0542: include_str!("./error_codes/E0542.md"), E0546: include_str!("./error_codes/E0546.md"), E0550: include_str!("./error_codes/E0550.md"), E0551: include_str!("./error_codes/E0551.md"), @@ -602,7 +603,6 @@ E0781: include_str!("./error_codes/E0781.md"), E0523, // E0526, // shuffle indices are not constant // E0540, // multiple rustc_deprecated attributes - E0542, // missing 'since' E0543, // missing 'reason' E0544, // multiple stability levels E0545, // incorrect 'issue' diff --git a/compiler/rustc_error_codes/src/error_codes/E0542.md b/compiler/rustc_error_codes/src/error_codes/E0542.md new file mode 100644 index 0000000000000..4ac08660fad75 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0542.md @@ -0,0 +1,47 @@ +A feature since is missing. + +Erroneous code example: + +```compile_fail,E0542 +#![feature(staged_api)] +#![stable(since = "1.0.0", feature = "test")] + +#[stable(feature = "_stable_fn")] // invalid +fn _stable_fn() {} + +#[rustc_const_stable(feature = "_stable_const_fn")] // invalid +fn _stable_const_fn() {} + +#[stable(feature = "_deprecated_fn", since = "0.1.0")] +#[rustc_deprecated( // invalid + reason = "explanation for deprecation" +)] +fn _deprecated_fn() {} +``` + +To fix the issue you need to provide the since field of the feature. + +``` +#![feature(staged_api)] +#![stable(since = "1.0.0", feature = "test")] + +#[stable(feature = "_stable_fn", since = "1.0.0")] +fn _stable_fn() {} + +#[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] +fn _stable_const_fn() {} + +#[stable(feature = "_deprecated_fn", since = "0.1.0")] +#[rustc_deprecated( + since = "1.0.0", + reason = "explanation for deprecation" +)] +fn _deprecated_fn() {} +``` + +See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix +of the Book and the [Stability attributes][stability-attributes] section of the +Rustc Dev Guide for more details. + +[how-rust-made-nightly]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html +[stability-attributes]: https://rustc-dev-guide.rust-lang.org/stability.html diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr index ee9a93359f032..151b96b8b5a66 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr @@ -116,5 +116,5 @@ LL | #[rustc_deprecated(since = "a", reason = "text")] error: aborting due to 19 previous errors -Some errors have detailed explanations: E0539, E0541, E0546, E0550. +Some errors have detailed explanations: E0539, E0541, E0542, E0546, E0550. For more information about an error, try `rustc --explain E0539`. From 956c81355a6982bcf5a072c24ffa7b47f0315c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Rubio?= Date: Sat, 6 Feb 2021 17:39:11 +0100 Subject: [PATCH 04/10] Update compiler/rustc_error_codes/src/error_codes/E0542.md Co-authored-by: Guillaume Gomez --- compiler/rustc_error_codes/src/error_codes/E0542.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0542.md b/compiler/rustc_error_codes/src/error_codes/E0542.md index 4ac08660fad75..01c070009e81e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0542.md +++ b/compiler/rustc_error_codes/src/error_codes/E0542.md @@ -1,4 +1,5 @@ -A feature since is missing. +The `since` value is missing in a stability attribute. + Erroneous code example: From 9be5d2d01f3600af0664279d8d8facaa2bb8bfbb Mon Sep 17 00:00:00 2001 From: Jesus Rubio Date: Sat, 6 Feb 2021 18:05:21 +0100 Subject: [PATCH 05/10] Format fixes --- compiler/rustc_error_codes/src/error_codes/E0542.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0542.md b/compiler/rustc_error_codes/src/error_codes/E0542.md index 01c070009e81e..929b21b8b1211 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0542.md +++ b/compiler/rustc_error_codes/src/error_codes/E0542.md @@ -1,6 +1,5 @@ The `since` value is missing in a stability attribute. - Erroneous code example: ```compile_fail,E0542 @@ -20,7 +19,7 @@ fn _stable_const_fn() {} fn _deprecated_fn() {} ``` -To fix the issue you need to provide the since field of the feature. +To fix the issue you need to provide the `since` field. ``` #![feature(staged_api)] From 0d8a071f983ee2a9863b2bfa7b73f809a1c9b109 Mon Sep 17 00:00:00 2001 From: Jesus Rubio Date: Sat, 6 Feb 2021 18:27:19 +0100 Subject: [PATCH 06/10] Improve long explanation for E0546 --- compiler/rustc_error_codes/src/error_codes/E0546.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0546.md b/compiler/rustc_error_codes/src/error_codes/E0546.md index b2df22c0f8fad..c5313490f2e5f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0546.md +++ b/compiler/rustc_error_codes/src/error_codes/E0546.md @@ -1,4 +1,4 @@ -A feature name is missing. +The `feature` value is missing in a stability attribute. Erroneous code example: @@ -13,15 +13,15 @@ fn unstable_fn() {} fn stable_fn() {} ``` -To fix the issue you need to provide a feature name. +To fix the issue you need to provide the `feature` field. ``` #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[unstable(feature = "unstable_fn", issue = "none")] // ok! +#[unstable(feature = "unstable_fn", issue = "none")] fn unstable_fn() {} -#[stable(feature = "stable_fn", since = "1.0.0")] // ok! +#[stable(feature = "stable_fn", since = "1.0.0")] fn stable_fn() {} ``` From 023c6d2e041da85313b7190a0d10285c3632ade1 Mon Sep 17 00:00:00 2001 From: Jesus Rubio Date: Sat, 6 Feb 2021 19:41:03 +0100 Subject: [PATCH 07/10] Comments updated to keep the consistency --- compiler/rustc_error_codes/src/error_codes/E0542.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0542.md b/compiler/rustc_error_codes/src/error_codes/E0542.md index 929b21b8b1211..dbbc34a71be2c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0542.md +++ b/compiler/rustc_error_codes/src/error_codes/E0542.md @@ -13,9 +13,9 @@ fn _stable_fn() {} fn _stable_const_fn() {} #[stable(feature = "_deprecated_fn", since = "0.1.0")] -#[rustc_deprecated( // invalid +#[rustc_deprecated( reason = "explanation for deprecation" -)] +)] // invalid fn _deprecated_fn() {} ``` @@ -25,17 +25,17 @@ To fix the issue you need to provide the `since` field. #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[stable(feature = "_stable_fn", since = "1.0.0")] +#[stable(feature = "_stable_fn", since = "1.0.0")] // ok! fn _stable_fn() {} -#[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] +#[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] // ok! fn _stable_const_fn() {} #[stable(feature = "_deprecated_fn", since = "0.1.0")] #[rustc_deprecated( since = "1.0.0", reason = "explanation for deprecation" -)] +)] // ok! fn _deprecated_fn() {} ``` From 777582228c22824d7615a93bf042df910af601b0 Mon Sep 17 00:00:00 2001 From: Jesus Rubio Date: Sat, 6 Feb 2021 19:44:09 +0100 Subject: [PATCH 08/10] References added --- compiler/rustc_error_codes/src/error_codes/E0546.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0546.md b/compiler/rustc_error_codes/src/error_codes/E0546.md index c5313490f2e5f..11f2bebba43ff 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0546.md +++ b/compiler/rustc_error_codes/src/error_codes/E0546.md @@ -19,9 +19,16 @@ To fix the issue you need to provide the `feature` field. #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[unstable(feature = "unstable_fn", issue = "none")] +#[unstable(feature = "unstable_fn", issue = "none")] // ok!! fn unstable_fn() {} -#[stable(feature = "stable_fn", since = "1.0.0")] +#[stable(feature = "stable_fn", since = "1.0.0")] // ok!! fn stable_fn() {} ``` + +See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix +of the Book and the [Stability attributes][stability-attributes] section of the +Rustc Dev Guide for more details. + +[how-rust-made-nightly]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html +[stability-attributes]: https://rustc-dev-guide.rust-lang.org/stability.html From ac6c09a980ff0785f0be209c86cb6da563f0ad26 Mon Sep 17 00:00:00 2001 From: Jesus Rubio Date: Sat, 6 Feb 2021 19:45:43 +0100 Subject: [PATCH 09/10] Typo fix --- compiler/rustc_error_codes/src/error_codes/E0546.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0546.md b/compiler/rustc_error_codes/src/error_codes/E0546.md index 11f2bebba43ff..0073357b5ea84 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0546.md +++ b/compiler/rustc_error_codes/src/error_codes/E0546.md @@ -19,10 +19,10 @@ To fix the issue you need to provide the `feature` field. #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[unstable(feature = "unstable_fn", issue = "none")] // ok!! +#[unstable(feature = "unstable_fn", issue = "none")] // ok! fn unstable_fn() {} -#[stable(feature = "stable_fn", since = "1.0.0")] // ok!! +#[stable(feature = "stable_fn", since = "1.0.0")] // ok! fn stable_fn() {} ``` From d2a3c04c3788af5067037516f78251064aabe30f Mon Sep 17 00:00:00 2001 From: bstrie <865233+bstrie@users.noreply.github.com> Date: Sat, 6 Feb 2021 16:58:52 -0500 Subject: [PATCH 10/10] Add regression test for #29821 Closes #29821 --- src/test/ui/issues/issue-29821.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/ui/issues/issue-29821.rs diff --git a/src/test/ui/issues/issue-29821.rs b/src/test/ui/issues/issue-29821.rs new file mode 100644 index 0000000000000..54be3afb59d0a --- /dev/null +++ b/src/test/ui/issues/issue-29821.rs @@ -0,0 +1,19 @@ +// build-pass + +pub trait Foo { + type FooAssoc; +} + +pub struct Bar { + id: F::FooAssoc +} + +pub struct Baz; + +impl Foo for Baz { + type FooAssoc = usize; +} + +static mut MY_FOO: Bar = Bar { id: 0 }; + +fn main() {}