From 6d43225bfb08ec91f7476b76c7fec632c4a096ef Mon Sep 17 00:00:00 2001 From: Yechan Bae Date: Wed, 3 Feb 2021 16:36:33 -0500 Subject: Fixes #80335 --- library/alloc/src/str.rs | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 70e0c7dba5e..a7584c6b651 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -90,8 +90,8 @@ impl> Join<&str> for [S] { } } -macro_rules! spezialize_for_lengths { - ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => { +macro_rules! specialize_for_lengths { + ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{ let mut target = $target; let iter = $iter; let sep_bytes = $separator; @@ -102,7 +102,8 @@ macro_rules! spezialize_for_lengths { $num => { for s in iter { copy_slice_and_advance!(target, sep_bytes); - copy_slice_and_advance!(target, s.borrow().as_ref()); + let content_bytes = s.borrow().as_ref(); + copy_slice_and_advance!(target, content_bytes); } }, )* @@ -110,11 +111,13 @@ macro_rules! spezialize_for_lengths { // arbitrary non-zero size fallback for s in iter { copy_slice_and_advance!(target, sep_bytes); - copy_slice_and_advance!(target, s.borrow().as_ref()); + let content_bytes = s.borrow().as_ref(); + copy_slice_and_advance!(target, content_bytes); } } } - }; + target + }} } macro_rules! copy_slice_and_advance { @@ -153,7 +156,7 @@ where // if the `len` calculation overflows, we'll panic // we would have run out of memory anyway and the rest of the function requires // the entire Vec pre-allocated for safety - let len = sep_len + let reserved_len = sep_len .checked_mul(iter.len()) .and_then(|n| { slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add) @@ -161,22 +164,25 @@ where .expect("attempt to join into collection with len > usize::MAX"); // crucial for safety - let mut result = Vec::with_capacity(len); - assert!(result.capacity() >= len); + let mut result = Vec::with_capacity(reserved_len); + debug_assert!(result.capacity() >= reserved_len); result.extend_from_slice(first.borrow().as_ref()); unsafe { - { - let pos = result.len(); - let target = result.get_unchecked_mut(pos..len); - - // copy separator and slices over without bounds checks - // generate loops with hardcoded offsets for small separators - // massive improvements possible (~ x2) - spezialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4); - } - result.set_len(len); + let pos = result.len(); + let target = result.get_unchecked_mut(pos..reserved_len); + + // copy separator and slices over without bounds checks + // generate loops with hardcoded offsets for small separators + // massive improvements possible (~ x2) + let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4); + + // issue #80335: A weird borrow implementation can return different + // slices for the length calculation and the actual copy, so + // `remain.len()` might be non-zero. + let result_len = reserved_len - remain.len(); + result.set_len(result_len); } result } -- cgit 1.4.1-3-g733a5 From 6233f3f4a391b9ef562e77dc4fb857ffaa4ca410 Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Sat, 20 Feb 2021 15:22:48 +0200 Subject: alloc: Added `as_slice` method to `BinaryHeap` collection --- library/alloc/src/collections/binary_heap.rs | 23 +++++++++++++++++++++++ library/alloc/tests/lib.rs | 1 + 2 files changed, 24 insertions(+) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 8a36b2af765..7a43a3a868b 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -889,6 +889,29 @@ impl BinaryHeap { self.data.shrink_to(min_capacity) } + /// Returns a slice of all values in the underlying vector, in arbitrary + /// order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_as_slice)] + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]); + /// let slice = heap.as_slice(); + /// + /// // Will print in some order + /// for x in slice { + /// println!("{}", x); + /// } + /// ``` + #[unstable(feature = "binary_heap_as_slice", issue = "82331")] + pub fn as_slice(&self) -> &[T] { + self.data.as_slice() + } + /// Consumes the `BinaryHeap` and returns the underlying vector /// in arbitrary order. /// diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index dd98f806451..4679121c929 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -15,6 +15,7 @@ #![feature(binary_heap_drain_sorted)] #![feature(slice_ptr_get)] #![feature(binary_heap_retain)] +#![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] #![feature(iter_map_while)] #![feature(int_bits_const)] -- cgit 1.4.1-3-g733a5 From e7f340e19be8a4d50214c364aabb5577b6b38e9f Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 16 Feb 2021 17:13:43 +0100 Subject: BTree: move blocks around in node.rs --- library/alloc/src/collections/btree/node.rs | 332 ++++++++++++++-------------- 1 file changed, 165 insertions(+), 167 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 9a7119470f3..f330a1bb3dc 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -128,106 +128,6 @@ impl InternalNode { /// is not a separate type and has no destructor. type BoxedNode = NonNull>; -/// The root node of an owned tree. -/// -/// Note that this does not have a destructor, and must be cleaned up manually. -pub type Root = NodeRef; - -impl Root { - /// Returns a new owned tree, with its own root node that is initially empty. - pub fn new() -> Self { - NodeRef::new_leaf().forget_type() - } -} - -impl NodeRef { - fn new_leaf() -> Self { - Self::from_new_leaf(LeafNode::new()) - } - - fn from_new_leaf(leaf: Box>) -> Self { - NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } - } -} - -impl NodeRef { - fn new_internal(child: Root) -> Self { - let mut new_node = unsafe { InternalNode::new() }; - new_node.edges[0].write(child.node); - unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } - } - - /// # Safety - /// `height` must not be zero. - unsafe fn from_new_internal(internal: Box>, height: usize) -> Self { - debug_assert!(height > 0); - let node = NonNull::from(Box::leak(internal)).cast(); - let mut this = NodeRef { height, node, _marker: PhantomData }; - this.borrow_mut().correct_all_childrens_parent_links(); - this - } -} - -impl NodeRef { - /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe - /// because the return value cannot be used to destroy the root, and there - /// cannot be other references to the tree. - pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Slightly mutably borrows the owned root node. - pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Irreversibly transitions to a reference that permits traversal and offers - /// destructive methods and little else. - pub fn into_dying(self) -> NodeRef { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - -impl NodeRef { - /// Adds a new internal node with a single edge pointing to the previous root node, - /// make that new node the root node, and return it. This increases the height by 1 - /// and is the opposite of `pop_internal_level`. - pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { - super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type()); - - // `self.borrow_mut()`, except that we just forgot we're internal now: - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Removes the internal root node, using its first child as the new root node. - /// As it is intended only to be called when the root node has only one child, - /// no cleanup is done on any of the keys, values and other children. - /// This decreases the height by 1 and is the opposite of `push_internal_level`. - /// - /// Requires exclusive access to the `Root` object but not to the root node; - /// it will not invalidate other handles or references to the root node. - /// - /// Panics if there is no internal level, i.e., if the root node is a leaf. - pub fn pop_internal_level(&mut self) { - assert!(self.height > 0); - - let top = self.node; - - // SAFETY: we asserted to be internal. - let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; - // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. - let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; - // SAFETY: the first edge is always initialized. - self.node = unsafe { internal_node.edges[0].assume_init_read() }; - self.height -= 1; - self.clear_parent_link(); - - unsafe { - Global.deallocate(top.cast(), Layout::new::>()); - } - } -} - // N.B. `NodeRef` is always covariant in `K` and `V`, even when the `BorrowType` // is `Mut`. This is technically wrong, but cannot result in any unsafety due to // internal use of `NodeRef` because we stay completely generic over `K` and `V`. @@ -292,6 +192,11 @@ pub struct NodeRef { _marker: PhantomData<(BorrowType, Type)>, } +/// The root node of an owned tree. +/// +/// Note that this does not have a destructor, and must be cleaned up manually. +pub type Root = NodeRef; + impl<'a, K: 'a, V: 'a, Type> Copy for NodeRef, K, V, Type> {} impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef, K, V, Type> { fn clone(&self) -> Self { @@ -307,6 +212,34 @@ unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef Send for NodeRef {} unsafe impl Send for NodeRef {} +impl NodeRef { + fn new_leaf() -> Self { + Self::from_new_leaf(LeafNode::new()) + } + + fn from_new_leaf(leaf: Box>) -> Self { + NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } + } +} + +impl NodeRef { + fn new_internal(child: Root) -> Self { + let mut new_node = unsafe { InternalNode::new() }; + new_node.edges[0].write(child.node); + unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } + } + + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal(internal: Box>, height: usize) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { height, node, _marker: PhantomData }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } +} + impl NodeRef { /// Unpack a node reference that was packed as `NodeRef::parent`. fn from_internal(node: NonNull>, height: usize) -> Self { @@ -420,6 +353,19 @@ impl NodeRef } } +impl NodeRef { + /// Could be a public implementation of PartialEq, but only used in this module. + fn eq(&self, other: &Self) -> bool { + let Self { node, height, _marker } = self; + if node.eq(&other.node) { + debug_assert_eq!(*height, other.height); + true + } else { + false + } + } +} + impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// Exposes the leaf portion of any leaf or internal node in an immutable tree. fn into_leaf(self) -> &'a LeafNode { @@ -461,20 +407,6 @@ impl NodeRef { } } -impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { - /// Unsafely asserts to the compiler the static information that this node is a `Leaf`. - unsafe fn cast_to_leaf_unchecked(self) -> NodeRef, K, V, marker::Leaf> { - debug_assert!(self.height == 0); - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } - - /// Unsafely asserts to the compiler the static information that this node is an `Internal`. - unsafe fn cast_to_internal_unchecked(self) -> NodeRef, K, V, marker::Internal> { - debug_assert!(self.height > 0); - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - impl<'a, K, V, Type> NodeRef, K, V, Type> { /// Temporarily takes out another, mutable reference to the same node. Beware, as /// this method is very dangerous, doubly so since it may not immediately appear @@ -577,6 +509,22 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { } } +impl<'a, K, V> NodeRef, K, V, marker::Internal> { + /// # Safety + /// Every item returned by `range` is a valid edge index for the node. + unsafe fn correct_childrens_parent_links>(&mut self, range: R) { + for i in range { + debug_assert!(i <= self.len()); + unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); + } + } + + fn correct_all_childrens_parent_links(&mut self) { + let len = self.len(); + unsafe { self.correct_childrens_parent_links(0..=len) }; + } +} + impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { /// Sets the node's link to its parent edge, /// without invalidating other references to the node. @@ -596,6 +544,71 @@ impl NodeRef { } } +impl NodeRef { + /// Returns a new owned tree, with its own root node that is initially empty. + pub fn new() -> Self { + NodeRef::new_leaf().forget_type() + } + + /// Adds a new internal node with a single edge pointing to the previous root node, + /// make that new node the root node, and return it. This increases the height by 1 + /// and is the opposite of `pop_internal_level`. + pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { + super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type()); + + // `self.borrow_mut()`, except that we just forgot we're internal now: + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Removes the internal root node, using its first child as the new root node. + /// As it is intended only to be called when the root node has only one child, + /// no cleanup is done on any of the keys, values and other children. + /// This decreases the height by 1 and is the opposite of `push_internal_level`. + /// + /// Requires exclusive access to the `Root` object but not to the root node; + /// it will not invalidate other handles or references to the root node. + /// + /// Panics if there is no internal level, i.e., if the root node is a leaf. + pub fn pop_internal_level(&mut self) { + assert!(self.height > 0); + + let top = self.node; + + // SAFETY: we asserted to be internal. + let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; + // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. + let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; + // SAFETY: the first edge is always initialized. + self.node = unsafe { internal_node.edges[0].assume_init_read() }; + self.height -= 1; + self.clear_parent_link(); + + unsafe { + Global.deallocate(top.cast(), Layout::new::>()); + } + } +} + +impl NodeRef { + /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe + /// because the return value cannot be used to destroy the root, and there + /// cannot be other references to the tree. + pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Slightly mutably borrows the owned root node. + pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Irreversibly transitions to a reference that permits traversal and offers + /// destructive methods and little else. + pub fn into_dying(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { /// Adds a key-value pair to the end of the node. pub fn push(&mut self, key: K, val: V) { @@ -610,22 +623,6 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { } } -impl<'a, K, V> NodeRef, K, V, marker::Internal> { - /// # Safety - /// Every item returned by `range` is a valid edge index for the node. - unsafe fn correct_childrens_parent_links>(&mut self, range: R) { - for i in range { - debug_assert!(i <= self.len()); - unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); - } - } - - fn correct_all_childrens_parent_links(&mut self) { - let len = self.len(); - unsafe { self.correct_childrens_parent_links(0..=len) }; - } -} - impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { /// Adds a key-value pair, and an edge to go to the right of that pair, /// to the end of the node. @@ -645,6 +642,20 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } } +impl NodeRef { + /// Removes any static information asserting that this node is a `Leaf` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Removes any static information asserting that this node is an `Internal` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + impl NodeRef { /// Checks whether a node is an `Internal` node or a `Leaf` node. pub fn force( @@ -669,6 +680,20 @@ impl NodeRef { } } +impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { + /// Unsafely asserts to the compiler the static information that this node is a `Leaf`. + unsafe fn cast_to_leaf_unchecked(self) -> NodeRef, K, V, marker::Leaf> { + debug_assert!(self.height == 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Unsafely asserts to the compiler the static information that this node is an `Internal`. + unsafe fn cast_to_internal_unchecked(self) -> NodeRef, K, V, marker::Internal> { + debug_assert!(self.height > 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + /// A reference to a specific key-value pair or edge within a node. The `Node` parameter /// must be a `NodeRef`, while the `Type` can either be `KV` (signifying a handle on a key-value /// pair) or `Edge` (signifying a handle on an edge). @@ -722,19 +747,6 @@ impl Handle, mar } } -impl NodeRef { - /// Could be a public implementation of PartialEq, but only used in this module. - fn eq(&self, other: &Self) -> bool { - let Self { node, height, _marker } = self; - if node.eq(&other.node) { - debug_assert_eq!(*height, other.height); - true - } else { - false - } - } -} - impl PartialEq for Handle, HandleType> { @@ -754,16 +766,6 @@ impl } } -impl<'a, K, V, Type> Handle, K, V, marker::LeafOrInternal>, Type> { - /// Unsafely asserts to the compiler the static information that the handle's node is a `Leaf`. - pub unsafe fn cast_to_leaf_unchecked( - self, - ) -> Handle, K, V, marker::Leaf>, Type> { - let node = unsafe { self.node.cast_to_leaf_unchecked() }; - Handle { node, idx: self.idx, _marker: PhantomData } - } -} - impl<'a, K, V, NodeType, HandleType> Handle, K, V, NodeType>, HandleType> { /// Temporarily takes out another, mutable handle on the same location. Beware, as /// this method is very dangerous, doubly so since it may not immediately appear @@ -1466,20 +1468,6 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { } } -impl NodeRef { - /// Removes any static information asserting that this node is a `Leaf` node. - pub fn forget_type(self) -> NodeRef { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - -impl NodeRef { - /// Removes any static information asserting that this node is an `Internal` node. - pub fn forget_type(self) -> NodeRef { - NodeRef { height: self.height, node: self.node, _marker: PhantomData } - } -} - impl Handle, marker::Edge> { pub fn forget_node_type( self, @@ -1531,6 +1519,16 @@ impl Handle Handle, K, V, marker::LeafOrInternal>, Type> { + /// Unsafely asserts to the compiler the static information that the handle's node is a `Leaf`. + pub unsafe fn cast_to_leaf_unchecked( + self, + ) -> Handle, K, V, marker::Leaf>, Type> { + let node = unsafe { self.node.cast_to_leaf_unchecked() }; + Handle { node, idx: self.idx, _marker: PhantomData } + } +} + impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { /// Move the suffix after `self` from one node to another one. `right` must be empty. /// The first edge of `right` remains unchanged. -- cgit 1.4.1-3-g733a5 From dd2b8a0444a957b9d1d6481abd38b025c855d79d Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Sat, 13 Mar 2021 17:21:56 +0200 Subject: provide a more realistic example for BinaryHeap::as_slice --- library/alloc/src/collections/binary_heap.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 7a43a3a868b..ed32ff496c6 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -899,13 +899,11 @@ impl BinaryHeap { /// ``` /// #![feature(binary_heap_as_slice)] /// use std::collections::BinaryHeap; + /// use std::io::{self, Write}; + /// /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]); - /// let slice = heap.as_slice(); /// - /// // Will print in some order - /// for x in slice { - /// println!("{}", x); - /// } + /// io::sink().write(heap.as_slice()).unwrap(); /// ``` #[unstable(feature = "binary_heap_as_slice", issue = "82331")] pub fn as_slice(&self) -> &[T] { -- cgit 1.4.1-3-g733a5 From 33d22f84000eca68397ba50d5481cfb11ce35145 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 15 Mar 2021 15:34:22 +0100 Subject: BTree: clarify order sanity enforced by range searches --- library/alloc/src/collections/btree/map.rs | 6 ++++++ library/alloc/src/collections/btree/navigate.rs | 15 +++++++++++---- library/alloc/src/collections/btree/search.rs | 15 ++++++++++++--- 3 files changed, 29 insertions(+), 7 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 622983996aa..40f3d5510cd 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1018,6 +1018,9 @@ impl BTreeMap { /// /// Panics if range `start > end`. /// Panics if range `start == end` and both bounds are `Excluded`. + /// May panic if the [`Ord`] implementation of type `T` is ill-defined, + /// either because it does not form a total order or because it does not + /// correspond to the [`Ord`] implementation of type `K`. /// /// # Examples /// @@ -1061,6 +1064,9 @@ impl BTreeMap { /// /// Panics if range `start > end`. /// Panics if range `start == end` and both bounds are `Excluded`. + /// May panic if the [`Ord`] implementation of type `T` is ill-defined, + /// either because it does not form a total order or because it does not + /// correspond to the [`Ord`] implementation of type `K`. /// /// # Examples /// diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index c2c99a9360c..4399feaccc9 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -29,11 +29,18 @@ impl LeafRange { impl NodeRef { /// Finds the distinct leaf edges delimiting a specified range in a tree. - /// Returns either a pair of different handles into the same tree or a pair - /// of empty options. + /// + /// If such distinct edges exist, returns them in ascending order, meaning + /// that a non-zero number of calls to `next_unchecked` on the `front` of + /// the result and/or calls to `next_back_unchecked` on the `back` of the + /// result will eventually reach the same edge. + /// + /// If there are no such edges, i.e., if the tree contains no key within + /// the range, returns a pair of empty options. + /// /// # Safety - /// Unless `BorrowType` is `Immut`, do not use the duplicate handles to - /// visit the same KV twice. + /// Unless `BorrowType` is `Immut`, do not use the handles to visit the same + /// KV twice. unsafe fn find_leaf_edges_spanning_range( self, range: R, diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs index f376b3cde02..7443db95203 100644 --- a/library/alloc/src/collections/btree/search.rs +++ b/library/alloc/src/collections/btree/search.rs @@ -68,13 +68,18 @@ impl NodeRef( mut self, @@ -115,6 +120,10 @@ impl NodeRef upper_edge_idx { + // Since we already checked the range bounds, this can only + // happen if `Q: Ord` does not implement a total order or does + // not correspond to the `K: Ord` implementation that is used + // while populating the tree. panic!("Ord is ill-defined in BTreeMap range") } if lower_edge_idx < upper_edge_idx { -- cgit 1.4.1-3-g733a5 From fd6e4e41b7608c6fcdd34aedfc2d88b27b1ada05 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Thu, 18 Mar 2021 08:22:04 +0100 Subject: BTree: no longer search arrays twice to check Ord --- library/alloc/src/collections/btree/map.rs | 6 --- library/alloc/src/collections/btree/map/tests.rs | 2 - library/alloc/src/collections/btree/search.rs | 52 ++++++++++++------------ 3 files changed, 27 insertions(+), 33 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 40f3d5510cd..622983996aa 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1018,9 +1018,6 @@ impl BTreeMap { /// /// Panics if range `start > end`. /// Panics if range `start == end` and both bounds are `Excluded`. - /// May panic if the [`Ord`] implementation of type `T` is ill-defined, - /// either because it does not form a total order or because it does not - /// correspond to the [`Ord`] implementation of type `K`. /// /// # Examples /// @@ -1064,9 +1061,6 @@ impl BTreeMap { /// /// Panics if range `start > end`. /// Panics if range `start == end` and both bounds are `Excluded`. - /// May panic if the [`Ord`] implementation of type `T` is ill-defined, - /// either because it does not form a total order or because it does not - /// correspond to the [`Ord`] implementation of type `K`. /// /// # Examples /// diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index e636e490e1b..3a74b6a6fa8 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -776,7 +776,6 @@ fn test_range_backwards_4() { } #[test] -#[should_panic] fn test_range_finding_ill_order_in_map() { let mut map = BTreeMap::new(); map.insert(Cyclic3::B, ()); @@ -789,7 +788,6 @@ fn test_range_finding_ill_order_in_map() { } #[test] -#[should_panic] fn test_range_finding_ill_order_in_range_ord() { // Has proper order the first time asked, then flips around. struct EvilTwin(i32); diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs index 7443db95203..62a048e61c6 100644 --- a/library/alloc/src/collections/btree/search.rs +++ b/library/alloc/src/collections/btree/search.rs @@ -76,9 +76,7 @@ impl NodeRef( @@ -118,14 +116,8 @@ impl NodeRef upper_edge_idx { - // Since we already checked the range bounds, this can only - // happen if `Q: Ord` does not implement a total order or does - // not correspond to the `K: Ord` implementation that is used - // while populating the tree. - panic!("Ord is ill-defined in BTreeMap range") - } + let (upper_edge_idx, upper_child_bound) = + unsafe { self.find_upper_bound_index(upper_bound, lower_edge_idx) }; if lower_edge_idx < upper_edge_idx { return Ok(( self, @@ -135,6 +127,7 @@ impl NodeRef return Err(common_edge), @@ -174,7 +167,7 @@ impl NodeRef, { - let (edge_idx, bound) = self.find_upper_bound_index(bound); + let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) }; let edge = unsafe { Handle::new_edge(self, edge_idx) }; (edge, bound) } @@ -193,29 +186,33 @@ impl NodeRef { Q: Ord, K: Borrow, { - match self.find_key_index(key) { + match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }), IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }), } } /// Returns either the KV index in the node at which the key (or an equivalent) - /// exists, or the edge index where the key belongs. + /// exists, or the edge index where the key belongs, starting from a particular index. /// /// The result is meaningful only if the tree is ordered by key, like the tree /// in a `BTreeMap` is. - fn find_key_index(&self, key: &Q) -> IndexResult + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_key_index(&self, key: &Q, start_index: usize) -> IndexResult where Q: Ord, K: Borrow, { let node = self.reborrow(); let keys = node.keys(); - for (i, k) in keys.iter().enumerate() { + debug_assert!(start_index <= keys.len()); + for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() { match key.cmp(k.borrow()) { Ordering::Greater => {} - Ordering::Equal => return IndexResult::KV(i), - Ordering::Less => return IndexResult::Edge(i), + Ordering::Equal => return IndexResult::KV(start_index + offset), + Ordering::Less => return IndexResult::Edge(start_index + offset), } } IndexResult::Edge(keys.len()) @@ -235,11 +232,11 @@ impl NodeRef { K: Borrow, { match bound { - Included(key) => match self.find_key_index(key) { + Included(key) => match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => (idx, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, - Excluded(key) => match self.find_key_index(key) { + Excluded(key) => match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => (idx + 1, AllIncluded), IndexResult::Edge(idx) => (idx, bound), }, @@ -248,26 +245,31 @@ impl NodeRef { } } - /// Clone of `find_lower_bound_index` for the upper bound. - fn find_upper_bound_index<'r, Q>( + /// Mirror image of `find_lower_bound_index` for the upper bound, + /// with an additional parameter to skip part of the key array. + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_upper_bound_index<'r, Q>( &self, bound: SearchBound<&'r Q>, + start_index: usize, ) -> (usize, SearchBound<&'r Q>) where Q: ?Sized + Ord, K: Borrow, { match bound { - Included(key) => match self.find_key_index(key) { + Included(key) => match unsafe { self.find_key_index(key, start_index) } { IndexResult::KV(idx) => (idx + 1, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, - Excluded(key) => match self.find_key_index(key) { + Excluded(key) => match unsafe { self.find_key_index(key, start_index) } { IndexResult::KV(idx) => (idx, AllIncluded), IndexResult::Edge(idx) => (idx, bound), }, AllIncluded => (self.len(), AllIncluded), - AllExcluded => (0, AllExcluded), + AllExcluded => (start_index, AllExcluded), } } } -- cgit 1.4.1-3-g733a5 From 26a62701e42d10c03ce5f2f911e7d5edeefa2f0f Mon Sep 17 00:00:00 2001 From: Yechan Bae Date: Sat, 20 Mar 2021 13:42:54 -0400 Subject: Update the comment --- library/alloc/src/str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index a7584c6b651..4d1e876457b 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -163,7 +163,7 @@ where }) .expect("attempt to join into collection with len > usize::MAX"); - // crucial for safety + // prepare an uninitialized buffer let mut result = Vec::with_capacity(reserved_len); debug_assert!(result.capacity() >= reserved_len); @@ -178,9 +178,9 @@ where // massive improvements possible (~ x2) let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4); - // issue #80335: A weird borrow implementation can return different - // slices for the length calculation and the actual copy, so - // `remain.len()` might be non-zero. + // A weird borrow implementation may return different + // slices for the length calculation and the actual copy. + // Make sure we don't expose uninitialized bytes to the caller. let result_len = reserved_len - remain.len(); result.set_len(result_len); } -- cgit 1.4.1-3-g733a5 From f5e37100d9c115ab327bafd42d0c4dad539d318f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 21 Mar 2021 17:47:57 -0400 Subject: Mark RawVec::reserve as inline and outline the resizing logic --- library/alloc/src/raw_vec.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 56f4ebe57f8..ff7bff7584a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -315,8 +315,20 @@ impl RawVec { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` + #[inline] pub fn reserve(&mut self, len: usize, additional: usize) { - handle_reserve(self.try_reserve(len, additional)); + // Callers expect this function to be very cheap when there is already sufficient capacity. + // Therefore, we move all the resizing and error-handling logic from grow_amortized and + // handle_reserve behind a call, while making sure that the this function is likely to be + // inlined as just a comparison and a call if the comparison fails. + #[inline(never)] + fn do_reserve_and_handle(slf: &mut RawVec, len: usize, additional: usize) { + handle_reserve(slf.grow_amortized(len, additional)); + } + + if self.needs_to_grow(len, additional) { + do_reserve_and_handle(self, len, additional); + } } /// The same as `reserve`, but returns on errors instead of panicking or aborting. -- cgit 1.4.1-3-g733a5 From 73d773482afcceb8475dd773c4e2e70ed4835242 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 21 Mar 2021 19:17:07 -0400 Subject: fmt, change to cold --- library/alloc/src/raw_vec.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index ff7bff7584a..dc02c9c883e 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -321,8 +321,12 @@ impl RawVec { // Therefore, we move all the resizing and error-handling logic from grow_amortized and // handle_reserve behind a call, while making sure that the this function is likely to be // inlined as just a comparison and a call if the comparison fails. - #[inline(never)] - fn do_reserve_and_handle(slf: &mut RawVec, len: usize, additional: usize) { + #[cold] + fn do_reserve_and_handle( + slf: &mut RawVec, + len: usize, + additional: usize, + ) { handle_reserve(slf.grow_amortized(len, additional)); } -- cgit 1.4.1-3-g733a5 From 18748c9121f5910075ca4317a78ef11adb639263 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 22 Mar 2021 15:14:24 -0400 Subject: Make # format easier to discover --- library/alloc/src/fmt.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index f9424b1d747..8453f694e1e 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -19,6 +19,10 @@ //! format!("{value}", value=4); // => "4" //! format!("{} {}", 1, 2); // => "1 2" //! format!("{:04}", 42); // => "0042" with leading zeros +//! format!("{:#?}", (100, 200)); // => "( +//! // 100, +//! // 200, +//! // )" //! ``` //! //! From these, you can see that the first argument is a format string. It is @@ -163,7 +167,7 @@ //! * `-` - Currently not used //! * `#` - This flag indicates that the "alternate" form of printing should //! be used. The alternate forms are: -//! * `#?` - pretty-print the [`Debug`] formatting +//! * `#?` - pretty-print the [`Debug`] formatting (newline and indent) //! * `#x` - precedes the argument with a `0x` //! * `#X` - precedes the argument with a `0x` //! * `#b` - precedes the argument with a `0b` -- cgit 1.4.1-3-g733a5 From 93737dc634f42d07441db2acf26a88ae2e888d9f Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 22 Mar 2021 17:09:11 -0400 Subject: Update library/alloc/src/fmt.rs --- library/alloc/src/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 8453f694e1e..e765fa9d14c 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -167,7 +167,7 @@ //! * `-` - Currently not used //! * `#` - This flag indicates that the "alternate" form of printing should //! be used. The alternate forms are: -//! * `#?` - pretty-print the [`Debug`] formatting (newline and indent) +//! * `#?` - pretty-print the [`Debug`] formatting (adds linebreaks and indentation) //! * `#x` - precedes the argument with a `0x` //! * `#X` - precedes the argument with a `0x` //! * `#b` - precedes the argument with a `0b` -- cgit 1.4.1-3-g733a5 From 6fdb8d8b360b91a10045fe74467b98d218b7ffe9 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 31 Oct 2020 17:21:23 -0700 Subject: Update signed fmt/-0f32 docs "semantic equivalence" is too strong a phrasing here, which is why actually explaining what kind of circumstances might produce a -0 was chosen instead. --- library/alloc/src/fmt.rs | 5 ++--- library/std/src/primitive_docs.rs | 8 +++++--- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index f9424b1d747..439b0adde20 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -157,9 +157,8 @@ //! //! * `+` - This is intended for numeric types and indicates that the sign //! should always be printed. Positive signs are never printed by -//! default, and the negative sign is only printed by default for the -//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`) -//! should always be printed. +//! default, and the negative sign is only printed by default for signed values. +//! This flag indicates that the correct sign (`+` or `-`) should always be printed. //! * `-` - Currently not used //! * `#` - This flag indicates that the "alternate" form of printing should //! be used. The alternate forms are: diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index d4bb2083d00..b48718df31c 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -805,10 +805,12 @@ mod prim_tuple {} /// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will /// print `0.2`. /// -/// Additionally, `f32` can represent a couple of special values: +/// Additionally, `f32` can represent some special values: /// -/// - `-0`: this is just due to how floats are encoded. It is semantically -/// equivalent to `0` and `-0.0 == 0.0` results in `true`. +/// - `-0`: this value exists due to how floats are encoded. -0 == 0 is true, but for other +/// operations they are not equal and the difference can be useful to certain algorithms. +/// For example, operations on negative numbers that underflow to 0 will usually generate -0 +/// instead of +0. /// - [∞](#associatedconstant.INFINITY) and /// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations /// like `1.0 / 0.0`. -- cgit 1.4.1-3-g733a5 From 3b1f5e34620d6bfa32a127258e2c2d9f2f4d693b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 8 Mar 2021 15:32:41 -0800 Subject: Use iter::zip in library/ --- library/alloc/src/lib.rs | 1 + library/alloc/src/vec/mod.rs | 9 +++------ library/core/src/array/iter.rs | 4 ++-- library/core/src/fmt/mod.rs | 5 +++-- library/core/src/num/bignum.rs | 6 ++++-- library/core/src/slice/ascii.rs | 3 ++- library/std/src/lib.rs | 1 + library/std/src/sys/unix/ext/net/addr.rs | 4 ++-- 8 files changed, 18 insertions(+), 15 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 40f2de8f70d..fb243100990 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -108,6 +108,7 @@ // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] +#![feature(iter_zip)] #![feature(lang_items)] #![feature(layout_for_ptr)] #![feature(maybe_uninit_ref)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ff93c772b5b..708898ad2e7 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -58,7 +58,7 @@ use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; -use core::iter::FromIterator; +use core::iter::{self, FromIterator}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -2268,11 +2268,8 @@ impl ExtendFromWithinSpec for Vec { // - caller guaratees that src is a valid index let to_clone = unsafe { this.get_unchecked(src) }; - to_clone - .iter() - .cloned() - .zip(spare.iter_mut()) - .map(|(src, dst)| dst.write(src)) + iter::zip(to_clone, spare) + .map(|(src, dst)| dst.write(src.clone())) // Note: // - Element was just initialized with `MaybeUninit::write`, so it's ok to increace len // - len is increased after each element to prevent leaks (see issue #82533) diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index f82454addd0..c36542f6314 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -2,7 +2,7 @@ use crate::{ fmt, - iter::{ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess}, + iter::{self, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess}, mem::{self, MaybeUninit}, ops::Range, ptr, @@ -215,7 +215,7 @@ impl Clone for IntoIter { let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 }; // Clone all alive elements. - for (src, dst) in self.as_slice().iter().zip(&mut new.data) { + for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { // Write a clone into the new array, then update its alive range. // If cloning panics, we'll correctly drop the previous items. dst.write(src.clone()); diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index d211ad4b2f7..d696ffa8277 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -4,6 +4,7 @@ use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; use crate::char::EscapeDebugExtArgs; +use crate::iter; use crate::marker::PhantomData; use crate::mem; use crate::num::flt2dec; @@ -1088,7 +1089,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { match args.fmt { None => { // We can use default formatting parameters for all arguments. - for (arg, piece) in args.args.iter().zip(args.pieces.iter()) { + for (arg, piece) in iter::zip(args.args, args.pieces) { formatter.buf.write_str(*piece)?; (arg.formatter)(arg.value, &mut formatter)?; idx += 1; @@ -1097,7 +1098,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { Some(fmt) => { // Every spec has a corresponding argument that is preceded by // a string piece. - for (arg, piece) in fmt.iter().zip(args.pieces.iter()) { + for (arg, piece) in iter::zip(fmt, args.pieces) { formatter.buf.write_str(*piece)?; // SAFETY: arg and args.args come from the same Arguments, // which guarantees the indexes are always within bounds. diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 6a1a1e19761..197b85fba1f 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -181,11 +181,12 @@ macro_rules! define_bignum { /// Adds `other` to itself and returns its own mutable reference. pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; + use crate::iter; use crate::num::bignum::FullOps; let mut sz = cmp::max(self.size, other.size); let mut carry = false; - for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) { + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { let (c, v) = (*a).full_add(*b, carry); *a = v; carry = c; @@ -219,11 +220,12 @@ macro_rules! define_bignum { /// Subtracts `other` from itself and returns its own mutable reference. pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; + use crate::iter; use crate::num::bignum::FullOps; let sz = cmp::max(self.size, other.size); let mut noborrow = true; - for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) { + for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { let (c, v) = (*a).full_add(!*b, noborrow); *a = v; noborrow = c; diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 42032bc9035..009ef9e0a9c 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -1,5 +1,6 @@ //! Operations on ASCII `[u8]`. +use crate::iter; use crate::mem; #[lang = "slice_u8"] @@ -19,7 +20,7 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { - self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) } /// Converts this slice to its ASCII upper case equivalent in-place. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8b34fb05055..3719eeb1840 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -278,6 +278,7 @@ #![feature(integer_atomics)] #![feature(into_future)] #![feature(intra_doc_pointers)] +#![feature(iter_zip)] #![feature(lang_items)] #![feature(link_args)] #![feature(linkage)] diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs index 6e7d1f1678a..459f3590e64 100644 --- a/library/std/src/sys/unix/ext/net/addr.rs +++ b/library/std/src/sys/unix/ext/net/addr.rs @@ -2,7 +2,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, mem}; +use crate::{ascii, fmt, io, iter, mem}; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? #[cfg(not(unix))] @@ -41,7 +41,7 @@ pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, &"path must be shorter than SUN_LEN", )); } - for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { + for (dst, src) in iter::zip(&mut addr.sun_path, bytes) { *dst = *src as libc::c_char; } // null byte for pathname addresses is already there because we zeroed the -- cgit 1.4.1-3-g733a5 From d29d87f08bcb495f94b1ebb1b8d1ea197da86dbc Mon Sep 17 00:00:00 2001 From: Violet Date: Sat, 27 Mar 2021 13:45:30 -0400 Subject: update links to make_ascii_lowercase for slice to point to methods on the same type, rather than on u8 --- library/alloc/src/slice.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 8cd4ef7a14e..7cbb88c820d 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -642,7 +642,7 @@ impl [u8] { /// /// To uppercase the value in-place, use [`make_ascii_uppercase`]. /// - /// [`make_ascii_uppercase`]: u8::make_ascii_uppercase + /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> Vec { @@ -659,7 +659,7 @@ impl [u8] { /// /// To lowercase the value in-place, use [`make_ascii_lowercase`]. /// - /// [`make_ascii_lowercase`]: u8::make_ascii_lowercase + /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> Vec { -- cgit 1.4.1-3-g733a5 From 634d48d9d6a27a74400de4bbd7a28147d2665ad1 Mon Sep 17 00:00:00 2001 From: Violet Date: Sat, 27 Mar 2021 14:15:42 -0400 Subject: adjust documentation links for slice ascii case functions to use newer rustdoc link format --- library/alloc/src/slice.rs | 4 ++-- library/core/src/slice/ascii.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 7cbb88c820d..036b84bb1d5 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -642,7 +642,7 @@ impl [u8] { /// /// To uppercase the value in-place, use [`make_ascii_uppercase`]. /// - /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> Vec { @@ -659,7 +659,7 @@ impl [u8] { /// /// To lowercase the value in-place, use [`make_ascii_lowercase`]. /// - /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> Vec { diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 42032bc9035..4249ac77d47 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -30,7 +30,7 @@ impl [u8] { /// To return a new uppercased value without modifying the existing one, use /// [`to_ascii_uppercase`]. /// - /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + /// [`to_ascii_uppercase`]: slice::to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn make_ascii_uppercase(&mut self) { @@ -47,7 +47,7 @@ impl [u8] { /// To return a new lowercased value without modifying the existing one, use /// [`to_ascii_lowercase`]. /// - /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + /// [`to_ascii_lowercase`]: slice::to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn make_ascii_lowercase(&mut self) { -- cgit 1.4.1-3-g733a5 From e051db6838496baf97fc34e63c36c73a6ea1c7f7 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 27 Mar 2021 15:56:07 -0400 Subject: may not -> might not "may not" has two possible meanings: 1. A command: "You may not stay up past your bedtime." 2. A fact that's only sometimes true: "Some cities may not have bike lanes." In some cases, the meaning is ambiguous: "Some cars may not have snow tires." (do the cars *happen* to not have snow tires, or is it physically impossible for them to have snow tires?) This changes places where the standard library uses the "description of fact" meaning to say "might not" instead. This is just `std::vec` for now - if you think this is a good idea I can convert the rest of the standard library. --- library/alloc/src/vec/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 135279874bb..b7b01deb4fc 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -267,12 +267,12 @@ mod spec_extend; /// unspecified, and you should use the appropriate methods to modify these. /// The pointer will never be null, so this type is null-pointer-optimized. /// -/// However, the pointer may not actually point to allocated memory. In particular, +/// However, the pointer might not actually point to allocated memory. In particular, /// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], /// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case -/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only /// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation /// details are very subtle — if you intend to allocate memory using a `Vec` /// and use it for something else (either to pass to unsafe code, or to build your @@ -347,7 +347,7 @@ mod spec_extend; /// whatever is most efficient or otherwise easy to implement. Do not rely on /// removed data to be erased for security purposes. Even if you drop a `Vec`, its /// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory -/// first, that may not actually happen because the optimizer does not consider +/// first, that might not actually happen because the optimizer does not consider /// this a side-effect that must be preserved. There is one case which we will /// not break, however: using `unsafe` code to write to the excess capacity, /// and then increasing the length to match, is always valid. -- cgit 1.4.1-3-g733a5 From 421f5d282a51e130d3ca7c4524d8ad6753437da9 Mon Sep 17 00:00:00 2001 From: The8472 Date: Mon, 29 Mar 2021 04:22:48 +0200 Subject: fix double-drop in in-place collect specialization --- library/alloc/src/vec/into_iter.rs | 27 ++++++++++++++++++--------- library/alloc/src/vec/source_iter_marker.rs | 4 ++-- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index bcbdffabc7f..324e894bafd 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -85,20 +85,29 @@ impl IntoIter { ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) } - pub(super) fn drop_remaining(&mut self) { - unsafe { - ptr::drop_in_place(self.as_mut_slice()); - } - self.ptr = self.end; - } + /// Drops remaining elements and relinquishes the backing allocation. + /// + /// This is roughly equivalent to the following, but more efficient + /// + /// ``` + /// # let mut into_iter = Vec::::with_capacity(10).into_iter(); + /// (&mut into_iter).for_each(core::mem::drop); + /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); } + /// ``` + pub(super) fn forget_allocation_drop_remaining(&mut self) { + let remaining = self.as_raw_mut_slice(); - /// Relinquishes the backing allocation, equivalent to - /// `ptr::write(&mut self, Vec::new().into_iter())` - pub(super) fn forget_allocation(&mut self) { + // overwrite the individual fields instead of creating a new + // struct and then overwriting &mut self. + // this creates less assembly self.cap = 0; self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; self.ptr = self.buf.as_ptr(); self.end = self.buf.as_ptr(); + + unsafe { + ptr::drop_in_place(remaining); + } } } diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index 50882fc1767..e857d284d3a 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -69,9 +69,9 @@ where } // drop any remaining values at the tail of the source - src.drop_remaining(); // but prevent drop of the allocation itself once IntoIter goes out of scope - src.forget_allocation(); + // if the drop panics then we also leak any elements collected into dst_buf + src.forget_allocation_drop_remaining(); let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) }; -- cgit 1.4.1-3-g733a5 From 595f3f25fcc9e11598eb0de2b8bb01022386147c Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Mon, 29 Mar 2021 22:44:48 +0300 Subject: Updated the tracking issue # --- library/alloc/src/collections/binary_heap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index ed32ff496c6..902ef9b123e 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -905,7 +905,7 @@ impl BinaryHeap { /// /// io::sink().write(heap.as_slice()).unwrap(); /// ``` - #[unstable(feature = "binary_heap_as_slice", issue = "82331")] + #[unstable(feature = "binary_heap_as_slice", issue = "83659")] pub fn as_slice(&self) -> &[T] { self.data.as_slice() } -- cgit 1.4.1-3-g733a5 From ad3a791e2a8c0300090fa73d4ce414a738346a41 Mon Sep 17 00:00:00 2001 From: The8472 Date: Wed, 31 Mar 2021 23:09:28 +0200 Subject: panic early when TrustedLen indicates a length > usize::MAX --- library/alloc/src/rc.rs | 7 +++++-- library/alloc/src/sync.rs | 7 +++++-- library/alloc/src/vec/mod.rs | 8 ++++++++ library/alloc/src/vec/spec_extend.rs | 7 ++++++- library/alloc/src/vec/spec_from_iter_nested.rs | 9 ++++++--- 5 files changed, 30 insertions(+), 8 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index dac4acc4692..2ee5e6c791c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1848,8 +1848,11 @@ impl> ToRcSlice for I { Rc::from_iter_exact(self, low) } } else { - // Fall back to normal implementation. - self.collect::>().into() + // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index aeae888dddc..1b7e656cefd 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2481,8 +2481,11 @@ impl> ToArcSlice for I { Arc::from_iter_exact(self, low) } } else { - // Fall back to normal implementation. - self.collect::>().into() + // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); } } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 20c2aae1789..91c3b16deee 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -410,6 +410,10 @@ impl Vec { /// /// [Capacity and reallocation]: #capacity-and-reallocation /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// /// # Examples /// /// ``` @@ -541,6 +545,10 @@ impl Vec { /// /// [Capacity and reallocation]: #capacity-and-reallocation /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// /// # Examples /// /// ``` diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index b6186a7ebaf..e132befcfa5 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -47,7 +47,12 @@ where }); } } else { - self.extend_desugared(iterator) + // Per TrustedLen contract a `None` upper bound means that the iterator length + // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway. + // Since the other branch already panics eagerly (via `reserve()`) we do the same here. + // This avoids additional codegen for a fallback code path which would eventually + // panic anyway. + panic!("capacity overflow"); } } } diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs index ec390c62165..948cf044197 100644 --- a/library/alloc/src/vec/spec_from_iter_nested.rs +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -46,10 +46,13 @@ where fn from_iter(iterator: I) -> Self { let mut vector = match iterator.size_hint() { (_, Some(upper)) => Vec::with_capacity(upper), - _ => Vec::new(), + // TrustedLen contract guarantees that `size_hint() == (_, None)` means that there + // are more than `usize::MAX` elements. + // Since the previous branch would eagerly panic if the capacity is too large + // (via `with_capacity`) we do the same here. + _ => panic!("capacity overflow"), }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs + // reuse extend specialization for TrustedLen vector.spec_extend(iterator); vector } -- cgit 1.4.1-3-g733a5 From b3a4f91b8d16f65e3220f14fc7867fed0cc7d1e7 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 26 Mar 2021 16:10:21 -0400 Subject: Bump cfgs --- compiler/rustc_error_codes/src/lib.rs | 3 +- library/alloc/src/lib.rs | 4 +-- library/core/src/hash/mod.rs | 52 ++++------------------------------- library/core/src/lib.rs | 6 ++-- library/core/src/macros/mod.rs | 2 -- library/core/src/ops/deref.rs | 2 +- library/core/src/prelude/v1.rs | 2 -- library/core/src/ptr/const_ptr.rs | 8 ------ library/core/src/ptr/mod.rs | 45 ------------------------------ library/core/src/ptr/mut_ptr.rs | 8 ------ library/core/src/ptr/non_null.rs | 2 -- library/core/src/slice/mod.rs | 28 ++++++------------- library/core/tests/lib.rs | 5 ++-- library/core/tests/ptr.rs | 7 ----- library/std/src/lib.rs | 3 +- library/std/src/prelude/v1.rs | 2 -- src/bootstrap/builder.rs | 14 ++-------- src/tools/linkchecker/main.rs | 2 -- src/tools/tidy/src/lib.rs | 2 -- 19 files changed, 25 insertions(+), 172 deletions(-) (limited to 'library/alloc/src') diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 14ddb3e2079..f2432f61653 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -1,5 +1,4 @@ -#![cfg_attr(bootstrap, deny(invalid_codeblock_attributes))] -#![cfg_attr(not(bootstrap), deny(rustdoc::invalid_codeblock_attributes))] +#![deny(rustdoc::invalid_codeblock_attributes)] //! This library is used to gather all error codes into one place, //! the goal being to make their maintenance easier. diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index fb243100990..14cb1d3b405 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -133,7 +133,6 @@ #![feature(trusted_len)] #![feature(unboxed_closures)] #![feature(unicode_internals)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] #![feature(unsize)] #![feature(unsized_fn_params)] #![feature(allocator_internals)] @@ -142,8 +141,7 @@ #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] #![feature(try_trait)] -#![cfg_attr(bootstrap, feature(type_alias_impl_trait))] -#![cfg_attr(not(bootstrap), feature(min_type_alias_impl_trait))] +#![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] #![feature(decl_macro)] diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 7bfa58d34ed..0c3303cc210 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -691,29 +691,9 @@ mod impls { impl Hash for *const T { #[inline] fn hash(&self, state: &mut H) { - #[cfg(not(bootstrap))] - { - let (address, metadata) = self.to_raw_parts(); - state.write_usize(address as usize); - metadata.hash(state); - } - #[cfg(bootstrap)] - { - if mem::size_of::() == mem::size_of::() { - // Thin pointer - state.write_usize(*self as *const () as usize); - } else { - // Fat pointer - // SAFETY: we are accessing the memory occupied by `self` - // which is guaranteed to be valid. - // This assumes a fat pointer can be represented by a `(usize, usize)`, - // which is safe to do in `std` because it is shipped and kept in sync - // with the implementation of fat pointers in `rustc`. - let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; - state.write_usize(a); - state.write_usize(b); - } - } + let (address, metadata) = self.to_raw_parts(); + state.write_usize(address as usize); + metadata.hash(state); } } @@ -721,29 +701,9 @@ mod impls { impl Hash for *mut T { #[inline] fn hash(&self, state: &mut H) { - #[cfg(not(bootstrap))] - { - let (address, metadata) = self.to_raw_parts(); - state.write_usize(address as usize); - metadata.hash(state); - } - #[cfg(bootstrap)] - { - if mem::size_of::() == mem::size_of::() { - // Thin pointer - state.write_usize(*self as *const () as usize); - } else { - // Fat pointer - // SAFETY: we are accessing the memory occupied by `self` - // which is guaranteed to be valid. - // This assumes a fat pointer can be represented by a `(usize, usize)`, - // which is safe to do in `std` because it is shipped and kept in sync - // with the implementation of fat pointers in `rustc`. - let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; - state.write_usize(a); - state.write_usize(b); - } - } + let (address, metadata) = self.to_raw_parts(); + state.write_usize(address as usize); + metadata.hash(state); } } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 158b1e152ad..013e98a8660 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -129,7 +129,7 @@ #![feature(auto_traits)] #![cfg_attr(bootstrap, feature(or_patterns))] #![feature(prelude_import)] -#![cfg_attr(not(bootstrap), feature(ptr_metadata))] +#![feature(ptr_metadata)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] #![feature(simd_ffi)] @@ -167,7 +167,6 @@ #![feature(slice_ptr_get)] #![feature(no_niche)] // rust-lang/rust#68303 #![feature(int_error_matching)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] #![deny(unsafe_op_in_unsafe_fn)] #[prelude_import] @@ -299,8 +298,7 @@ pub mod primitive; unused_imports, unsafe_op_in_unsafe_fn )] -#[cfg_attr(bootstrap, allow(non_autolinks))] -#[cfg_attr(not(bootstrap), allow(rustdoc::non_autolinks))] +#[allow(rustdoc::non_autolinks)] // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. #[allow(clashing_extern_declarations)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 99894b5605e..5d9b0f80d3a 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1391,7 +1391,6 @@ pub(crate) mod builtin { } /// Attribute macro used to apply derive macros. - #[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] pub macro derive($item:item) { @@ -1453,7 +1452,6 @@ pub(crate) mod builtin { } /// Expands all `#[cfg]` and `#[cfg_attr]` attributes in the code fragment it's applied to. - #[cfg(not(bootstrap))] #[unstable( feature = "cfg_eval", issue = "82679", diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 10e3ce67448..dcf3ce070ec 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -65,7 +65,7 @@ pub trait Deref { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "deref_target"] - #[cfg_attr(not(bootstrap), lang = "deref_target")] + #[lang = "deref_target"] type Target: ?Sized; /// Dereferences the value. diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 7d33ca8bb69..c89fe57cb05 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -67,7 +67,6 @@ pub use crate::macros::builtin::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::macros::builtin::derive; @@ -80,7 +79,6 @@ pub use crate::macros::builtin::derive; #[doc(no_inline)] pub use crate::macros::builtin::cfg_accessible; -#[cfg(not(bootstrap))] #[unstable( feature = "cfg_eval", issue = "82679", diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 25b8f435acc..f18387d020d 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -51,7 +51,6 @@ impl *const T { /// Decompose a (possibly wide) pointer into is address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -915,13 +914,6 @@ impl *const [T] { #[unstable(feature = "slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { - #[cfg(bootstrap)] - { - // SAFETY: this is safe because `*const [T]` and `FatPtr` have the same layout. - // Only `std` can make this guarantee. - unsafe { Repr { rust: self }.raw }.len - } - #[cfg(not(bootstrap))] metadata(self) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6412bd41a8c..52660116026 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -90,11 +90,8 @@ pub use crate::intrinsics::copy; #[doc(inline)] pub use crate::intrinsics::write_bytes; -#[cfg(not(bootstrap))] mod metadata; -#[cfg(not(bootstrap))] pub(crate) use metadata::PtrRepr; -#[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin}; @@ -236,33 +233,6 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } -#[cfg(bootstrap)] -#[repr(C)] -pub(crate) union Repr { - pub(crate) rust: *const [T], - rust_mut: *mut [T], - pub(crate) raw: FatPtr, -} - -#[cfg(bootstrap)] -#[repr(C)] -pub(crate) struct FatPtr { - data: *const T, - pub(crate) len: usize, -} - -#[cfg(bootstrap)] -// Manual impl needed to avoid `T: Clone` bound. -impl Clone for FatPtr { - fn clone(&self) -> Self { - *self - } -} - -#[cfg(bootstrap)] -// Manual impl needed to avoid `T: Copy` bound. -impl Copy for FatPtr {} - /// Forms a raw slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. @@ -287,14 +257,6 @@ impl Copy for FatPtr {} #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { - #[cfg(bootstrap)] - { - // SAFETY: Accessing the value from the `Repr` union is safe since *const [T] - // and FatPtr have the same memory layouts. Only std can make this - // guarantee. - unsafe { Repr { raw: FatPtr { data, len } }.rust } - } - #[cfg(not(bootstrap))] from_raw_parts(data.cast(), len) } @@ -327,13 +289,6 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { - #[cfg(bootstrap)] - { - // SAFETY: Accessing the value from the `Repr` union is safe since *mut [T] - // and FatPtr have the same memory layouts - unsafe { Repr { raw: FatPtr { data, len } }.rust_mut } - } - #[cfg(not(bootstrap))] from_raw_parts_mut(data.cast(), len) } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 732e1273b4b..3c6f1978283 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -50,7 +50,6 @@ impl *mut T { /// Decompose a (possibly wide) pointer into is address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -1175,13 +1174,6 @@ impl *mut [T] { #[unstable(feature = "slice_ptr_len", issue = "71146")] #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { - #[cfg(bootstrap)] - { - // SAFETY: this is safe because `*const [T]` and `FatPtr` have the same layout. - // Only `std` can make this guarantee. - unsafe { Repr { rust_mut: self }.raw }.len - } - #[cfg(not(bootstrap))] metadata(self) } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 83b88ffd916..e525f616043 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -181,7 +181,6 @@ impl NonNull { /// See the documentation of [`std::ptr::from_raw_parts`] for more details. /// /// [`std::ptr::from_raw_parts`]: crate::ptr::from_raw_parts - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] @@ -198,7 +197,6 @@ impl NonNull { /// Decompose a (possibly wide) pointer into is address and metadata components. /// /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] #[inline] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e4b1bffcfe0..ec28cdd1ba0 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -102,23 +102,14 @@ impl [T] { // SAFETY: const sound because we transmute out the length field as a usize (which it must be) #[rustc_allow_const_fn_unstable(const_fn_union)] pub const fn len(&self) -> usize { - #[cfg(bootstrap)] - { - // SAFETY: this is safe because `&[T]` and `FatPtr` have the same layout. - // Only `std` can make this guarantee. - unsafe { crate::ptr::Repr { rust: self }.raw.len } - } - #[cfg(not(bootstrap))] - { - // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. - // As of this writing this causes a "Const-stable functions can only call other - // const-stable functions" error. - - // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T - // and PtrComponents have the same memory layouts. Only std can make this - // guarantee. - unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata } - } + // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. + // As of this writing this causes a "Const-stable functions can only call other + // const-stable functions" error. + + // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T + // and PtrComponents have the same memory layouts. Only std can make this + // guarantee. + unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata } } /// Returns `true` if the slice has a length of 0. @@ -2265,8 +2256,7 @@ impl [T] { // in crate `alloc`, and as such doesn't exists yet when building `core`. // links to downstream crate: #74481. Since primitives are only documented in // libstd (#73423), this never leads to broken links in practice. - #[cfg_attr(not(bootstrap), allow(rustdoc::broken_intra_doc_links))] - #[cfg_attr(bootstrap, allow(broken_intra_doc_links))] + #[allow(rustdoc::broken_intra_doc_links)] #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] #[inline] pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 997e618cc51..1d885eb1092 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -68,7 +68,7 @@ #![feature(option_result_unwrap_unchecked)] #![feature(result_into_ok_or_err)] #![feature(peekable_peek_mut)] -#![cfg_attr(not(bootstrap), feature(ptr_metadata))] +#![feature(ptr_metadata)] #![feature(once_cell)] #![feature(unsized_tuple_coercion)] #![feature(nonzero_leading_trailing_zeros)] @@ -76,8 +76,7 @@ #![feature(integer_atomics)] #![feature(slice_group_by)] #![feature(trusted_random_access)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] -#![cfg_attr(not(bootstrap), feature(unsize))] +#![feature(unsize)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 224a58e3ccd..11af8090c3a 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1,8 +1,6 @@ use core::cell::RefCell; -#[cfg(not(bootstrap))] use core::ptr; use core::ptr::*; -#[cfg(not(bootstrap))] use std::fmt::{Debug, Display}; #[test] @@ -419,7 +417,6 @@ fn offset_from() { } #[test] -#[cfg(not(bootstrap))] fn ptr_metadata() { struct Unit; struct Pair(A, B); @@ -478,7 +475,6 @@ fn ptr_metadata() { } #[test] -#[cfg(not(bootstrap))] fn ptr_metadata_bounds() { fn metadata_eq_method_address() -> usize { // The `Metadata` associated type has an `Ord` bound, so this is valid: @@ -510,7 +506,6 @@ fn ptr_metadata_bounds() { } #[test] -#[cfg(not(bootstrap))] fn dyn_metadata() { #[derive(Debug)] #[repr(align(32))] @@ -530,7 +525,6 @@ fn dyn_metadata() { } #[test] -#[cfg(not(bootstrap))] fn from_raw_parts() { let mut value = 5_u32; let address = &mut value as *mut _ as *mut (); @@ -557,7 +551,6 @@ fn from_raw_parts() { } #[test] -#[cfg(not(bootstrap))] fn thin_box() { let foo = ThinBox::::new(4); assert_eq!(foo.to_string(), "4"); diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6ab68100b1d..c983022746c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -234,7 +234,7 @@ #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_accessible)] -#![cfg_attr(not(bootstrap), feature(cfg_eval))] +#![feature(cfg_eval)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] @@ -331,7 +331,6 @@ #![feature(try_blocks)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))] #![feature(unsafe_cell_raw_get)] #![feature(unwind_attributes)] #![feature(vec_into_raw_parts)] diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index c5b871edbf2..4a3c3ba1635 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -54,7 +54,6 @@ pub use core::prelude::v1::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(hidden)] pub use core::prelude::v1::derive; @@ -67,7 +66,6 @@ pub use core::prelude::v1::derive; #[doc(hidden)] pub use core::prelude::v1::cfg_accessible; -#[cfg(not(bootstrap))] #[unstable( feature = "cfg_eval", issue = "82679", diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 86f59495504..38901a35296 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -741,12 +741,7 @@ impl<'a> Builder<'a> { .env("RUSTDOC_REAL", self.rustdoc(compiler)) .env("RUSTC_BOOTSTRAP", "1"); - // cfg(bootstrap), can be removed on the next beta bump - if compiler.stage == 0 { - cmd.arg("-Winvalid_codeblock_attributes"); - } else { - cmd.arg("-Wrustdoc::invalid_codeblock_attributes"); - } + cmd.arg("-Wrustdoc::invalid_codeblock_attributes"); if self.config.deny_warnings { cmd.arg("-Dwarnings"); @@ -1303,12 +1298,7 @@ impl<'a> Builder<'a> { // fixed via better support from Cargo. cargo.env("RUSTC_LINT_FLAGS", lint_flags.join(" ")); - // cfg(bootstrap), can be removed on the next beta bump - if compiler.stage == 0 { - rustdocflags.arg("-Winvalid_codeblock_attributes"); - } else { - rustdocflags.arg("-Wrustdoc::invalid_codeblock_attributes"); - } + rustdocflags.arg("-Wrustdoc::invalid_codeblock_attributes"); } if mode == Mode::Rustc { diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index f6875e0036f..c677d04917e 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -14,8 +14,6 @@ //! A few exceptions are allowed as there's known bugs in rustdoc, but this //! should catch the majority of "broken link" cases. -#![cfg_attr(bootstrap, feature(str_split_once))] - use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::env; diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 11d36751f67..cbcc01dc39a 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -3,8 +3,6 @@ //! This library contains the tidy lints and exposes it //! to be used by tools. -#![cfg_attr(bootstrap, feature(str_split_once))] - use std::fs::File; use std::io::Read; use walkdir::{DirEntry, WalkDir}; -- cgit 1.4.1-3-g733a5