Add documentation to more `From::from` implementations.
For users looking at documentation through IDE popups, this gives them relevant information rather than the generic trait documentation wording “Performs the conversion”. For users reading the documentation for a specific type for any reason, this informs them when the conversion may allocate or copy significant memory versus when it is always a move or cheap copy.
Notes on specific cases:
* The new documentation for `From<T> for T` explains that it is not a conversion at all.
* Also documented `impl<T, U> Into<U> for T where U: From<T>`, the other central blanket implementation of conversion.
* The new documentation for construction of maps and sets from arrays of keys mentions the handling of duplicates. Future work could be to do this for *all* code paths that convert an iterable to a map or set.
* I did not add documentation to conversions of a specific error type to a more general error type.
* I did not add documentation to unstable code.
This change was prepared by searching for the text "From<... for" and so may have missed some cases that for whatever reason did not match. I also looked for `Into` impls but did not find any worth documenting by the above criteria.
use super::search::SearchResult::*;
mod entry;
+
+#[stable(feature = "rust1", since = "1.0.0")]
pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry};
+
use Entry::*;
/// Minimum number of elements in a node that is not a root.
// An empty map is represented either by the absence of a root node or by a
// root node that is an empty leaf.
-/// A map based on a [B-Tree].
+/// An ordered map based on a [B-Tree].
///
/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
/// behavior.
///
+/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::values`], or
+/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
+/// amortized constant time per item returned.
+///
/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
/// [`Cell`]: core::cell::Cell
/// [`RefCell`]: core::cell::RefCell
/// ```
/// use std::collections::BTreeMap;
///
- /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"]
- /// .iter()
- /// .map(|&s| (s, 0))
- /// .collect();
+ /// let mut map: BTreeMap<&str, i32> =
+ /// [("Alice", 0), ("Bob", 0), ("Carol", 0), ("Cheryl", 0)].into();
/// for (_, balance) in map.range_mut("B".."Cheryl") {
/// *balance += 100;
/// }
/// let mut count: BTreeMap<&str, usize> = BTreeMap::new();
///
/// // count the number of occurrences of letters in the vec
- /// for x in vec!["a", "b", "a", "c", "a", "b"] {
+ /// for x in ["a", "b", "a", "c", "a", "b"] {
/// *count.entry(x).or_insert(0) += 1;
/// }
///
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let evens: BTreeMap<_, _> = map.drain_filter(|k, _v| k % 2 == 0).collect();
/// let odds = map;
- /// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
- /// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
+ /// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]);
+ /// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);
/// ```
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
pub(crate) fn bulk_build_from_sorted_iter<I>(iter: I) -> Self
where
K: Ord,
- I: Iterator<Item = (K, V)>,
+ I: IntoIterator<Item = (K, V)>,
{
let mut root = Root::new();
let mut length = 0;
- root.bulk_push(DedupSortedIter::new(iter), &mut length);
+ root.bulk_push(DedupSortedIter::new(iter.into_iter()), &mut length);
BTreeMap { root: Some(root), length }
}
}
// use stable sort to preserve the insertion order.
inputs.sort_by(|a, b| a.0.cmp(&b.0));
- BTreeMap::bulk_build_from_sorted_iter(inputs.into_iter())
+ BTreeMap::bulk_build_from_sorted_iter(inputs)
}
}
#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<K: Ord, V, const N: usize> From<[(K, V); N]> for BTreeMap<K, V> {
+ /// Converts a `[(K, V); N]` into a `BTreeMap<(K, V)>`.
+ ///
/// ```
/// use std::collections::BTreeMap;
///
// use stable sort to preserve the insertion order.
arr.sort_by(|a, b| a.0.cmp(&b.0));
- BTreeMap::bulk_build_from_sorted_iter(core::array::IntoIter::new(arr))
+ BTreeMap::bulk_build_from_sorted_iter(arr)
}
}
/// ```
/// use std::collections::BTreeMap;
///
- /// let mut map = BTreeMap::new();
- /// map.insert("a", 1);
- /// map.insert("b", 2);
- /// map.insert("c", 3);
+ /// let mut map = BTreeMap::from([
+ /// ("a", 1),
+ /// ("b", 2),
+ /// ("c", 3),
+ /// ]);
///
/// // add 10 to the value if the key isn't "a"
/// for (key, value) in map.iter_mut() {
// FIXME(conventions): implement bounded iterators
-/// A set based on a B-Tree.
+/// An ordered set based on a B-Tree.
///
/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance
/// benefits and drawbacks.
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
/// behavior.
///
+/// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case
+/// logarithmic and amortized constant time per item returned.
+///
/// [`Ord`]: core::cmp::Ord
/// [`Cell`]: core::cell::Cell
/// [`RefCell`]: core::cell::RefCell
self_iter: Iter<'a, T>,
other_set: &'a BTreeSet<T>,
},
- Iterate(Iter<'a, T>), // simply produce all values in `self`
+ Iterate(Iter<'a, T>), // simply produce all elements in `self`
}
#[stable(feature = "collection_debug", since = "1.17.0")]
small_iter: Iter<'a, T>,
large_set: &'a BTreeSet<T>,
},
- Answer(Option<&'a T>), // return a specific value or emptiness
+ Answer(Option<&'a T>), // return a specific element or emptiness
}
#[stable(feature = "collection_debug", since = "1.17.0")]
Range { iter: self.map.range(range) }
}
- /// Visits the values representing the difference,
- /// i.e., the values that are in `self` but not in `other`,
+ /// Visits the elements representing the difference,
+ /// i.e., the elements that are in `self` but not in `other`,
/// in ascending order.
///
/// # Examples
}
}
- /// Visits the values representing the symmetric difference,
- /// i.e., the values that are in `self` or in `other` but not in both,
+ /// Visits the elements representing the symmetric difference,
+ /// i.e., the elements that are in `self` or in `other` but not in both,
/// in ascending order.
///
/// # Examples
SymmetricDifference(MergeIterInner::new(self.iter(), other.iter()))
}
- /// Visits the values representing the intersection,
- /// i.e., the values that are both in `self` and `other`,
+ /// Visits the elements representing the intersection,
+ /// i.e., the elements that are both in `self` and `other`,
/// in ascending order.
///
/// # Examples
}
}
- /// Visits the values representing the union,
- /// i.e., all the values in `self` or `other`, without duplicates,
+ /// Visits the elements representing the union,
+ /// i.e., all the elements in `self` or `other`, without duplicates,
/// in ascending order.
///
/// # Examples
Union(MergeIterInner::new(self.iter(), other.iter()))
}
- /// Clears the set, removing all values.
+ /// Clears the set, removing all elements.
///
/// # Examples
///
self.map.clear()
}
- /// Returns `true` if the set contains a value.
+ /// Returns `true` if the set contains an element equal to the value.
///
- /// The value may be any borrowed form of the set's value type,
+ /// The value may be any borrowed form of the set's element type,
/// but the ordering on the borrowed form *must* match the
- /// ordering on the value type.
+ /// ordering on the element type.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
- /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let set = BTreeSet::from([1, 2, 3]);
/// assert_eq!(set.contains(&1), true);
/// assert_eq!(set.contains(&4), false);
/// ```
self.map.contains_key(value)
}
- /// Returns a reference to the value in the set, if any, that is equal to the given value.
+ /// Returns a reference to the element in the set, if any, that is equal to
+ /// the value.
///
- /// The value may be any borrowed form of the set's value type,
+ /// The value may be any borrowed form of the set's element type,
/// but the ordering on the borrowed form *must* match the
- /// ordering on the value type.
+ /// ordering on the element type.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
- /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let set = BTreeSet::from([1, 2, 3]);
/// assert_eq!(set.get(&2), Some(&2));
/// assert_eq!(set.get(&4), None);
/// ```
/// ```
/// use std::collections::BTreeSet;
///
- /// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let a = BTreeSet::from([1, 2, 3]);
/// let mut b = BTreeSet::new();
///
/// assert_eq!(a.is_disjoint(&b), true);
}
/// Returns `true` if the set is a subset of another,
- /// i.e., `other` contains at least all the values in `self`.
+ /// i.e., `other` contains at least all the elements in `self`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
- /// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let sup = BTreeSet::from([1, 2, 3]);
/// let mut set = BTreeSet::new();
///
/// assert_eq!(set.is_subset(&sup), true);
}
/// Returns `true` if the set is a superset of another,
- /// i.e., `self` contains at least all the values in `other`.
+ /// i.e., `self` contains at least all the elements in `other`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
- /// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect();
+ /// let sub = BTreeSet::from([1, 2]);
/// let mut set = BTreeSet::new();
///
/// assert_eq!(set.is_superset(&sub), false);
other.is_subset(self)
}
- /// Returns a reference to the first value in the set, if any.
- /// This value is always the minimum of all values in the set.
+ /// Returns a reference to the first element in the set, if any.
+ /// This element is always the minimum of all elements in the set.
///
/// # Examples
///
self.map.first_key_value().map(|(k, _)| k)
}
- /// Returns a reference to the last value in the set, if any.
- /// This value is always the maximum of all values in the set.
+ /// Returns a reference to the last element in the set, if any.
+ /// This element is always the maximum of all elements in the set.
///
/// # Examples
///
self.map.last_key_value().map(|(k, _)| k)
}
- /// Removes the first value from the set and returns it, if any.
- /// The first value is always the minimum value in the set.
+ /// Removes the first element from the set and returns it, if any.
+ /// The first element is always the minimum element in the set.
///
/// # Examples
///
self.map.pop_first().map(|kv| kv.0)
}
- /// Removes the last value from the set and returns it, if any.
- /// The last value is always the maximum value in the set.
+ /// Removes the last element from the set and returns it, if any.
+ /// The last element is always the maximum element in the set.
///
/// # Examples
///
/// Adds a value to the set.
///
- /// If the set did not have this value present, `true` is returned.
+ /// If the set did not have an equal element present, `true` is returned.
///
- /// If the set did have this value present, `false` is returned, and the
- /// entry is not updated. See the [module-level documentation] for more.
+ /// If the set did have an equal element present, `false` is returned, and
+ /// the entry is not updated. See the [module-level documentation] for more.
///
/// [module-level documentation]: index.html#insert-and-complex-keys
///
self.map.insert(value, ()).is_none()
}
- /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
- /// one. Returns the replaced value.
+ /// Adds a value to the set, replacing the existing element, if any, that is
+ /// equal to the value. Returns the replaced element.
///
/// # Examples
///
Recover::replace(&mut self.map, value)
}
- /// Removes a value from the set. Returns whether the value was
- /// present in the set.
+ /// If the set contains an element equal to the value, removes it from the
+ /// set and drops it. Returns whether such an element was present.
///
- /// The value may be any borrowed form of the set's value type,
+ /// The value may be any borrowed form of the set's element type,
/// but the ordering on the borrowed form *must* match the
- /// ordering on the value type.
+ /// ordering on the element type.
///
/// # Examples
///
self.map.remove(value).is_some()
}
- /// Removes and returns the value in the set, if any, that is equal to the given one.
+ /// Removes and returns the element in the set, if any, that is equal to
+ /// the value.
///
- /// The value may be any borrowed form of the set's value type,
+ /// The value may be any borrowed form of the set's element type,
/// but the ordering on the borrowed form *must* match the
- /// ordering on the value type.
+ /// ordering on the element type.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
- /// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let mut set = BTreeSet::from([1, 2, 3]);
/// assert_eq!(set.take(&2), Some(2));
/// assert_eq!(set.take(&2), None);
/// ```
/// ```
/// use std::collections::BTreeSet;
///
- /// let xs = [1, 2, 3, 4, 5, 6];
- /// let mut set: BTreeSet<i32> = xs.iter().cloned().collect();
+ /// let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
/// // Keep only the even numbers.
/// set.retain(|&k| k % 2 == 0);
/// assert!(set.iter().eq([2, 4, 6].iter()));
self.map.append(&mut other.map);
}
- /// Splits the collection into two at the given value. Returns everything after the given value,
- /// including the value.
+ /// Splits the collection into two at the value. Returns a new collection
+ /// with all elements greater than or equal to the value.
///
/// # Examples
///
BTreeSet { map: self.map.split_off(value) }
}
- /// Creates an iterator that visits all values in ascending order and uses a closure
- /// to determine if a value should be removed.
+ /// Creates an iterator that visits all elements in ascending order and
+ /// uses a closure to determine if an element should be removed.
///
- /// If the closure returns `true`, the value is removed from the set and yielded. If
- /// the closure returns `false`, or panics, the value remains in the set and will
- /// not be yielded.
+ /// If the closure returns `true`, the element is removed from the set and
+ /// yielded. If the closure returns `false`, or panics, the element remains
+ /// in the set and will not be yielded.
///
- /// If the iterator is only partially consumed or not consumed at all, each of the
- /// remaining values is still subjected to the closure and removed and dropped if it
- /// returns `true`.
+ /// If the iterator is only partially consumed or not consumed at all, each
+ /// of the remaining elements is still subjected to the closure and removed
+ /// and dropped if it returns `true`.
///
- /// It is unspecified how many more values will be subjected to the closure if a
- /// panic occurs in the closure, or if a panic occurs while dropping a value, or if
- /// the `DrainFilter` itself is leaked.
+ /// It is unspecified how many more elements will be subjected to the
+ /// closure if a panic occurs in the closure, or if a panic occurs while
+ /// dropping an element, or if the `DrainFilter` itself is leaked.
///
/// # Examples
///
DrainFilter { pred, inner: self.map.drain_filter_inner() }
}
- /// Gets an iterator that visits the values in the `BTreeSet` in ascending order.
+ /// Gets an iterator that visits the elements in the `BTreeSet` in ascending
+ /// order.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
- /// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
+ /// let set = BTreeSet::from([1, 2, 3]);
/// let mut set_iter = set.iter();
/// assert_eq!(set_iter.next(), Some(&1));
/// assert_eq!(set_iter.next(), Some(&2));
/// ```
/// use std::collections::BTreeSet;
///
- /// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
+ /// let set = BTreeSet::from([3, 1, 2]);
/// let mut set_iter = set.iter();
/// assert_eq!(set_iter.next(), Some(&1));
/// assert_eq!(set_iter.next(), Some(&2));
#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<T: Ord, const N: usize> From<[T; N]> for BTreeSet<T> {
+ /// Converts a `[T; N]` into a `BTreeSet<T>`.
+ ///
/// ```
/// use std::collections::BTreeSet;
///
// use stable sort to preserve the insertion order.
arr.sort();
- let iter = core::array::IntoIter::new(arr).map(|k| (k, ()));
+ let iter = IntoIterator::into_iter(arr).map(|k| (k, ()));
let map = BTreeMap::bulk_build_from_sorted_iter(iter);
BTreeSet { map }
}
/// ```
/// use std::collections::BTreeSet;
///
- /// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
+ /// let set = BTreeSet::from([1, 2, 3, 4]);
///
/// let v: Vec<_> = set.into_iter().collect();
/// assert_eq!(v, [1, 2, 3, 4]);
/// ```
/// use std::collections::BTreeSet;
///
- /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
- /// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect();
+ /// let a = BTreeSet::from([1, 2, 3]);
+ /// let b = BTreeSet::from([3, 4, 5]);
///
/// let result = &a - &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
/// ```
/// use std::collections::BTreeSet;
///
- /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
- /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect();
+ /// let a = BTreeSet::from([1, 2, 3]);
+ /// let b = BTreeSet::from([2, 3, 4]);
///
/// let result = &a ^ &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
/// ```
/// use std::collections::BTreeSet;
///
- /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
- /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect();
+ /// let a = BTreeSet::from([1, 2, 3]);
+ /// let b = BTreeSet::from([2, 3, 4]);
///
/// let result = &a & &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
/// ```
/// use std::collections::BTreeSet;
///
- /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
- /// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect();
+ /// let a = BTreeSet::from([1, 2, 3]);
+ /// let b = BTreeSet::from([3, 4, 5]);
///
/// let result = &a | &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
/// let list: LinkedList<u32> = LinkedList::new();
/// ```
#[inline]
- #[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_linked_list_new", since = "1.39.0")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
pub const fn new() -> Self {
#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<T, const N: usize> From<[T; N]> for LinkedList<T> {
+ /// Converts a `[T; N]` into a `LinkedList<T>`.
+ ///
/// ```
/// use std::collections::LinkedList;
///
/// assert_eq!(list1, list2);
/// ```
fn from(arr: [T; N]) -> Self {
- core::array::IntoIter::new(arr).collect()
+ Self::from_iter(arr)
}
}
-//! A double-ended queue implemented with a growable ring buffer.
+//! A double-ended queue (deque) implemented with a growable ring buffer.
//!
//! This queue has *O*(1) amortized inserts and removals from both ends of the
//! container. It also has *O*(1) indexing like a vector. The contained elements
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for VecDeque<T> {
- /// Creates an empty `VecDeque<T>`.
+ /// Creates an empty deque.
#[inline]
fn default() -> VecDeque<T> {
VecDeque::new()
}
impl<T> VecDeque<T> {
- /// Creates an empty `VecDeque`.
+ /// Creates an empty deque.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let vector: VecDeque<u32> = VecDeque::new();
+ /// let deque: VecDeque<u32> = VecDeque::new();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
VecDeque::new_in(Global)
}
- /// Creates an empty `VecDeque` with space for at least `capacity` elements.
+ /// Creates an empty deque with space for at least `capacity` elements.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let vector: VecDeque<u32> = VecDeque::with_capacity(10);
+ /// let deque: VecDeque<u32> = VecDeque::with_capacity(10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
}
impl<T, A: Allocator> VecDeque<T, A> {
- /// Creates an empty `VecDeque`.
+ /// Creates an empty deque.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let vector: VecDeque<u32> = VecDeque::new();
+ /// let deque: VecDeque<u32> = VecDeque::new();
/// ```
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
VecDeque::with_capacity_in(INITIAL_CAPACITY, alloc)
}
- /// Creates an empty `VecDeque` with space for at least `capacity` elements.
+ /// Creates an empty deque with space for at least `capacity` elements.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let vector: VecDeque<u32> = VecDeque::with_capacity(10);
+ /// let deque: VecDeque<u32> = VecDeque::with_capacity(10);
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque<T, A> {
unsafe { ptr::swap(self.ptr().add(ri), self.ptr().add(rj)) }
}
- /// Returns the number of elements the `VecDeque` can hold without
+ /// Returns the number of elements the deque can hold without
/// reallocating.
///
/// # Examples
}
/// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
- /// given `VecDeque`. Does nothing if the capacity is already sufficient.
+ /// given deque. Does nothing if the capacity is already sufficient.
///
/// Note that the allocator may give the collection more space than it requests. Therefore
/// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future
/// ```
/// use std::collections::VecDeque;
///
- /// let mut buf: VecDeque<i32> = vec![1].into_iter().collect();
+ /// let mut buf: VecDeque<i32> = [1].into();
/// buf.reserve_exact(10);
/// assert!(buf.capacity() >= 11);
/// ```
}
/// Reserves capacity for at least `additional` more elements to be inserted in the given
- /// `VecDeque`. The collection may reserve more space to avoid frequent reallocations.
+ /// deque. The collection may reserve more space to avoid frequent reallocations.
///
/// # Panics
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut buf: VecDeque<i32> = vec![1].into_iter().collect();
+ /// let mut buf: VecDeque<i32> = [1].into();
/// buf.reserve(10);
/// assert!(buf.capacity() >= 11);
/// ```
}
/// Tries to reserve the minimum capacity for exactly `additional` more elements to
- /// be inserted in the given `VecDeque<T>`. After calling `try_reserve_exact`,
+ /// be inserted in the given deque. After calling `try_reserve_exact`,
/// capacity will be greater than or equal to `self.len() + additional`.
/// Does nothing if the capacity is already sufficient.
///
/// Note that the allocator may give the collection more space than it
/// requests. Therefore, capacity can not be relied upon to be precisely
- /// minimal. Prefer [`reserve`] if future insertions are expected.
+ /// minimal. Prefer [`try_reserve`] if future insertions are expected.
///
- /// [`reserve`]: VecDeque::reserve
+ /// [`try_reserve`]: VecDeque::try_reserve
///
/// # Errors
///
}
/// Tries to reserve capacity for at least `additional` more elements to be inserted
- /// in the given `VecDeque<T>`. The collection may reserve more space to avoid
+ /// in the given deque. The collection may reserve more space to avoid
/// frequent reallocations. After calling `try_reserve`, capacity will be
/// greater than or equal to `self.len() + additional`. Does nothing if
/// capacity is already sufficient.
Ok(())
}
- /// Shrinks the capacity of the `VecDeque` as much as possible.
+ /// Shrinks the capacity of the deque as much as possible.
///
/// It will drop down as close as possible to the length but the allocator may still inform the
- /// `VecDeque` that there is space for a few more elements.
+ /// deque that there is space for a few more elements.
///
/// # Examples
///
self.shrink_to(0);
}
- /// Shrinks the capacity of the `VecDeque` with a lower bound.
+ /// Shrinks the capacity of the deque with a lower bound.
///
/// The capacity will remain at least as large as both the length
/// and the supplied value.
}
}
- /// Shortens the `VecDeque`, keeping the first `len` elements and dropping
+ /// Shortens the deque, keeping the first `len` elements and dropping
/// the rest.
///
- /// If `len` is greater than the `VecDeque`'s current length, this has no
+ /// If `len` is greater than the deque's current length, this has no
/// effect.
///
/// # Examples
#[stable(feature = "rust1", since = "1.0.0")]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
// SAFETY: The internal `IterMut` safety invariant is established because the
- // `ring` we create is a dereferencable slice for lifetime '_.
+ // `ring` we create is a dereferenceable slice for lifetime '_.
let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap());
unsafe { IterMut::new(ring, self.tail, self.head, PhantomData) }
}
/// Returns a pair of slices which contain, in order, the contents of the
- /// `VecDeque`.
+ /// deque.
///
/// If [`make_contiguous`] was previously called, all elements of the
- /// `VecDeque` will be in the first slice and the second slice will be empty.
+ /// deque will be in the first slice and the second slice will be empty.
///
/// [`make_contiguous`]: VecDeque::make_contiguous
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut vector = VecDeque::new();
+ /// let mut deque = VecDeque::new();
///
- /// vector.push_back(0);
- /// vector.push_back(1);
- /// vector.push_back(2);
+ /// deque.push_back(0);
+ /// deque.push_back(1);
+ /// deque.push_back(2);
///
- /// assert_eq!(vector.as_slices(), (&[0, 1, 2][..], &[][..]));
+ /// assert_eq!(deque.as_slices(), (&[0, 1, 2][..], &[][..]));
///
- /// vector.push_front(10);
- /// vector.push_front(9);
+ /// deque.push_front(10);
+ /// deque.push_front(9);
///
- /// assert_eq!(vector.as_slices(), (&[9, 10][..], &[0, 1, 2][..]));
+ /// assert_eq!(deque.as_slices(), (&[9, 10][..], &[0, 1, 2][..]));
/// ```
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
}
/// Returns a pair of slices which contain, in order, the contents of the
- /// `VecDeque`.
+ /// deque.
///
/// If [`make_contiguous`] was previously called, all elements of the
- /// `VecDeque` will be in the first slice and the second slice will be empty.
+ /// deque will be in the first slice and the second slice will be empty.
///
/// [`make_contiguous`]: VecDeque::make_contiguous
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut vector = VecDeque::new();
+ /// let mut deque = VecDeque::new();
///
- /// vector.push_back(0);
- /// vector.push_back(1);
+ /// deque.push_back(0);
+ /// deque.push_back(1);
///
- /// vector.push_front(10);
- /// vector.push_front(9);
+ /// deque.push_front(10);
+ /// deque.push_front(9);
///
- /// vector.as_mut_slices().0[0] = 42;
- /// vector.as_mut_slices().1[0] = 24;
- /// assert_eq!(vector.as_slices(), (&[42, 10][..], &[24, 1][..]));
+ /// deque.as_mut_slices().0[0] = 42;
+ /// deque.as_mut_slices().1[0] = 24;
+ /// assert_eq!(deque.as_slices(), (&[42, 10][..], &[24, 1][..]));
/// ```
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
}
}
- /// Returns the number of elements in the `VecDeque`.
+ /// Returns the number of elements in the deque.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut v = VecDeque::new();
- /// assert_eq!(v.len(), 0);
- /// v.push_back(1);
- /// assert_eq!(v.len(), 1);
+ /// let mut deque = VecDeque::new();
+ /// assert_eq!(deque.len(), 0);
+ /// deque.push_back(1);
+ /// assert_eq!(deque.len(), 1);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
count(self.tail, self.head, self.cap())
}
- /// Returns `true` if the `VecDeque` is empty.
+ /// Returns `true` if the deque is empty.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut v = VecDeque::new();
- /// assert!(v.is_empty());
- /// v.push_front(1);
- /// assert!(!v.is_empty());
+ /// let mut deque = VecDeque::new();
+ /// assert!(deque.is_empty());
+ /// deque.push_front(1);
+ /// assert!(!deque.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_empty(&self) -> bool {
(tail, head)
}
- /// Creates an iterator that covers the specified range in the `VecDeque`.
+ /// Creates an iterator that covers the specified range in the deque.
///
/// # Panics
///
/// Panics if the starting point is greater than the end point or if
- /// the end point is greater than the length of the vector.
+ /// the end point is greater than the length of the deque.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
- /// let range = v.range(2..).copied().collect::<VecDeque<_>>();
+ /// let deque: VecDeque<_> = [1, 2, 3].into();
+ /// let range = deque.range(2..).copied().collect::<VecDeque<_>>();
/// assert_eq!(range, [3]);
///
/// // A full range covers all contents
- /// let all = v.range(..);
+ /// let all = deque.range(..);
/// assert_eq!(all.len(), 3);
/// ```
#[inline]
}
}
- /// Creates an iterator that covers the specified mutable range in the `VecDeque`.
+ /// Creates an iterator that covers the specified mutable range in the deque.
///
/// # Panics
///
/// Panics if the starting point is greater than the end point or if
- /// the end point is greater than the length of the vector.
+ /// the end point is greater than the length of the deque.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
- /// for v in v.range_mut(2..) {
+ /// let mut deque: VecDeque<_> = [1, 2, 3].into();
+ /// for v in deque.range_mut(2..) {
/// *v *= 2;
/// }
- /// assert_eq!(v, vec![1, 2, 6]);
+ /// assert_eq!(deque, [1, 2, 6]);
///
/// // A full range covers all contents
- /// for v in v.range_mut(..) {
+ /// for v in deque.range_mut(..) {
/// *v *= 2;
/// }
- /// assert_eq!(v, vec![2, 4, 12]);
+ /// assert_eq!(deque, [2, 4, 12]);
/// ```
#[inline]
#[stable(feature = "deque_range", since = "1.51.0")]
let (tail, head) = self.range_tail_head(range);
// SAFETY: The internal `IterMut` safety invariant is established because the
- // `ring` we create is a dereferencable slice for lifetime '_.
+ // `ring` we create is a dereferenceable slice for lifetime '_.
let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap());
unsafe { IterMut::new(ring, tail, head, PhantomData) }
}
/// Creates a draining iterator that removes the specified range in the
- /// `VecDeque` and yields the removed items.
+ /// deque and yields the removed items.
///
/// Note 1: The element range is removed even if the iterator is not
/// consumed until the end.
/// # Panics
///
/// Panics if the starting point is greater than the end point or if
- /// the end point is greater than the length of the vector.
+ /// the end point is greater than the length of the deque.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
- /// let drained = v.drain(2..).collect::<VecDeque<_>>();
+ /// let mut deque: VecDeque<_> = [1, 2, 3].into();
+ /// let drained = deque.drain(2..).collect::<VecDeque<_>>();
/// assert_eq!(drained, [3]);
- /// assert_eq!(v, [1, 2]);
+ /// assert_eq!(deque, [1, 2]);
///
/// // A full range clears all contents
- /// v.drain(..);
- /// assert!(v.is_empty());
+ /// deque.drain(..);
+ /// assert!(deque.is_empty());
/// ```
#[inline]
#[stable(feature = "drain", since = "1.6.0")]
unsafe { Drain::new(drain_head, head, iter, deque) }
}
- /// Clears the `VecDeque`, removing all values.
+ /// Clears the deque, removing all values.
///
/// # Examples
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut v = VecDeque::new();
- /// v.push_back(1);
- /// v.clear();
- /// assert!(v.is_empty());
+ /// let mut deque = VecDeque::new();
+ /// deque.push_back(1);
+ /// deque.clear();
+ /// assert!(deque.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
self.truncate(0);
}
- /// Returns `true` if the `VecDeque` contains an element equal to the
+ /// Returns `true` if the deque contains an element equal to the
/// given value.
///
/// # Examples
/// ```
/// use std::collections::VecDeque;
///
- /// let mut vector: VecDeque<u32> = VecDeque::new();
+ /// let mut deque: VecDeque<u32> = VecDeque::new();
///
- /// vector.push_back(0);
- /// vector.push_back(1);
+ /// deque.push_back(0);
+ /// deque.push_back(1);
///
- /// assert_eq!(vector.contains(&1), true);
- /// assert_eq!(vector.contains(&10), false);
+ /// assert_eq!(deque.contains(&1), true);
+ /// assert_eq!(deque.contains(&10), false);
/// ```
#[stable(feature = "vec_deque_contains", since = "1.12.0")]
pub fn contains(&self, x: &T) -> bool
a.contains(x) || b.contains(x)
}
- /// Provides a reference to the front element, or `None` if the `VecDeque` is
+ /// Provides a reference to the front element, or `None` if the deque is
/// empty.
///
/// # Examples
}
/// Provides a mutable reference to the front element, or `None` if the
- /// `VecDeque` is empty.
+ /// deque is empty.
///
/// # Examples
///
self.get_mut(0)
}
- /// Provides a reference to the back element, or `None` if the `VecDeque` is
+ /// Provides a reference to the back element, or `None` if the deque is
/// empty.
///
/// # Examples
}
/// Provides a mutable reference to the back element, or `None` if the
- /// `VecDeque` is empty.
+ /// deque is empty.
///
/// # Examples
///
self.get_mut(self.len().wrapping_sub(1))
}
- /// Removes the first element and returns it, or `None` if the `VecDeque` is
+ /// Removes the first element and returns it, or `None` if the deque is
/// empty.
///
/// # Examples
}
}
- /// Removes the last element from the `VecDeque` and returns it, or `None` if
+ /// Removes the last element from the deque and returns it, or `None` if
/// it is empty.
///
/// # Examples
}
}
- /// Prepends an element to the `VecDeque`.
+ /// Prepends an element to the deque.
///
/// # Examples
///
}
}
- /// Appends an element to the back of the `VecDeque`.
+ /// Appends an element to the back of the deque.
///
/// # Examples
///
self.tail <= self.head
}
- /// Removes an element from anywhere in the `VecDeque` and returns it,
+ /// Removes an element from anywhere in the deque and returns it,
/// replacing it with the first element.
///
/// This does not preserve ordering, but is *O*(1).
self.pop_front()
}
- /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the
- /// last element.
+ /// Removes an element from anywhere in the deque and returns it,
+ /// replacing it with the last element.
///
/// This does not preserve ordering, but is *O*(1).
///
self.pop_back()
}
- /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices
- /// greater than or equal to `index` towards the back.
+ /// Inserts an element at `index` within the deque, shifting all elements
+ /// with indices greater than or equal to `index` towards the back.
///
/// Element at index 0 is the front of the queue.
///
/// # Panics
///
- /// Panics if `index` is greater than `VecDeque`'s length
+ /// Panics if `index` is greater than deque's length
///
/// # Examples
///
}
}
- /// Removes and returns the element at `index` from the `VecDeque`.
+ /// Removes and returns the element at `index` from the deque.
/// Whichever end is closer to the removal point will be moved to make
/// room, and all the affected elements will be moved to new positions.
/// Returns `None` if `index` is out of bounds.
elem
}
- /// Splits the `VecDeque` into two at the given index.
+ /// Splits the deque into two at the given index.
///
/// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`,
- /// and the returned `VecDeque` contains elements `[at, len)`.
+ /// and the returned deque contains elements `[at, len)`.
///
/// Note that the capacity of `self` does not change.
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
+ /// let mut buf: VecDeque<_> = [1, 2, 3].into();
/// let buf2 = buf.split_off(1);
/// assert_eq!(buf, [1]);
/// assert_eq!(buf2, [2, 3]);
/// ```
/// use std::collections::VecDeque;
///
- /// let mut buf: VecDeque<_> = vec![1, 2].into_iter().collect();
- /// let mut buf2: VecDeque<_> = vec![3, 4].into_iter().collect();
+ /// let mut buf: VecDeque<_> = [1, 2].into();
+ /// let mut buf2: VecDeque<_> = [3, 4].into();
/// buf.append(&mut buf2);
/// assert_eq!(buf, [1, 2, 3, 4]);
/// assert_eq!(buf2, []);
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
+ {
+ self.retain_mut(|elem| f(elem));
+ }
+
+ /// Retains only the elements specified by the predicate.
+ ///
+ /// In other words, remove all elements `e` such that `f(&e)` returns false.
+ /// This method operates in place, visiting each element exactly once in the
+ /// original order, and preserves the order of the retained elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(vec_retain_mut)]
+ ///
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.extend(1..5);
+ /// buf.retain_mut(|x| if *x % 2 == 0 {
+ /// *x += 1;
+ /// true
+ /// } else {
+ /// false
+ /// });
+ /// assert_eq!(buf, [3, 5]);
+ /// ```
+ #[unstable(feature = "vec_retain_mut", issue = "90829")]
+ pub fn retain_mut<F>(&mut self, mut f: F)
+ where
+ F: FnMut(&mut T) -> bool,
{
let len = self.len();
let mut idx = 0;
// Stage 1: All values are retained.
while cur < len {
- if !f(&self[cur]) {
+ if !f(&mut self[cur]) {
cur += 1;
break;
}
}
// Stage 2: Swap retained value into current idx.
while cur < len {
- if !f(&self[cur]) {
+ if !f(&mut self[cur]) {
cur += 1;
continue;
}
cur += 1;
idx += 1;
}
- // Stage 3: Trancate all values after idx.
+ // Stage 3: Truncate all values after idx.
if cur != idx {
self.truncate(idx);
}
debug_assert!(!self.is_full());
}
- /// Modifies the `VecDeque` in-place so that `len()` is equal to `new_len`,
+ /// Modifies the deque in-place so that `len()` is equal to `new_len`,
/// either by removing excess elements from the back or by appending
/// elements generated by calling `generator` to the back.
///
///
/// Once the internal storage is contiguous, the [`as_slices`] and
/// [`as_mut_slices`] methods will return the entire contents of the
- /// `VecDeque` in a single slice.
+ /// deque in a single slice.
///
/// [`as_slices`]: VecDeque::as_slices
/// [`as_mut_slices`]: VecDeque::as_mut_slices
}
}
- /// Binary searches this sorted `VecDeque` for a given element.
+ /// Binary searches the sorted deque for a given element.
///
/// If the value is found then [`Result::Ok`] is returned, containing the
/// index of the matching element. If there are multiple matches, then any
/// ```
/// use std::collections::VecDeque;
///
- /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
+ /// let deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
///
/// assert_eq!(deque.binary_search(&13), Ok(9));
/// assert_eq!(deque.binary_search(&4), Err(7));
/// assert!(matches!(r, Ok(1..=4)));
/// ```
///
- /// If you want to insert an item to a sorted `VecDeque`, while maintaining
+ /// If you want to insert an item to a sorted deque, while maintaining
/// sort order:
///
/// ```
/// use std::collections::VecDeque;
///
- /// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
+ /// let mut deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
/// let num = 42;
/// let idx = deque.binary_search(&num).unwrap_or_else(|x| x);
/// deque.insert(idx, num);
self.binary_search_by(|e| e.cmp(x))
}
- /// Binary searches this sorted `VecDeque` with a comparator function.
+ /// Binary searches the sorted deque with a comparator function.
///
/// The comparator function should implement an order consistent
- /// with the sort order of the underlying `VecDeque`, returning an
- /// order code that indicates whether its argument is `Less`,
- /// `Equal` or `Greater` than the desired target.
+ /// with the sort order of the deque, returning an order code that
+ /// indicates whether its argument is `Less`, `Equal` or `Greater`
+ /// than the desired target.
///
/// If the value is found then [`Result::Ok`] is returned, containing the
/// index of the matching element. If there are multiple matches, then any
/// ```
/// use std::collections::VecDeque;
///
- /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
+ /// let deque: VecDeque<_> = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
///
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&13)), Ok(9));
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&4)), Err(7));
}
}
- /// Binary searches this sorted `VecDeque` with a key extraction function.
+ /// Binary searches the sorted deque with a key extraction function.
///
- /// Assumes that the `VecDeque` is sorted by the key, for instance with
+ /// Assumes that the deque is sorted by the key, for instance with
/// [`make_contiguous().sort_by_key()`] using the same key extraction function.
///
/// If the value is found then [`Result::Ok`] is returned, containing the
/// ```
/// use std::collections::VecDeque;
///
- /// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1),
+ /// let deque: VecDeque<_> = [(0, 0), (2, 1), (4, 1), (5, 1),
/// (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
/// (1, 21), (2, 34), (4, 55)].into();
///
/// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0
/// (all odd numbers are at the start, all even at the end).
///
- /// If this deque is not partitioned, the returned result is unspecified and meaningless,
+ /// If the deque is not partitioned, the returned result is unspecified and meaningless,
/// as this method performs a kind of binary search.
///
/// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`].
/// ```
/// use std::collections::VecDeque;
///
- /// let deque: VecDeque<_> = vec![1, 2, 3, 3, 5, 6, 7].into();
+ /// let deque: VecDeque<_> = [1, 2, 3, 3, 5, 6, 7].into();
/// let i = deque.partition_point(|&x| x < 5);
///
/// assert_eq!(i, 4);
}
impl<T: Clone, A: Allocator> VecDeque<T, A> {
- /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
+ /// Modifies the deque in-place so that `len()` is equal to new_len,
/// either by removing excess elements from the back or by appending clones of `value`
/// to the back.
///
type Item = T;
type IntoIter = IntoIter<T, A>;
- /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
+ /// Consumes the deque into a front-to-back iterator yielding elements by
/// value.
fn into_iter(self) -> IntoIter<T, A> {
IntoIter::new(self)
#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
+ /// Converts a `[T; N]` into a `VecDeque<T>`.
+ ///
/// ```
/// use std::collections::VecDeque;
///
#[cfg(not(no_global_oom_handling))]
mod spec_extend;
-/// A contiguous growable array type, written as `Vec<T>` and pronounced 'vector'.
+/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
///
/// # Examples
///
///
/// # Panics
///
- /// Panics if the new capacity overflows `usize`.
+ /// Panics if the new capacity exceeds `isize::MAX` bytes.
///
/// # Examples
///
///
/// Note that the allocator may give the collection more space than it
/// requests. Therefore, capacity can not be relied upon to be precisely
- /// minimal. Prefer [`reserve`] if future insertions are expected.
+ /// minimal. Prefer [`try_reserve`] if future insertions are expected.
///
- /// [`reserve`]: Vec::reserve
+ /// [`try_reserve`]: Vec::try_reserve
///
/// # Errors
///
///
/// Note: Because this shifts over the remaining elements, it has a
/// worst-case performance of *O*(*n*). If you don't need the order of elements
- /// to be preserved, use [`swap_remove`] instead.
+ /// to be preserved, use [`swap_remove`] instead. If you'd like to remove
+ /// elements from the beginning of the `Vec`, consider using
+ /// [`VecDeque::pop_front`] instead.
///
/// [`swap_remove`]: Vec::swap_remove
+ /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front
///
/// # Panics
///
let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len };
- // process_one return a bool indicates whether the processing element should be retained.
- #[inline(always)]
- fn process_one<F, T, A: Allocator, const DELETED: bool>(
+ fn process_loop<F, T, A: Allocator, const DELETED: bool>(
+ original_len: usize,
f: &mut F,
g: &mut BackshiftOnDrop<'_, T, A>,
- ) -> bool
- where
+ ) where
F: FnMut(&mut T) -> bool,
{
- // SAFETY: Unchecked element must be valid.
- let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) };
- if !f(cur) {
- // Advance early to avoid double drop if `drop_in_place` panicked.
- g.processed_len += 1;
- g.deleted_cnt += 1;
- // SAFETY: We never touch this element again after dropped.
- unsafe { ptr::drop_in_place(cur) };
- // We already advanced the counter.
- return false;
- }
- if DELETED {
- // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element.
- // We use copy for move, and never touch this element again.
- unsafe {
- let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt);
- ptr::copy_nonoverlapping(cur, hole_slot, 1);
+ while g.processed_len != original_len {
+ // SAFETY: Unchecked element must be valid.
+ let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) };
+ if !f(cur) {
+ // Advance early to avoid double drop if `drop_in_place` panicked.
+ g.processed_len += 1;
+ g.deleted_cnt += 1;
+ // SAFETY: We never touch this element again after dropped.
+ unsafe { ptr::drop_in_place(cur) };
+ // We already advanced the counter.
+ if DELETED {
+ continue;
+ } else {
+ break;
+ }
+ }
+ if DELETED {
+ // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element.
+ // We use copy for move, and never touch this element again.
+ unsafe {
+ let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt);
+ ptr::copy_nonoverlapping(cur, hole_slot, 1);
+ }
}
+ g.processed_len += 1;
}
- g.processed_len += 1;
- return true;
}
// Stage 1: Nothing was deleted.
- while g.processed_len != original_len {
- if !process_one::<F, T, A, false>(&mut f, &mut g) {
- break;
- }
- }
+ process_loop::<F, T, A, false>(original_len, &mut f, &mut g);
// Stage 2: Some elements were deleted.
- while g.processed_len != original_len {
- process_one::<F, T, A, true>(&mut f, &mut g);
- }
+ process_loop::<F, T, A, true>(original_len, &mut f, &mut g);
// All item are processed. This can be optimized to `set_len` by LLVM.
drop(g);
let ptr = self.vec.as_mut_ptr();
let len = self.vec.len();
- /* How many items were left when `same_bucket` paniced.
+ /* How many items were left when `same_bucket` panicked.
* Basically vec[read..].len() */
let items_left = len.wrapping_sub(self.read);
/// Removes the last element from a vector and returns it, or [`None`] if it
/// is empty.
///
+ /// If you'd like to pop the first element, consider using
+ /// [`VecDeque::pop_front`] instead.
+ ///
+ /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front
+ ///
/// # Examples
///
/// ```
/// # Examples
///
/// ```
- /// #![feature(vec_spare_capacity, maybe_uninit_extra)]
- ///
/// // Allocate vector big enough for 10 elements.
/// let mut v = Vec::with_capacity(10);
///
///
/// assert_eq!(&v, &[0, 1, 2]);
/// ```
- #[unstable(feature = "vec_spare_capacity", issue = "75017")]
+ #[stable(feature = "vec_spare_capacity", since = "1.60.0")]
#[inline]
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
// Note:
/// # Examples
///
/// ```
- /// #![feature(vec_split_at_spare, maybe_uninit_extra)]
+ /// #![feature(vec_split_at_spare)]
///
/// let mut v = vec![1, 1, 2];
///
unsafe fn split_at_spare_mut_with_len(
&mut self,
) -> (&mut [T], &mut [MaybeUninit<T>], &mut usize) {
- let Range { start: ptr, end: spare_ptr } = self.as_mut_ptr_range();
+ let ptr = self.as_mut_ptr();
+ // SAFETY:
+ // - `ptr` is guaranteed to be valid for `self.len` elements
+ // - but the allocation extends out to `self.buf.capacity()` elements, possibly
+ // uninitialized
+ let spare_ptr = unsafe { ptr.add(self.len) };
let spare_ptr = spare_ptr.cast::<MaybeUninit<T>>();
let spare_len = self.buf.capacity() - self.len;
// SAFETY:
- // - `ptr` is guaranteed to be valid for `len` elements
+ // - `ptr` is guaranteed to be valid for `self.len` elements
// - `spare_ptr` is pointing one element past the buffer, so it doesn't overlap with `initialized`
unsafe {
let initialized = slice::from_raw_parts_mut(ptr, self.len);
/// Clones and appends all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
- /// it to this `Vec`. The `other` vector is traversed in-order.
+ /// it to this `Vec`. The `other` slice is traversed in-order.
///
/// Note that this function is same as [`extend`] except that it is
/// specialized to work with slices instead. If and when Rust gets
}
}
-struct ExtendDefault;
-impl<T: Default> ExtendWith<T> for ExtendDefault {
- fn next(&mut self) -> T {
- Default::default()
- }
- fn last(self) -> T {
- Default::default()
- }
-}
-
struct ExtendFunc<F>(F);
impl<T, F: FnMut() -> T> ExtendWith<T> for ExtendFunc<F> {
fn next(&mut self) -> T {
/// # Examples
///
/// ```
- /// let mut v = vec![1, 2, 3];
- /// let new = [7, 8];
- /// let u: Vec<_> = v.splice(..2, new).collect();
- /// assert_eq!(v, &[7, 8, 3]);
- /// assert_eq!(u, &[1, 2]);
+ /// let mut v = vec![1, 2, 3, 4];
+ /// let new = [7, 8, 9];
+ /// let u: Vec<_> = v.splice(1..3, new).collect();
+ /// assert_eq!(v, &[1, 7, 8, 9, 4]);
+ /// assert_eq!(u, &[2, 3]);
/// ```
#[cfg(not(no_global_oom_handling))]
#[inline]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array", since = "1.44.0")]
impl<T, const N: usize> From<[T; N]> for Vec<T> {
- #[cfg(not(test))]
- fn from(s: [T; N]) -> Vec<T> {
- <[T]>::into_vec(box s)
- }
/// Allocate a `Vec<T>` and move `s`'s items into it.
///
/// # Examples
/// ```
/// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]);
/// ```
+ #[cfg(not(test))]
+ fn from(s: [T; N]) -> Vec<T> {
+ <[T]>::into_vec(box s)
+ }
+
#[cfg(test)]
fn from(s: [T; N]) -> Vec<T> {
crate::slice::into_vec(box s)
/// # Examples
///
/// ```
- /// use std::convert::TryInto;
/// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
/// assert_eq!(<Vec<i32>>::new().try_into(), Ok([]));
/// ```
///
/// If the length doesn't match, the input comes back in `Err`:
/// ```
- /// use std::convert::TryInto;
/// let r: Result<[i32; 4], _> = (0..10).collect::<Vec<_>>().try_into();
/// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
/// ```
/// If you're fine with just getting a prefix of the `Vec<T>`,
/// you can call [`.truncate(N)`](Vec::truncate) first.
/// ```
- /// use std::convert::TryInto;
/// let mut v = String::from("hello world").into_bytes();
/// v.sort();
/// v.truncate(2);
#[stable(feature = "cell_from", since = "1.12.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T> const From<T> for Cell<T> {
+ /// Creates a new `Cell<T>` containing the given value.
fn from(t: T) -> Cell<T> {
Cell::new(t)
}
Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b })
}
None => Err(BorrowError {
- // If a borrow occured, then we must already have an outstanding borrow,
+ // If a borrow occurred, then we must already have an outstanding borrow,
// so `borrowed_at` will be `Some`
#[cfg(feature = "debug_refcell")]
location: self.borrowed_at.get().unwrap(),
Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b })
}
None => Err(BorrowMutError {
- // If a borrow occured, then we must already have an outstanding borrow,
+ // If a borrow occurred, then we must already have an outstanding borrow,
// so `borrowed_at` will be `Some`
#[cfg(feature = "debug_refcell")]
location: self.borrowed_at.get().unwrap(),
Ok(unsafe { &*self.value.get() })
} else {
Err(BorrowError {
- // If a borrow occured, then we must already have an outstanding borrow,
+ // If a borrow occurred, then we must already have an outstanding borrow,
// so `borrowed_at` will be `Some`
#[cfg(feature = "debug_refcell")]
location: self.borrowed_at.get().unwrap(),
#[stable(feature = "cell_from", since = "1.12.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T> const From<T> for RefCell<T> {
+ /// Creates a new `RefCell<T>` containing the given value.
fn from(t: T) -> RefCell<T> {
RefCell::new(t)
}
///
/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(
- not(bootstrap),
- must_not_suspend = "holding a Ref across suspend \
- points can cause BorrowErrors"
-)]
+#[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"]
pub struct Ref<'b, T: ?Sized + 'b> {
value: &'b T,
borrow: BorrowRef<'b>,
///
/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(
- not(bootstrap),
- must_not_suspend = "holding a RefMut across suspend \
- points can cause BorrowErrors"
-)]
+#[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"]
pub struct RefMut<'b, T: ?Sized + 'b> {
value: &'b mut T,
borrow: BorrowRefMut<'b>,
/// ```
#[inline(always)]
#[stable(feature = "unsafe_cell_raw_get", since = "1.56.0")]
+ #[rustc_const_stable(feature = "unsafe_cell_raw_get", since = "1.56.0")]
pub const fn raw_get(this: *const Self) -> *mut T {
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
// #[repr(transparent)]. This exploits libstd's special status, there is
#[stable(feature = "cell_from", since = "1.12.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T> const From<T> for UnsafeCell<T> {
+ /// Creates a new `UnsafeCell<T>` containing the given value.
fn from(t: T) -> UnsafeCell<T> {
UnsafeCell::new(t)
}
/// ```rust
/// use std::convert::identity;
///
-/// let iter = vec![Some(1), None, Some(3)].into_iter();
+/// let iter = [Some(1), None, Some(3)].into_iter();
/// let filtered = iter.filter_map(identity).collect::<Vec<_>>();
/// assert_eq!(vec![1, 3], filtered);
/// ```
/// `TryFrom<T>` can be implemented as follows:
///
/// ```
-/// use std::convert::TryFrom;
-///
/// struct GreaterThanZero(i32);
///
/// impl TryFrom<i32> for GreaterThanZero {
/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
///
/// ```
-/// use std::convert::TryFrom;
-///
/// let big_number = 1_000_000_000_000i64;
/// // Silently truncates `big_number`, requires detecting
/// // and handling the truncation after the fact.
// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T: ?Sized, U: ?Sized> const AsRef<U> for &T
where
- T: AsRef<U>,
+ T: ~const AsRef<U>,
{
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T: ?Sized, U: ?Sized> const AsRef<U> for &mut T
where
- T: AsRef<U>,
+ T: ~const AsRef<U>,
{
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T: ?Sized, U: ?Sized> const AsMut<U> for &mut T
where
- T: AsMut<U>,
+ T: ~const AsMut<U>,
{
fn as_mut(&mut self) -> &mut U {
(*self).as_mut()
// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U> Into<U> for T
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T, U> const Into<U> for T
where
- U: From<T>,
+ U: ~const From<T>,
{
+ /// Calls `U::from(self)`.
+ ///
+ /// That is, this conversion is whatever the implementation of
+ /// <code>[From]<T> for U</code> chooses to do.
fn into(self) -> U {
U::from(self)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T> const From<T> for T {
+ /// Returns the argument unchanged.
fn from(t: T) -> T {
t
}
// TryFrom implies TryInto
#[stable(feature = "try_from", since = "1.34.0")]
-impl<T, U> TryInto<U> for T
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T, U> const TryInto<U> for T
where
- U: TryFrom<T>,
+ U: ~const TryFrom<T>,
{
type Error = U::Error;
// Infallible conversions are semantically equivalent to fallible conversions
// with an uninhabited error type.
#[stable(feature = "try_from", since = "1.34.0")]
-impl<T, U> TryFrom<U> for T
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<T, U> const TryFrom<U> for T
where
- U: Into<T>,
+ U: ~const Into<T>,
{
type Error = Infallible;
#[unstable(feature = "once_cell", issue = "74465")]
impl<T> const From<T> for OnceCell<T> {
+ /// Creates a new `OnceCell<T>` which already contains the given `value`.
fn from(value: T) -> Self {
OnceCell { inner: UnsafeCell::new(Some(value)) }
}
/// Returns `None` if the cell is empty.
#[unstable(feature = "once_cell", issue = "74465")]
pub fn get_mut(&mut self) -> Option<&mut T> {
- // SAFETY: Safe because we have unique access
- unsafe { &mut *self.inner.get() }.as_mut()
+ self.inner.get_mut().as_mut()
}
/// Sets the contents of the cell to `value`.
///
/// * The pointer must be properly aligned.
///
- /// * It must be "dereferencable" in the sense defined in [the module documentation].
+ /// * It must be "dereferenceable" in the sense defined in [the module documentation].
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit<T> {
+ #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ pub const unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit<T> {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &*self.cast().as_ptr() }
///
/// * The pointer must be properly aligned.
///
- /// * It must be "dereferencable" in the sense defined in [the module documentation].
+ /// * It must be "dereferenceable" in the sense defined in [the module documentation].
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit<T> {
+ #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ pub const unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit<T> {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &mut *self.cast().as_ptr() }
/// }
/// ```
#[stable(feature = "nonnull", since = "1.25.0")]
+ #[rustc_const_unstable(feature = "const_nonnull_new", issue = "93235")]
#[inline]
- pub fn new(ptr: *mut T) -> Option<Self> {
+ pub const fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
// SAFETY: The pointer is already checked and is not null
Some(unsafe { Self::new_unchecked(ptr) })
///
/// * The pointer must be properly aligned.
///
- /// * It must be "dereferencable" in the sense defined in [the module documentation].
+ /// * It must be "dereferenceable" in the sense defined in [the module documentation].
///
/// * The pointer must point to an initialized instance of `T`.
///
///
/// [the module documentation]: crate::ptr#safety
#[stable(feature = "nonnull", since = "1.25.0")]
+ #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[must_use]
#[inline]
- pub unsafe fn as_ref<'a>(&self) -> &'a T {
+ pub const unsafe fn as_ref<'a>(&self) -> &'a T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &*self.as_ptr() }
///
/// * The pointer must be properly aligned.
///
- /// * It must be "dereferencable" in the sense defined in [the module documentation].
+ /// * It must be "dereferenceable" in the sense defined in [the module documentation].
///
/// * The pointer must point to an initialized instance of `T`.
///
///
/// [the module documentation]: crate::ptr#safety
#[stable(feature = "nonnull", since = "1.25.0")]
+ #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[must_use]
#[inline]
- pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
+ pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a mutable reference.
unsafe { &mut *self.as_ptr() }
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit<T>] {
+ #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ pub const unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit<T>] {
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
}
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit<T>] {
+ #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ pub const unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit<T>] {
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
}
/// Returns a raw pointer to an element or subslice, without doing bounds
/// checking.
///
- /// Calling this method with an out-of-bounds index or when `self` is not dereferencable
+ /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable
/// is *[undefined behavior]* even if the resulting pointer is not used.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
where
I: SliceIndex<[T]>,
{
- // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds.
+ // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
// As a consequence, the resulting pointer cannot be null.
unsafe { NonNull::new_unchecked(self.as_ptr().get_unchecked_mut(index)) }
}
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T: ?Sized> const From<&mut T> for NonNull<T> {
+ /// Converts a `&mut T` to a `NonNull<T>`.
+ ///
+ /// This conversion is safe and infallible since references cannot be null.
#[inline]
fn from(reference: &mut T) -> Self {
// SAFETY: A mutable reference cannot be null.
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T: ?Sized> const From<&T> for NonNull<T> {
+ /// Converts a `&T` to a `NonNull<T>`.
+ ///
+ /// This conversion is safe and infallible since references cannot be null.
#[inline]
fn from(reference: &T) -> Self {
// SAFETY: A reference cannot be null, so the conditions for
/// Creates a new `Unique` if `ptr` is non-null.
#[inline]
- pub fn new(ptr: *mut T) -> Option<Self> {
+ pub const fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
// SAFETY: The pointer has already been checked and is not null.
Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
#[must_use]
#[inline]
- pub unsafe fn as_ref(&self) -> &T {
+ pub const unsafe fn as_ref(&self) -> &T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &*self.as_ptr() }
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
#[must_use]
#[inline]
- pub unsafe fn as_mut(&mut self) -> &mut T {
+ pub const unsafe fn as_mut(&mut self) -> &mut T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a mutable reference.
unsafe { &mut *self.as_ptr() }
#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> const From<&mut T> for Unique<T> {
+ /// Converts a `&mut T` to a `Unique<T>`.
+ ///
+ /// This conversion is infallible since references cannot be null.
#[inline]
fn from(reference: &mut T) -> Self {
// SAFETY: A mutable reference cannot be null
/// loads and stores of `u8`.
#[cfg(target_has_atomic_load_store = "8")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "AtomicBool"]
#[repr(C, align(1))]
pub struct AtomicBool {
v: UnsafeCell<u8>,
#[inline]
#[cfg(target_has_atomic_equal_alignment = "8")]
#[unstable(feature = "atomic_from_mut", issue = "76314")]
- pub fn from_mut(v: &mut bool) -> &Self {
+ pub fn from_mut(v: &mut bool) -> &mut Self {
// SAFETY: the mutable reference guarantees unique ownership, and
// alignment of both `bool` and `Self` is 1.
- unsafe { &*(v as *mut bool as *mut Self) }
+ unsafe { &mut *(v as *mut bool as *mut Self) }
}
/// Consumes the atomic and returns the contained value.
#[inline]
#[cfg(target_has_atomic_equal_alignment = "ptr")]
#[unstable(feature = "atomic_from_mut", issue = "76314")]
- pub fn from_mut(v: &mut *mut T) -> &Self {
+ pub fn from_mut(v: &mut *mut T) -> &mut Self {
use crate::mem::align_of;
let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
// SAFETY:
// - the mutable reference guarantees unique ownership.
// - the alignment of `*mut T` and `Self` is the same on all platforms
// supported by rust, as verified above.
- unsafe { &*(v as *mut *mut T as *mut Self) }
+ unsafe { &mut *(v as *mut *mut T as *mut Self) }
}
/// Consumes the atomic and returns the contained value.
#[stable(feature = "atomic_from", since = "1.23.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T> const From<*mut T> for AtomicPtr<T> {
+ /// Converts a `*mut T` into an `AtomicPtr<T>`.
#[inline]
fn from(p: *mut T) -> Self {
Self::new(p)
#[inline]
#[$cfg_align]
#[unstable(feature = "atomic_from_mut", issue = "76314")]
- pub fn from_mut(v: &mut $int_type) -> &Self {
+ pub fn from_mut(v: &mut $int_type) -> &mut Self {
use crate::mem::align_of;
let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
// SAFETY:
// - the mutable reference guarantees unique ownership.
// - the alignment of `$int_type` and `Self` is the
// same, as promised by $cfg_align and verified above.
- unsafe { &*(v as *mut $int_type as *mut Self) }
+ unsafe { &mut *(v as *mut $int_type as *mut Self) }
}
/// Consumes the atomic and returns the contained value.
/// the position of the nul byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
- trait SpecIntoVec {
- fn into_vec(self) -> Vec<u8>;
+ trait SpecNewImpl {
+ fn spec_new_impl(self) -> Result<CString, NulError>;
}
- impl<T: Into<Vec<u8>>> SpecIntoVec for T {
- default fn into_vec(self) -> Vec<u8> {
- self.into()
+
+ impl<T: Into<Vec<u8>>> SpecNewImpl for T {
+ default fn spec_new_impl(self) -> Result<CString, NulError> {
+ let bytes: Vec<u8> = self.into();
+ match memchr::memchr(0, &bytes) {
+ Some(i) => Err(NulError(i, bytes)),
+ None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
+ }
}
}
- // Specialization for avoiding reallocation.
- impl SpecIntoVec for &'_ [u8] {
- fn into_vec(self) -> Vec<u8> {
- let mut v = Vec::with_capacity(self.len() + 1);
- v.extend(self);
- v
+
+ // Specialization for avoiding reallocation
+ #[inline(always)] // Without that it is not inlined into specializations
+ fn spec_new_impl_bytes(bytes: &[u8]) -> Result<CString, NulError> {
+ // We cannot have such large slice that we would overflow here
+ // but using `checked_add` allows LLVM to assume that capacity never overflows
+ // and generate twice shorter code.
+ // `saturating_add` doesn't help for some reason.
+ let capacity = bytes.len().checked_add(1).unwrap();
+
+ // Allocate before validation to avoid duplication of allocation code.
+ // We still need to allocate and copy memory even if we get an error.
+ let mut buffer = Vec::with_capacity(capacity);
+ buffer.extend(bytes);
+
+ // Check memory of self instead of new buffer.
+ // This allows better optimizations if lto enabled.
+ match memchr::memchr(0, bytes) {
+ Some(i) => Err(NulError(i, buffer)),
+ None => Ok(unsafe { CString::from_vec_unchecked(buffer) }),
}
}
- impl SpecIntoVec for &'_ str {
- fn into_vec(self) -> Vec<u8> {
- let mut v = Vec::with_capacity(self.len() + 1);
- v.extend(self.as_bytes());
- v
+
+ impl SpecNewImpl for &'_ [u8] {
+ fn spec_new_impl(self) -> Result<CString, NulError> {
+ spec_new_impl_bytes(self)
}
}
- Self::_new(SpecIntoVec::into_vec(t))
- }
+ impl SpecNewImpl for &'_ str {
+ fn spec_new_impl(self) -> Result<CString, NulError> {
+ spec_new_impl_bytes(self.as_bytes())
+ }
+ }
- fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
- match memchr::memchr(0, &bytes) {
- Some(i) => Err(NulError(i, bytes)),
- None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
+ impl SpecNewImpl for &'_ mut [u8] {
+ fn spec_new_impl(self) -> Result<CString, NulError> {
+ spec_new_impl_bytes(self)
+ }
}
+
+ t.spec_new_impl()
}
/// Creates a C-compatible string by consuming a byte vector,
#[stable(feature = "cstring_from_cow_cstr", since = "1.28.0")]
impl<'a> From<Cow<'a, CStr>> for CString {
+ /// Converts a `Cow<'a, CStr>` into a `CString`, by copying the contents if they are
+ /// borrowed.
#[inline]
fn from(s: Cow<'a, CStr>) -> Self {
s.into_owned()
#[stable(feature = "box_from_c_str", since = "1.17.0")]
impl From<&CStr> for Box<CStr> {
+ /// Converts a `&CStr` into a `Box<CStr>`,
+ /// by copying the contents into a newly allocated [`Box`].
fn from(s: &CStr) -> Box<CStr> {
let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
#[stable(feature = "box_from_cow", since = "1.45.0")]
impl From<Cow<'_, CStr>> for Box<CStr> {
+ /// Converts a `Cow<'a, CStr>` into a `Box<CStr>`,
+ /// by copying the contents if they are borrowed.
#[inline]
fn from(cow: Cow<'_, CStr>) -> Box<CStr> {
match cow {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
- /// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> without copying or allocating.
+ /// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> by moving the [`CString`]
+ /// data into a new [`Arc`] buffer.
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&CStr> for Arc<CStr> {
+ /// Converts a `&CStr` into a `Arc<CStr>`,
+ /// by copying the contents into a newly allocated [`Arc`].
#[inline]
fn from(s: &CStr) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
- /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> without copying or allocating.
+ /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`]
+ /// data into a new [`Arc`] buffer.
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&CStr> for Rc<CStr> {
+ /// Converts a `&CStr` into a `Rc<CStr>`,
+ /// by copying the contents into a newly allocated [`Rc`].
#[inline]
fn from(s: &CStr) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
impl From<NulError> for io::Error {
/// Converts a [`NulError`] into a [`io::Error`].
fn from(_: NulError) -> io::Error {
- io::Error::new_const(io::ErrorKind::InvalidInput, &"data provided contains a nul byte")
+ io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
}
}
/// assert!(cstr.is_err());
/// ```
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
- pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
+ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
let nul_pos = memchr::memchr(0, bytes);
- if let Some(nul_pos) = nul_pos {
- if nul_pos + 1 != bytes.len() {
- return Err(FromBytesWithNulError::interior_nul(nul_pos));
+ match nul_pos {
+ Some(nul_pos) if nul_pos + 1 == bytes.len() => {
+ // SAFETY: We know there is only one nul byte, at the end
+ // of the byte slice.
+ Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
}
- Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) })
- } else {
- Err(FromBytesWithNulError::not_nul_terminated())
+ Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
+ None => Err(FromBytesWithNulError::not_nul_terminated()),
}
}
#[inline]
#[must_use]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
- #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
+ #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
// SAFETY: Casting to CStr is safe because its internal representation
// is a [u8] too (safe only inside std).
#[stable(feature = "cstring_asref", since = "1.7.0")]
impl From<&CStr> for CString {
+ /// Copies the contents of the `&CStr` into a newly allocated `CString`.
fn from(s: &CStr) -> CString {
s.to_owned()
}
use crate::borrow::{Borrow, Cow};
use crate::cmp;
+use crate::collections::TryReserveError;
use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::iter::{Extend, FromIterator};
self.inner.reserve(additional)
}
+ /// Tries to reserve capacity for at least `additional` more length units
+ /// in the given `OsString`. The string may reserve more space to avoid
+ /// frequent reallocations. After calling `try_reserve`, capacity will be
+ /// greater than or equal to `self.len() + additional`. Does nothing if
+ /// capacity is already sufficient.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(try_reserve_2)]
+ /// use std::ffi::{OsStr, OsString};
+ /// use std::collections::TryReserveError;
+ ///
+ /// fn process_data(data: &str) -> Result<OsString, TryReserveError> {
+ /// let mut s = OsString::new();
+ ///
+ /// // Pre-reserve the memory, exiting if we can't
+ /// s.try_reserve(OsStr::new(data).len())?;
+ ///
+ /// // Now we know this can't OOM in the middle of our complex work
+ /// s.push(data);
+ ///
+ /// Ok(s)
+ /// }
+ /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
+ /// ```
+ #[unstable(feature = "try_reserve_2", issue = "91789")]
+ #[inline]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve(additional)
+ }
+
/// Reserves the minimum capacity for exactly `additional` more capacity to
/// be inserted in the given `OsString`. Does nothing if the capacity is
/// already sufficient.
self.inner.reserve_exact(additional)
}
+ /// Tries to reserve the minimum capacity for exactly `additional`
+ /// more length units in the given `OsString`. After calling
+ /// `try_reserve_exact`, capacity will be greater than or equal to
+ /// `self.len() + additional` if it returns `Ok(())`.
+ /// Does nothing if the capacity is already sufficient.
+ ///
+ /// Note that the allocator may give the `OsString` more space than it
+ /// requests. Therefore, capacity can not be relied upon to be precisely
+ /// minimal. Prefer [`try_reserve`] if future insertions are expected.
+ ///
+ /// [`try_reserve`]: OsString::try_reserve
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(try_reserve_2)]
+ /// use std::ffi::{OsStr, OsString};
+ /// use std::collections::TryReserveError;
+ ///
+ /// fn process_data(data: &str) -> Result<OsString, TryReserveError> {
+ /// let mut s = OsString::new();
+ ///
+ /// // Pre-reserve the memory, exiting if we can't
+ /// s.try_reserve_exact(OsStr::new(data).len())?;
+ ///
+ /// // Now we know this can't OOM in the middle of our complex work
+ /// s.push(data);
+ ///
+ /// Ok(s)
+ /// }
+ /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
+ /// ```
+ #[unstable(feature = "try_reserve_2", issue = "91789")]
+ #[inline]
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve_exact(additional)
+ }
+
/// Shrinks the capacity of the `OsString` to match its length.
///
/// # Examples
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
+ /// Copies any value implementing <code>[AsRef]<[OsStr]></code>
+ /// into a newly allocated [`OsString`].
fn from(s: &T) -> OsString {
s.as_ref().to_os_string()
}
#[stable(feature = "box_from_os_str", since = "1.17.0")]
impl From<&OsStr> for Box<OsStr> {
+ /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>.
#[inline]
fn from(s: &OsStr) -> Box<OsStr> {
let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
#[stable(feature = "box_from_cow", since = "1.45.0")]
impl From<Cow<'_, OsStr>> for Box<OsStr> {
+ /// Converts a `Cow<'a, OsStr>` into a <code>[Box]<[OsStr]></code>,
+ /// by copying the contents if they are borrowed.
#[inline]
fn from(cow: Cow<'_, OsStr>) -> Box<OsStr> {
match cow {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
- /// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> without copying or allocating.
+ /// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> by moving the [`OsString`]
+ /// data into a new [`Arc`] buffer.
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&OsStr> for Arc<OsStr> {
+ /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>.
#[inline]
fn from(s: &OsStr) -> Arc<OsStr> {
let arc = s.inner.into_arc();
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
- /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> without copying or allocating.
+ /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`]
+ /// data into a new [`Rc`] buffer.
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&OsStr> for Rc<OsStr> {
+ /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>.
#[inline]
fn from(s: &OsStr) -> Rc<OsStr> {
let rc = s.inner.into_rc();
#[stable(feature = "cow_from_osstr", since = "1.28.0")]
impl<'a> From<OsString> for Cow<'a, OsStr> {
+ /// Moves the string into a [`Cow::Owned`].
#[inline]
fn from(s: OsString) -> Cow<'a, OsStr> {
Cow::Owned(s)
#[stable(feature = "cow_from_osstr", since = "1.28.0")]
impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
+ /// Converts the string reference into a [`Cow::Borrowed`].
#[inline]
fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
Cow::Borrowed(s)
#[stable(feature = "cow_from_osstr", since = "1.28.0")]
impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
+ /// Converts the string reference into a [`Cow::Borrowed`].
#[inline]
fn from(s: &'a OsString) -> Cow<'a, OsStr> {
Cow::Borrowed(s.as_os_str())
#[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")]
impl<'a> From<Cow<'a, OsStr>> for OsString {
+ /// Converts a `Cow<'a, OsStr>` into an [`OsString`],
+ /// by copying the contents if they are borrowed.
#[inline]
fn from(s: Cow<'a, OsStr>) -> Self {
s.into_owned()
use crate::borrow::{Borrow, Cow};
use crate::cmp;
+use crate::collections::TryReserveError;
use crate::error::Error;
use crate::fmt;
use crate::fs;
use crate::sync::Arc;
use crate::ffi::{OsStr, OsString};
-
+use crate::sys;
use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR};
////////////////////////////////////////////////////////////////////////////////
self.inner.reserve(additional)
}
+ /// Invokes [`try_reserve`] on the underlying instance of [`OsString`].
+ ///
+ /// [`try_reserve`]: OsString::try_reserve
+ #[unstable(feature = "try_reserve_2", issue = "91789")]
+ #[inline]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve(additional)
+ }
+
/// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].
///
/// [`reserve_exact`]: OsString::reserve_exact
self.inner.reserve_exact(additional)
}
+ /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`].
+ ///
+ /// [`try_reserve_exact`]: OsString::try_reserve_exact
+ #[unstable(feature = "try_reserve_2", issue = "91789")]
+ #[inline]
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve_exact(additional)
+ }
+
/// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].
///
/// [`shrink_to_fit`]: OsString::shrink_to_fit
#[stable(feature = "path_buf_from_box", since = "1.18.0")]
impl From<Box<Path>> for PathBuf {
- /// Converts a `Box<Path>` into a `PathBuf`
+ /// Converts a <code>[Box]<[Path]></code> into a [`PathBuf`].
///
/// This conversion does not allocate or copy memory.
#[inline]
#[stable(feature = "box_from_path_buf", since = "1.20.0")]
impl From<PathBuf> for Box<Path> {
- /// Converts a `PathBuf` into a `Box<Path>`
+ /// Converts a [`PathBuf`] into a <code>[Box]<[Path]></code>.
///
/// This conversion currently should not allocate memory,
/// but this behavior is not guaranteed on all platforms or in all future versions.
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
- /// Converts a borrowed `OsStr` to a `PathBuf`.
+ /// Converts a borrowed [`OsStr`] to a [`PathBuf`].
///
/// Allocates a [`PathBuf`] and copies the data into it.
#[inline]
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Arc<Path> {
- /// Converts a [`PathBuf`] into an [`Arc`] by moving the [`PathBuf`] data into a new [`Arc`] buffer.
+ /// Converts a [`PathBuf`] into an <code>[Arc]<[Path]></code> by moving the [`PathBuf`] data
+ /// into a new [`Arc`] buffer.
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.into_os_string());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Rc<Path> {
- /// Converts a [`PathBuf`] into an [`Rc`] by moving the [`PathBuf`] data into a new `Rc` buffer.
+ /// Converts a [`PathBuf`] into an <code>[Rc]<[Path]></code> by moving the [`PathBuf`] data into
+ /// a new [`Rc`] buffer.
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.into_os_string());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&Path> for Rc<Path> {
- /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new `Rc` buffer.
+ /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.as_os_str());
/// This function will traverse symbolic links to query information about the
/// destination file. In case of broken symbolic links this will return `Ok(false)`.
///
- /// As opposed to the `exists()` method, this one doesn't silently ignore errors
+ /// As opposed to the [`exists()`] method, this one doesn't silently ignore errors
/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
/// denied on some of the parent directories.)
///
/// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
/// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
/// ```
+ ///
+ /// [`exists()`]: Self::exists
// FIXME: stabilization should modify documentation of `exists()` to recommend this method
// instead.
#[unstable(feature = "path_try_exists", issue = "83186")]
/// use std::os::unix::fs::symlink;
///
/// let link_path = Path::new("link");
- /// symlink("/origin_does_not_exists/", link_path).unwrap();
+ /// symlink("/origin_does_not_exist/", link_path).unwrap();
/// assert_eq!(link_path.is_symlink(), true);
/// assert_eq!(link_path.exists(), false);
/// ```
/// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call
/// [`fs::Metadata::is_symlink`] if it was [`Ok`].
#[must_use]
- #[stable(feature = "is_symlink", since = "1.57.0")]
+ #[stable(feature = "is_symlink", since = "1.58.0")]
pub fn is_symlink(&self) -> bool {
fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
}
impl Hash for Path {
fn hash<H: Hasher>(&self, h: &mut H) {
let bytes = self.as_u8_slice();
- let prefix_len = match parse_prefix(&self.inner) {
+ let (prefix_len, verbatim) = match parse_prefix(&self.inner) {
Some(prefix) => {
prefix.hash(h);
- prefix.len()
+ (prefix.len(), prefix.is_verbatim())
}
- None => 0,
+ None => (0, false),
};
let bytes = &bytes[prefix_len..];
let mut bytes_hashed = 0;
for i in 0..bytes.len() {
- if is_sep_byte(bytes[i]) {
+ let is_sep = if verbatim { is_verbatim_sep(bytes[i]) } else { is_sep_byte(bytes[i]) };
+ if is_sep {
if i > component_start {
let to_hash = &bytes[component_start..i];
h.write(to_hash);
}
// skip over separator and optionally a following CurDir item
- // since components() would normalize these away
- component_start = i + match bytes[i..] {
- [_, b'.', b'/', ..] | [_, b'.'] => 2,
- _ => 1,
- };
+ // since components() would normalize these away.
+ component_start = i + 1;
+
+ let tail = &bytes[component_start..];
+
+ if !verbatim {
+ component_start += match tail {
+ [b'.'] => 1,
+ [b'.', sep @ _, ..] if is_sep_byte(*sep) => 1,
+ _ => 0,
+ };
+ }
}
}
"prefix not found"
}
}
+
+/// Makes the path absolute without accessing the filesystem.
+///
+/// If the path is relative, the current directory is used as the base directory.
+/// All intermediate components will be resolved according to platforms-specific
+/// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not
+/// resolve symlinks and may succeed even if the path does not exist.
+///
+/// If the `path` is empty or getting the
+/// [current directory][crate::env::current_dir] fails then an error will be
+/// returned.
+///
+/// # Examples
+///
+/// ## Posix paths
+///
+/// ```
+/// #![feature(absolute_path)]
+/// # #[cfg(unix)]
+/// fn main() -> std::io::Result<()> {
+/// use std::path::{self, Path};
+///
+/// // Relative to absolute
+/// let absolute = path::absolute("foo/./bar")?;
+/// assert!(absolute.ends_with("foo/bar"));
+///
+/// // Absolute to absolute
+/// let absolute = path::absolute("/foo//test/.././bar.rs")?;
+/// assert_eq!(absolute, Path::new("/foo/test/../bar.rs"));
+/// Ok(())
+/// }
+/// # #[cfg(not(unix))]
+/// # fn main() {}
+/// ```
+///
+/// The path is resolved using [POSIX semantics][posix-semantics] except that
+/// it stops short of resolving symlinks. This means it will keep `..`
+/// components and trailing slashes.
+///
+/// ## Windows paths
+///
+/// ```
+/// #![feature(absolute_path)]
+/// # #[cfg(windows)]
+/// fn main() -> std::io::Result<()> {
+/// use std::path::{self, Path};
+///
+/// // Relative to absolute
+/// let absolute = path::absolute("foo/./bar")?;
+/// assert!(absolute.ends_with(r"foo\bar"));
+///
+/// // Absolute to absolute
+/// let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?;
+///
+/// assert_eq!(absolute, Path::new(r"C:\foo\bar.rs"));
+/// Ok(())
+/// }
+/// # #[cfg(not(windows))]
+/// # fn main() {}
+/// ```
+///
+/// For verbatim paths this will simply return the path as given. For other
+/// paths this is currently equivalent to calling [`GetFullPathNameW`][windows-path]
+/// This may change in the future.
+///
+/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
+/// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
+#[unstable(feature = "absolute_path", issue = "92750")]
+pub fn absolute<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
+ let path = path.as_ref();
+ if path.as_os_str().is_empty() {
+ Err(io::const_io_error!(io::ErrorKind::InvalidInput, "cannot make an empty path absolute",))
+ } else {
+ sys::path::absolute(path)
+ }
+}
use crate::ffi::OsStr;
use crate::fmt;
use crate::fs;
-use crate::io::{self, Initializer, IoSlice, IoSliceMut};
+use crate::io::{self, IoSlice, IoSliceMut};
use crate::num::NonZeroI32;
use crate::path::Path;
use crate::str;
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
-
- #[inline]
- unsafe fn initializer(&self) -> Initializer {
- // SAFETY: Read is guaranteed to work on uninitialized memory
- unsafe { Initializer::nop() }
- }
}
impl AsInner<AnonPipe> for ChildStdout {
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
-
- #[inline]
- unsafe fn initializer(&self) -> Initializer {
- // SAFETY: Read is guaranteed to work on uninitialized memory
- unsafe { Initializer::nop() }
- }
}
impl AsInner<AnonPipe> for ChildStderr {
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStdin> for Stdio {
- /// Converts a `ChildStdin` into a `Stdio`
+ /// Converts a [`ChildStdin`] into a [`Stdio`].
///
/// # Examples
///
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStdout> for Stdio {
- /// Converts a `ChildStdout` into a `Stdio`
+ /// Converts a [`ChildStdout`] into a [`Stdio`].
///
/// # Examples
///
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStderr> for Stdio {
- /// Converts a `ChildStderr` into a `Stdio`
+ /// Converts a [`ChildStderr`] into a [`Stdio`].
///
/// # Examples
///
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<fs::File> for Stdio {
- /// Converts a `File` into a `Stdio`
+ /// Converts a [`File`](fs::File) into a [`Stdio`].
///
/// # Examples
///
/// ```
/// #![feature(exit_status_error)]
/// # if cfg!(unix) {
- /// use std::convert::TryFrom;
/// use std::num::NonZeroI32;
/// use std::process::Command;
///
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
}
+impl ExitCode {
+ // This should not be stabilized when stabilizing ExitCode, we don't know that i32 will serve
+ // all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we
+ // likely want to isolate users anything that could restrict the platform specific
+ // representation of an ExitCode
+ //
+ // More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426
+ /// Convert an ExitCode into an i32
+ #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+ #[inline]
+ pub fn to_i32(self) -> i32 {
+ self.0.as_i32()
+ }
+}
+
+#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+impl From<u8> for ExitCode {
+ /// Construct an exit code from an arbitrary u8 value.
+ fn from(code: u8) -> Self {
+ ExitCode(imp::ExitCode::from(code))
+ }
+}
+
impl Child {
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
/// error is returned.
pub trait Termination {
/// Is called to get the representation of the value as status code.
/// This status code is returned to the operating system.
- fn report(self) -> i32;
+ fn report(self) -> ExitCode;
}
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for () {
#[inline]
- fn report(self) -> i32 {
+ fn report(self) -> ExitCode {
ExitCode::SUCCESS.report()
}
}
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Debug> Termination for Result<(), E> {
- fn report(self) -> i32 {
+ fn report(self) -> ExitCode {
match self {
Ok(()) => ().report(),
Err(err) => Err::<!, _>(err).report(),
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for ! {
- fn report(self) -> i32 {
+ fn report(self) -> ExitCode {
self
}
}
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Debug> Termination for Result<!, E> {
- fn report(self) -> i32 {
+ fn report(self) -> ExitCode {
let Err(err) = self;
eprintln!("Error: {:?}", err);
ExitCode::FAILURE.report()
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Debug> Termination for Result<Infallible, E> {
- fn report(self) -> i32 {
+ fn report(self) -> ExitCode {
let Err(err) = self;
Err::<!, _>(err).report()
}
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for ExitCode {
#[inline]
- fn report(self) -> i32 {
- self.0.as_i32()
+ fn report(self) -> ExitCode {
+ self
}
}