Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #128128

Merged
merged 17 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion library/alloc/src/collections/binary_heap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
/// heap.push(4);
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_binary_heap_new_in", issue = "112353")]
#[rustc_const_unstable(feature = "const_binary_heap_new_in", issue = "125961")]
#[must_use]
pub const fn new_in(alloc: A) -> BinaryHeap<T, A> {
BinaryHeap { data: Vec::new_in(alloc) }
Expand Down
4 changes: 2 additions & 2 deletions library/alloc/src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl str {
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
pub fn replace<P: Pattern>(&self, from: P, to: &str) -> String {
let mut result = String::new();
let mut last_end = 0;
for (start, part) in self.match_indices(from) {
Expand Down Expand Up @@ -309,7 +309,7 @@ impl str {
#[must_use = "this returns the replaced string as a new allocation, \
without modifying the original"]
#[stable(feature = "str_replacen", since = "1.16.0")]
pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String {
pub fn replacen<P: Pattern>(&self, pat: P, to: &str, count: usize) -> String {
// Hope to reduce the times of re-allocation
let mut result = String::with_capacity(32);
let mut last_end = 0;
Expand Down
27 changes: 15 additions & 12 deletions library/alloc/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1497,10 +1497,7 @@ impl String {
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")]
pub fn remove_matches<'a, P>(&'a mut self, pat: P)
where
P: for<'x> Pattern<'x>,
{
pub fn remove_matches<P: Pattern>(&mut self, pat: P) {
use core::str::pattern::Searcher;

let rejections = {
Expand Down Expand Up @@ -2288,35 +2285,41 @@ impl<'a> Extend<Cow<'a, str>> for String {
reason = "API not fully fleshed out and ready to be stabilized",
issue = "27721"
)]
impl<'a, 'b> Pattern<'a> for &'b String {
type Searcher = <&'b str as Pattern<'a>>::Searcher;
impl<'b> Pattern for &'b String {
type Searcher<'a> = <&'b str as Pattern>::Searcher<'a>;

fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher {
fn into_searcher(self, haystack: &str) -> <&'b str as Pattern>::Searcher<'_> {
self[..].into_searcher(haystack)
}

#[inline]
fn is_contained_in(self, haystack: &'a str) -> bool {
fn is_contained_in(self, haystack: &str) -> bool {
self[..].is_contained_in(haystack)
}

#[inline]
fn is_prefix_of(self, haystack: &'a str) -> bool {
fn is_prefix_of(self, haystack: &str) -> bool {
self[..].is_prefix_of(haystack)
}

#[inline]
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
fn strip_prefix_of(self, haystack: &str) -> Option<&str> {
self[..].strip_prefix_of(haystack)
}

#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool {
fn is_suffix_of<'a>(self, haystack: &'a str) -> bool
where
Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>,
{
self[..].is_suffix_of(haystack)
}

#[inline]
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&str>
where
Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>,
{
self[..].strip_suffix_of(haystack)
}
}
Expand Down
14 changes: 6 additions & 8 deletions library/alloc/tests/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1927,12 +1927,10 @@ mod pattern {
}
}

fn cmp_search_to_vec<'a>(
rev: bool,
pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
haystack: &'a str,
right: Vec<SearchStep>,
) {
fn cmp_search_to_vec<P>(rev: bool, pat: P, haystack: &str, right: Vec<SearchStep>)
where
P: for<'a> Pattern<Searcher<'a>: ReverseSearcher<'a>>,
{
let mut searcher = pat.into_searcher(haystack);
let mut v = vec![];
loop {
Expand Down Expand Up @@ -2191,9 +2189,9 @@ generate_iterator_test! {
fn different_str_pattern_forwarding_lifetimes() {
use std::str::pattern::Pattern;

fn foo<'a, P>(p: P)
fn foo<P>(p: P)
where
for<'b> &'b P: Pattern<'a>,
for<'b> &'b P: Pattern,
{
for _ in 0..3 {
"asdf".find(&p);
Expand Down
12 changes: 9 additions & 3 deletions library/core/src/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//! const SOME_PROPERTY: bool = true;
//! }
//!
//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
//! # trait QueryId { const SOME_PROPERTY: ::core::primitive::bool; }
//! ```
//!
//! Note that the `SOME_PROPERTY` associated constant would not compile, as its
Expand All @@ -25,11 +25,17 @@
//! pub struct bool;
//!
//! impl QueryId for bool {
//! const SOME_PROPERTY: core::primitive::bool = true;
//! const SOME_PROPERTY: ::core::primitive::bool = true;
//! }
//!
//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
//! # trait QueryId { const SOME_PROPERTY: ::core::primitive::bool; }
//! ```
//!
//! We also used `::core` instead of `core`, because `core` can be
//! shadowed, too. Paths, starting with `::`, are searched in
//! the [extern prelude] since Edition 2018.
//!
//! [extern prelude]: https://doc.rust-lang.org/nightly/reference/names/preludes.html#extern-prelude

#[stable(feature = "core_primitive", since = "1.43.0")]
pub use bool;
Expand Down
115 changes: 115 additions & 0 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4522,6 +4522,121 @@ impl<T> [T] {
// are disjunct and in bounds.
unsafe { Ok(self.get_many_unchecked_mut(indices)) }
}

/// Returns the index that an element reference points to.
///
/// Returns `None` if `element` does not point within the slice or if it points between elements.
///
/// This method is useful for extending slice iterators like [`slice::split`].
///
/// Note that this uses pointer arithmetic and **does not compare elements**.
/// To find the index of an element via comparison, use
/// [`.iter().position()`](crate::iter::Iterator::position) instead.
///
/// # Panics
/// Panics if `T` is zero-sized.
///
/// # Examples
/// Basic usage:
/// ```
/// #![feature(substr_range)]
///
/// let nums: &[u32] = &[1, 7, 1, 1];
/// let num = &nums[2];
///
/// assert_eq!(num, &1);
/// assert_eq!(nums.elem_offset(num), Some(2));
/// ```
/// Returning `None` with an in-between element:
/// ```
/// #![feature(substr_range)]
///
/// let arr: &[[u32; 2]] = &[[0, 1], [2, 3]];
/// let flat_arr: &[u32] = arr.as_flattened();
///
/// let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap();
/// let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap();
///
/// assert_eq!(ok_elm, &[0, 1]);
/// assert_eq!(weird_elm, &[1, 2]);
///
/// assert_eq!(arr.elem_offset(ok_elm), Some(0)); // Points to element 0
/// assert_eq!(arr.elem_offset(weird_elm), None); // Points between element 0 and 1
/// ```
#[must_use]
#[unstable(feature = "substr_range", issue = "126769")]
pub fn elem_offset(&self, element: &T) -> Option<usize> {
if T::IS_ZST {
panic!("elements are zero-sized");
}

let self_start = self.as_ptr() as usize;
let elem_start = element as *const T as usize;

let byte_offset = elem_start.wrapping_sub(self_start);

if byte_offset % mem::size_of::<T>() != 0 {
return None;
}

let offset = byte_offset / mem::size_of::<T>();

if offset < self.len() { Some(offset) } else { None }
}

/// Returns the range of indices that a subslice points to.
///
/// Returns `None` if `subslice` does not point within the slice or if it points between elements.
///
/// This method **does not compare elements**. Instead, this method finds the location in the slice that
/// `subslice` was obtained from. To find the index of a subslice via comparison, instead use
/// [`.windows()`](slice::windows)[`.position()`](crate::iter::Iterator::position).
///
/// This method is useful for extending slice iterators like [`slice::split`].
///
/// Note that this may return a false positive (either `Some(0..0)` or `Some(self.len()..self.len())`)
/// if `subslice` has a length of zero and points to the beginning or end of another, separate, slice.
///
/// # Panics
/// Panics if `T` is zero-sized.
///
/// # Examples
/// Basic usage:
/// ```
/// #![feature(substr_range)]
///
/// let nums = &[0, 5, 10, 0, 0, 5];
///
/// let mut iter = nums
/// .split(|t| *t == 0)
/// .map(|n| nums.subslice_range(n).unwrap());
///
/// assert_eq!(iter.next(), Some(0..0));
/// assert_eq!(iter.next(), Some(1..3));
/// assert_eq!(iter.next(), Some(4..4));
/// assert_eq!(iter.next(), Some(5..6));
/// ```
#[must_use]
#[unstable(feature = "substr_range", issue = "126769")]
pub fn subslice_range(&self, subslice: &[T]) -> Option<Range<usize>> {
if T::IS_ZST {
panic!("elements are zero-sized");
}

let self_start = self.as_ptr() as usize;
let subslice_start = subslice.as_ptr() as usize;

let byte_start = subslice_start.wrapping_sub(self_start);

if byte_start % core::mem::size_of::<T>() != 0 {
return None;
}

let start = byte_start / core::mem::size_of::<T>();
let end = start.wrapping_add(subslice.len());

if start <= self.len() && end <= self.len() { Some(start..end) } else { None }
}
}

impl<T, const N: usize> [[T; N]] {
Expand Down
Loading
Loading