Auto merge of #128128 - matthiaskrgr:rollup-jz6w0ck, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #125962 (Update tracking issue for `const_binary_heap_new_in`) - #126770 (Add elem_offset and related methods) - #127481 (Remove generic lifetime parameter of trait `Pattern`) - #128043 (Docs for core::primitive: mention that "core" can be shadowed, too, so we should write "::core") - #128092 (Remove wrapper functions from c.rs) - #128100 (Allow to pass a full path for `run-make` tests) - #128106 (Fix return type of FileAttr methods on AIX target) - #128108 (ensure std step before preparing sysroot) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f4831e6317
24 changed files with 438 additions and 333 deletions
|
@ -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) }
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
|
|
|
@ -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]] {
|
||||
|
|
|
@ -411,7 +411,7 @@ macro_rules! derive_pattern_clone {
|
|||
(clone $t:ident with |$s:ident| $e:expr) => {
|
||||
impl<'a, P> Clone for $t<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: Clone>,
|
||||
P: Pattern<Searcher<'a>: Clone>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
let $s = self;
|
||||
|
@ -424,7 +424,7 @@ macro_rules! derive_pattern_clone {
|
|||
/// This macro generates two public iterator structs
|
||||
/// wrapping a private internal one that makes use of the `Pattern` API.
|
||||
///
|
||||
/// For all patterns `P: Pattern<'a>` the following items will be
|
||||
/// For all patterns `P: Pattern` the following items will be
|
||||
/// generated (generics omitted):
|
||||
///
|
||||
/// struct $forward_iterator($internal_iterator);
|
||||
|
@ -484,12 +484,12 @@ macro_rules! generate_pattern_iterators {
|
|||
} => {
|
||||
$(#[$forward_iterator_attribute])*
|
||||
$(#[$common_stability_attribute])*
|
||||
pub struct $forward_iterator<'a, P: Pattern<'a>>(pub(super) $internal_iterator<'a, P>);
|
||||
pub struct $forward_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>);
|
||||
|
||||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> fmt::Debug for $forward_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
P: Pattern<Searcher<'a>: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple(stringify!($forward_iterator))
|
||||
|
@ -499,7 +499,7 @@ macro_rules! generate_pattern_iterators {
|
|||
}
|
||||
|
||||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P: Pattern<'a>> Iterator for $forward_iterator<'a, P> {
|
||||
impl<'a, P: Pattern> Iterator for $forward_iterator<'a, P> {
|
||||
type Item = $iterty;
|
||||
|
||||
#[inline]
|
||||
|
@ -511,7 +511,7 @@ macro_rules! generate_pattern_iterators {
|
|||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> Clone for $forward_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: Clone>,
|
||||
P: Pattern<Searcher<'a>: Clone>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
$forward_iterator(self.0.clone())
|
||||
|
@ -520,12 +520,12 @@ macro_rules! generate_pattern_iterators {
|
|||
|
||||
$(#[$reverse_iterator_attribute])*
|
||||
$(#[$common_stability_attribute])*
|
||||
pub struct $reverse_iterator<'a, P: Pattern<'a>>(pub(super) $internal_iterator<'a, P>);
|
||||
pub struct $reverse_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>);
|
||||
|
||||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> fmt::Debug for $reverse_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
P: Pattern<Searcher<'a>: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple(stringify!($reverse_iterator))
|
||||
|
@ -537,7 +537,7 @@ macro_rules! generate_pattern_iterators {
|
|||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> Iterator for $reverse_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
P: Pattern<Searcher<'a>: ReverseSearcher<'a>>,
|
||||
{
|
||||
type Item = $iterty;
|
||||
|
||||
|
@ -550,7 +550,7 @@ macro_rules! generate_pattern_iterators {
|
|||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> Clone for $reverse_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: Clone>,
|
||||
P: Pattern<Searcher<'a>: Clone>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
$reverse_iterator(self.0.clone())
|
||||
|
@ -558,12 +558,12 @@ macro_rules! generate_pattern_iterators {
|
|||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {}
|
||||
impl<'a, P: Pattern> FusedIterator for $forward_iterator<'a, P> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, P> FusedIterator for $reverse_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
P: Pattern<Searcher<'a>: ReverseSearcher<'a>>,
|
||||
{}
|
||||
|
||||
generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*,
|
||||
|
@ -578,7 +578,7 @@ macro_rules! generate_pattern_iterators {
|
|||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>,
|
||||
P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<$iterty> {
|
||||
|
@ -589,7 +589,7 @@ macro_rules! generate_pattern_iterators {
|
|||
$(#[$common_stability_attribute])*
|
||||
impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>,
|
||||
P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<$iterty> {
|
||||
|
@ -609,17 +609,17 @@ derive_pattern_clone! {
|
|||
with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
|
||||
}
|
||||
|
||||
pub(super) struct SplitInternal<'a, P: Pattern<'a>> {
|
||||
pub(super) struct SplitInternal<'a, P: Pattern> {
|
||||
pub(super) start: usize,
|
||||
pub(super) end: usize,
|
||||
pub(super) matcher: P::Searcher,
|
||||
pub(super) matcher: P::Searcher<'a>,
|
||||
pub(super) allow_trailing_empty: bool,
|
||||
pub(super) finished: bool,
|
||||
}
|
||||
|
||||
impl<'a, P> fmt::Debug for SplitInternal<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
P: Pattern<Searcher<'a>: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SplitInternal")
|
||||
|
@ -632,7 +632,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
||||
impl<'a, P: Pattern> SplitInternal<'a, P> {
|
||||
#[inline]
|
||||
fn get_end(&mut self) -> Option<&'a str> {
|
||||
if !self.finished {
|
||||
|
@ -689,7 +689,7 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
|||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a str>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
if self.finished {
|
||||
return None;
|
||||
|
@ -726,7 +726,7 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
|||
#[inline]
|
||||
fn next_back_inclusive(&mut self) -> Option<&'a str>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
if self.finished {
|
||||
return None;
|
||||
|
@ -796,7 +796,7 @@ generate_pattern_iterators! {
|
|||
delegate double ended;
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> Split<'a, P> {
|
||||
impl<'a, P: Pattern> Split<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
@ -819,7 +819,7 @@ impl<'a, P: Pattern<'a>> Split<'a, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> RSplit<'a, P> {
|
||||
impl<'a, P: Pattern> RSplit<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
@ -860,7 +860,7 @@ generate_pattern_iterators! {
|
|||
delegate double ended;
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
|
||||
impl<'a, P: Pattern> SplitTerminator<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
@ -883,7 +883,7 @@ impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
|
||||
impl<'a, P: Pattern> RSplitTerminator<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
@ -911,7 +911,7 @@ derive_pattern_clone! {
|
|||
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
|
||||
}
|
||||
|
||||
pub(super) struct SplitNInternal<'a, P: Pattern<'a>> {
|
||||
pub(super) struct SplitNInternal<'a, P: Pattern> {
|
||||
pub(super) iter: SplitInternal<'a, P>,
|
||||
/// The number of splits remaining
|
||||
pub(super) count: usize,
|
||||
|
@ -919,7 +919,7 @@ pub(super) struct SplitNInternal<'a, P: Pattern<'a>> {
|
|||
|
||||
impl<'a, P> fmt::Debug for SplitNInternal<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
P: Pattern<Searcher<'a>: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SplitNInternal")
|
||||
|
@ -929,7 +929,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
|
||||
impl<'a, P: Pattern> SplitNInternal<'a, P> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a str> {
|
||||
match self.count {
|
||||
|
@ -948,7 +948,7 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
|
|||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a str>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
match self.count {
|
||||
0 => None,
|
||||
|
@ -987,7 +987,7 @@ generate_pattern_iterators! {
|
|||
delegate single ended;
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitN<'a, P> {
|
||||
impl<'a, P: Pattern> SplitN<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
@ -1010,7 +1010,7 @@ impl<'a, P: Pattern<'a>> SplitN<'a, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
|
||||
impl<'a, P: Pattern> RSplitN<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
@ -1038,18 +1038,18 @@ derive_pattern_clone! {
|
|||
with |s| MatchIndicesInternal(s.0.clone())
|
||||
}
|
||||
|
||||
pub(super) struct MatchIndicesInternal<'a, P: Pattern<'a>>(pub(super) P::Searcher);
|
||||
pub(super) struct MatchIndicesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>);
|
||||
|
||||
impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
P: Pattern<Searcher<'a>: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MatchIndicesInternal").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
|
||||
impl<'a, P: Pattern> MatchIndicesInternal<'a, P> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(usize, &'a str)> {
|
||||
self.0
|
||||
|
@ -1061,7 +1061,7 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
|
|||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(usize, &'a str)>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
self.0
|
||||
.next_match_back()
|
||||
|
@ -1093,18 +1093,18 @@ derive_pattern_clone! {
|
|||
with |s| MatchesInternal(s.0.clone())
|
||||
}
|
||||
|
||||
pub(super) struct MatchesInternal<'a, P: Pattern<'a>>(pub(super) P::Searcher);
|
||||
pub(super) struct MatchesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>);
|
||||
|
||||
impl<'a, P> fmt::Debug for MatchesInternal<'a, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: fmt::Debug>,
|
||||
P: Pattern<Searcher<'a>: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MatchesInternal").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
|
||||
impl<'a, P: Pattern> MatchesInternal<'a, P> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a str> {
|
||||
// SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
|
||||
|
@ -1117,7 +1117,7 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
|
|||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a str>
|
||||
where
|
||||
P::Searcher: ReverseSearcher<'a>,
|
||||
P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
// SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
|
||||
self.0.next_match_back().map(|(a, b)| unsafe {
|
||||
|
@ -1288,7 +1288,7 @@ pub struct SplitAsciiWhitespace<'a> {
|
|||
///
|
||||
/// [`split_inclusive`]: str::split_inclusive
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
pub struct SplitInclusive<'a, P: Pattern<'a>>(pub(super) SplitInternal<'a, P>);
|
||||
pub struct SplitInclusive<'a, P: Pattern>(pub(super) SplitInternal<'a, P>);
|
||||
|
||||
#[stable(feature = "split_whitespace", since = "1.1.0")]
|
||||
impl<'a> Iterator for SplitWhitespace<'a> {
|
||||
|
@ -1410,7 +1410,7 @@ impl<'a> SplitAsciiWhitespace<'a> {
|
|||
}
|
||||
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> {
|
||||
impl<'a, P: Pattern> Iterator for SplitInclusive<'a, P> {
|
||||
type Item = &'a str;
|
||||
|
||||
#[inline]
|
||||
|
@ -1420,7 +1420,7 @@ impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> {
|
|||
}
|
||||
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
|
||||
impl<'a, P: Pattern<Searcher<'a>: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SplitInclusive").field("0", &self.0).finish()
|
||||
}
|
||||
|
@ -1428,14 +1428,14 @@ impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a,
|
|||
|
||||
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> {
|
||||
impl<'a, P: Pattern<Searcher<'a>: Clone>> Clone for SplitInclusive<'a, P> {
|
||||
fn clone(&self) -> Self {
|
||||
SplitInclusive(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
impl<'a, P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>> DoubleEndedIterator
|
||||
impl<'a, P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>> DoubleEndedIterator
|
||||
for SplitInclusive<'a, P>
|
||||
{
|
||||
#[inline]
|
||||
|
@ -1445,9 +1445,9 @@ impl<'a, P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>> DoubleEndedIterator
|
|||
}
|
||||
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
|
||||
impl<'a, P: Pattern> FusedIterator for SplitInclusive<'a, P> {}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
|
||||
impl<'a, P: Pattern> SplitInclusive<'a, P> {
|
||||
/// Returns remainder of the split string.
|
||||
///
|
||||
/// If the iterator is empty, returns `None`.
|
||||
|
|
|
@ -19,6 +19,7 @@ use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
|
|||
use crate::ascii;
|
||||
use crate::char::{self, EscapeDebugExtArgs};
|
||||
use crate::mem;
|
||||
use crate::ops::Range;
|
||||
use crate::slice::{self, SliceIndex};
|
||||
|
||||
pub mod pattern;
|
||||
|
@ -1137,7 +1138,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
|
||||
pub fn contains<P: Pattern>(&self, pat: P) -> bool {
|
||||
pat.is_contained_in(self)
|
||||
}
|
||||
|
||||
|
@ -1174,7 +1175,7 @@ impl str {
|
|||
/// assert!(bananas.starts_with(&['a', 'b', 'c', 'd']));
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
|
||||
pub fn starts_with<P: Pattern>(&self, pat: P) -> bool {
|
||||
pat.is_prefix_of(self)
|
||||
}
|
||||
|
||||
|
@ -1198,9 +1199,9 @@ impl str {
|
|||
/// assert!(!bananas.ends_with("nana"));
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn ends_with<'a, P>(&'a self, pat: P) -> bool
|
||||
pub fn ends_with<P: Pattern>(&self, pat: P) -> bool
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
pat.is_suffix_of(self)
|
||||
}
|
||||
|
@ -1249,7 +1250,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
|
||||
pub fn find<P: Pattern>(&self, pat: P) -> Option<usize> {
|
||||
pat.into_searcher(self).next_match().map(|(i, _)| i)
|
||||
}
|
||||
|
||||
|
@ -1295,9 +1296,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn rfind<'a, P>(&'a self, pat: P) -> Option<usize>
|
||||
pub fn rfind<P: Pattern>(&self, pat: P) -> Option<usize>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
pat.into_searcher(self).next_match_back().map(|(i, _)| i)
|
||||
}
|
||||
|
@ -1417,7 +1418,7 @@ impl str {
|
|||
/// [`split_whitespace`]: str::split_whitespace
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
|
||||
pub fn split<P: Pattern>(&self, pat: P) -> Split<'_, P> {
|
||||
Split(SplitInternal {
|
||||
start: 0,
|
||||
end: self.len(),
|
||||
|
@ -1457,7 +1458,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "split_inclusive", since = "1.51.0")]
|
||||
#[inline]
|
||||
pub fn split_inclusive<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitInclusive<'a, P> {
|
||||
pub fn split_inclusive<P: Pattern>(&self, pat: P) -> SplitInclusive<'_, P> {
|
||||
SplitInclusive(SplitInternal {
|
||||
start: 0,
|
||||
end: self.len(),
|
||||
|
@ -1512,9 +1513,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn rsplit<'a, P>(&'a self, pat: P) -> RSplit<'a, P>
|
||||
pub fn rsplit<P: Pattern>(&self, pat: P) -> RSplit<'_, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
RSplit(self.split(pat).0)
|
||||
}
|
||||
|
@ -1561,7 +1562,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
|
||||
pub fn split_terminator<P: Pattern>(&self, pat: P) -> SplitTerminator<'_, P> {
|
||||
SplitTerminator(SplitInternal { allow_trailing_empty: false, ..self.split(pat).0 })
|
||||
}
|
||||
|
||||
|
@ -1607,9 +1608,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn rsplit_terminator<'a, P>(&'a self, pat: P) -> RSplitTerminator<'a, P>
|
||||
pub fn rsplit_terminator<P: Pattern>(&self, pat: P) -> RSplitTerminator<'_, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
RSplitTerminator(self.split_terminator(pat).0)
|
||||
}
|
||||
|
@ -1662,7 +1663,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
|
||||
pub fn splitn<P: Pattern>(&self, n: usize, pat: P) -> SplitN<'_, P> {
|
||||
SplitN(SplitNInternal { iter: self.split(pat).0, count: n })
|
||||
}
|
||||
|
||||
|
@ -1711,9 +1712,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn rsplitn<'a, P>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
|
||||
pub fn rsplitn<P: Pattern>(&self, n: usize, pat: P) -> RSplitN<'_, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
RSplitN(self.splitn(n, pat).0)
|
||||
}
|
||||
|
@ -1731,7 +1732,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "str_split_once", since = "1.52.0")]
|
||||
#[inline]
|
||||
pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> {
|
||||
pub fn split_once<P: Pattern>(&self, delimiter: P) -> Option<(&'_ str, &'_ str)> {
|
||||
let (start, end) = delimiter.into_searcher(self).next_match()?;
|
||||
// SAFETY: `Searcher` is known to return valid indices.
|
||||
unsafe { Some((self.get_unchecked(..start), self.get_unchecked(end..))) }
|
||||
|
@ -1749,9 +1750,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "str_split_once", since = "1.52.0")]
|
||||
#[inline]
|
||||
pub fn rsplit_once<'a, P>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)>
|
||||
pub fn rsplit_once<P: Pattern>(&self, delimiter: P) -> Option<(&'_ str, &'_ str)>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
let (start, end) = delimiter.into_searcher(self).next_match_back()?;
|
||||
// SAFETY: `Searcher` is known to return valid indices.
|
||||
|
@ -1789,7 +1790,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "str_matches", since = "1.2.0")]
|
||||
#[inline]
|
||||
pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
|
||||
pub fn matches<P: Pattern>(&self, pat: P) -> Matches<'_, P> {
|
||||
Matches(MatchesInternal(pat.into_searcher(self)))
|
||||
}
|
||||
|
||||
|
@ -1823,9 +1824,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "str_matches", since = "1.2.0")]
|
||||
#[inline]
|
||||
pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P>
|
||||
pub fn rmatches<P: Pattern>(&self, pat: P) -> RMatches<'_, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
RMatches(self.matches(pat).0)
|
||||
}
|
||||
|
@ -1867,7 +1868,7 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "str_match_indices", since = "1.5.0")]
|
||||
#[inline]
|
||||
pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
|
||||
pub fn match_indices<P: Pattern>(&self, pat: P) -> MatchIndices<'_, P> {
|
||||
MatchIndices(MatchIndicesInternal(pat.into_searcher(self)))
|
||||
}
|
||||
|
||||
|
@ -1907,9 +1908,9 @@ impl str {
|
|||
/// ```
|
||||
#[stable(feature = "str_match_indices", since = "1.5.0")]
|
||||
#[inline]
|
||||
pub fn rmatch_indices<'a, P>(&'a self, pat: P) -> RMatchIndices<'a, P>
|
||||
pub fn rmatch_indices<P: Pattern>(&self, pat: P) -> RMatchIndices<'_, P>
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
RMatchIndices(self.match_indices(pat).0)
|
||||
}
|
||||
|
@ -2122,9 +2123,9 @@ impl str {
|
|||
#[must_use = "this returns the trimmed string as a new slice, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn trim_matches<'a, P>(&'a self, pat: P) -> &'a str
|
||||
pub fn trim_matches<P: Pattern>(&self, pat: P) -> &str
|
||||
where
|
||||
P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: DoubleEndedSearcher<'a>,
|
||||
{
|
||||
let mut i = 0;
|
||||
let mut j = 0;
|
||||
|
@ -2169,7 +2170,7 @@ impl str {
|
|||
#[must_use = "this returns the trimmed string as a new slice, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "trim_direction", since = "1.30.0")]
|
||||
pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
pub fn trim_start_matches<P: Pattern>(&self, pat: P) -> &str {
|
||||
let mut i = self.len();
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((a, _)) = matcher.next_reject() {
|
||||
|
@ -2202,7 +2203,7 @@ impl str {
|
|||
#[must_use = "this returns the remaining substring as a new slice, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "str_strip", since = "1.45.0")]
|
||||
pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> {
|
||||
pub fn strip_prefix<P: Pattern>(&self, prefix: P) -> Option<&str> {
|
||||
prefix.strip_prefix_of(self)
|
||||
}
|
||||
|
||||
|
@ -2229,10 +2230,9 @@ impl str {
|
|||
#[must_use = "this returns the remaining substring as a new slice, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "str_strip", since = "1.45.0")]
|
||||
pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str>
|
||||
pub fn strip_suffix<P: Pattern>(&self, suffix: P) -> Option<&str>
|
||||
where
|
||||
P: Pattern<'a>,
|
||||
<P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
suffix.strip_suffix_of(self)
|
||||
}
|
||||
|
@ -2273,9 +2273,9 @@ impl str {
|
|||
#[must_use = "this returns the trimmed string as a new slice, \
|
||||
without modifying the original"]
|
||||
#[stable(feature = "trim_direction", since = "1.30.0")]
|
||||
pub fn trim_end_matches<'a, P>(&'a self, pat: P) -> &'a str
|
||||
pub fn trim_end_matches<P: Pattern>(&self, pat: P) -> &str
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
let mut j = 0;
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
|
@ -2317,7 +2317,7 @@ impl str {
|
|||
note = "superseded by `trim_start_matches`",
|
||||
suggestion = "trim_start_matches"
|
||||
)]
|
||||
pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
pub fn trim_left_matches<P: Pattern>(&self, pat: P) -> &str {
|
||||
self.trim_start_matches(pat)
|
||||
}
|
||||
|
||||
|
@ -2360,9 +2360,9 @@ impl str {
|
|||
note = "superseded by `trim_end_matches`",
|
||||
suggestion = "trim_end_matches"
|
||||
)]
|
||||
pub fn trim_right_matches<'a, P>(&'a self, pat: P) -> &'a str
|
||||
pub fn trim_right_matches<P: Pattern>(&self, pat: P) -> &str
|
||||
where
|
||||
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
|
||||
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
self.trim_end_matches(pat)
|
||||
}
|
||||
|
@ -2721,6 +2721,39 @@ impl str {
|
|||
pub fn escape_unicode(&self) -> EscapeUnicode<'_> {
|
||||
EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) }
|
||||
}
|
||||
|
||||
/// Returns the range that a substring points to.
|
||||
///
|
||||
/// Returns `None` if `substr` does not point within `self`.
|
||||
///
|
||||
/// Unlike [`str::find`], **this does not search through the string**.
|
||||
/// Instead, it uses pointer arithmetic to find where in the string
|
||||
/// `substr` is derived from.
|
||||
///
|
||||
/// This is useful for extending [`str::split`] and similar methods.
|
||||
///
|
||||
/// Note that this method may return false positives (typically either
|
||||
/// `Some(0..0)` or `Some(self.len()..self.len())`) if `substr` is a
|
||||
/// zero-length `str` that points at the beginning or end of another,
|
||||
/// independent, `str`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// #![feature(substr_range)]
|
||||
///
|
||||
/// let data = "a, b, b, a";
|
||||
/// let mut iter = data.split(", ").map(|s| data.substr_range(s).unwrap());
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(0..1));
|
||||
/// assert_eq!(iter.next(), Some(3..4));
|
||||
/// assert_eq!(iter.next(), Some(6..7));
|
||||
/// assert_eq!(iter.next(), Some(9..10));
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[unstable(feature = "substr_range", issue = "126769")]
|
||||
pub fn substr_range(&self, substr: &str) -> Option<Range<usize>> {
|
||||
self.as_bytes().subslice_range(substr.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
@ -48,8 +48,8 @@ use crate::slice::memchr;
|
|||
|
||||
/// A string pattern.
|
||||
///
|
||||
/// A `Pattern<'a>` expresses that the implementing type
|
||||
/// can be used as a string pattern for searching in a [`&'a str`][str].
|
||||
/// A `Pattern` expresses that the implementing type
|
||||
/// can be used as a string pattern for searching in a [`&str`][str].
|
||||
///
|
||||
/// For example, both `'a'` and `"aa"` are patterns that
|
||||
/// would match at index `1` in the string `"baaaab"`.
|
||||
|
@ -97,38 +97,38 @@ use crate::slice::memchr;
|
|||
/// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4));
|
||||
/// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None);
|
||||
/// ```
|
||||
pub trait Pattern<'a>: Sized {
|
||||
pub trait Pattern: Sized {
|
||||
/// Associated searcher for this pattern
|
||||
type Searcher: Searcher<'a>;
|
||||
type Searcher<'a>: Searcher<'a>;
|
||||
|
||||
/// Constructs the associated searcher from
|
||||
/// `self` and the `haystack` to search in.
|
||||
fn into_searcher(self, haystack: &'a str) -> Self::Searcher;
|
||||
fn into_searcher(self, haystack: &str) -> Self::Searcher<'_>;
|
||||
|
||||
/// Checks whether the pattern matches anywhere in the haystack
|
||||
#[inline]
|
||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||
fn is_contained_in(self, haystack: &str) -> bool {
|
||||
self.into_searcher(haystack).next_match().is_some()
|
||||
}
|
||||
|
||||
/// Checks whether the pattern matches at the front of the haystack
|
||||
#[inline]
|
||||
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
||||
fn is_prefix_of(self, haystack: &str) -> bool {
|
||||
matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
|
||||
}
|
||||
|
||||
/// Checks whether the pattern matches at the back of the haystack
|
||||
#[inline]
|
||||
fn is_suffix_of(self, haystack: &'a str) -> bool
|
||||
fn is_suffix_of<'a>(self, haystack: &'a str) -> bool
|
||||
where
|
||||
Self::Searcher: ReverseSearcher<'a>,
|
||||
Self::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
|
||||
}
|
||||
|
||||
/// Removes the pattern from the front of haystack, if it matches.
|
||||
#[inline]
|
||||
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
|
||||
fn strip_prefix_of(self, haystack: &str) -> Option<&str> {
|
||||
if let SearchStep::Match(start, len) = self.into_searcher(haystack).next() {
|
||||
debug_assert_eq!(
|
||||
start, 0,
|
||||
|
@ -144,9 +144,9 @@ pub trait Pattern<'a>: Sized {
|
|||
|
||||
/// Removes the pattern from the back of haystack, if it matches.
|
||||
#[inline]
|
||||
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
|
||||
fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str>
|
||||
where
|
||||
Self::Searcher: ReverseSearcher<'a>,
|
||||
Self::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
if let SearchStep::Match(start, end) = self.into_searcher(haystack).next_back() {
|
||||
debug_assert_eq!(
|
||||
|
@ -349,7 +349,7 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
|
|||
// Impl for char
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Associated type for `<char as Pattern<'a>>::Searcher`.
|
||||
/// Associated type for `<char as Pattern>::Searcher<'a>`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CharSearcher<'a> {
|
||||
haystack: &'a str,
|
||||
|
@ -543,11 +543,11 @@ impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
|
|||
/// ```
|
||||
/// assert_eq!("Hello world".find('o'), Some(4));
|
||||
/// ```
|
||||
impl<'a> Pattern<'a> for char {
|
||||
type Searcher = CharSearcher<'a>;
|
||||
impl Pattern for char {
|
||||
type Searcher<'a> = CharSearcher<'a>;
|
||||
|
||||
#[inline]
|
||||
fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
|
||||
fn into_searcher(self, haystack: &str) -> Self::Searcher<'_> {
|
||||
let mut utf8_encoded = [0; 4];
|
||||
let utf8_size = self
|
||||
.encode_utf8(&mut utf8_encoded)
|
||||
|
@ -566,7 +566,7 @@ impl<'a> Pattern<'a> for char {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||
fn is_contained_in(self, haystack: &str) -> bool {
|
||||
if (self as u32) < 128 {
|
||||
haystack.as_bytes().contains(&(self as u8))
|
||||
} else {
|
||||
|
@ -576,27 +576,27 @@ impl<'a> Pattern<'a> for char {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
||||
fn is_prefix_of(self, haystack: &str) -> bool {
|
||||
self.encode_utf8(&mut [0u8; 4]).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.encode_utf8(&mut [0u8; 4]).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: ReverseSearcher<'a>,
|
||||
Self::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
self.encode_utf8(&mut [0u8; 4]).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<&'a str>
|
||||
where
|
||||
Self::Searcher: ReverseSearcher<'a>,
|
||||
Self::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
self.encode_utf8(&mut [0u8; 4]).strip_suffix_of(haystack)
|
||||
}
|
||||
|
@ -651,11 +651,11 @@ struct MultiCharEqSearcher<'a, C: MultiCharEq> {
|
|||
char_indices: super::CharIndices<'a>,
|
||||
}
|
||||
|
||||
impl<'a, C: MultiCharEq> Pattern<'a> for MultiCharEqPattern<C> {
|
||||
type Searcher = MultiCharEqSearcher<'a, C>;
|
||||
impl<C: MultiCharEq> Pattern for MultiCharEqPattern<C> {
|
||||
type Searcher<'a> = MultiCharEqSearcher<'a, C>;
|
||||
|
||||
#[inline]
|
||||
fn into_searcher(self, haystack: &'a str) -> MultiCharEqSearcher<'a, C> {
|
||||
fn into_searcher(self, haystack: &str) -> MultiCharEqSearcher<'_, C> {
|
||||
MultiCharEqSearcher { haystack, char_eq: self.0, char_indices: haystack.char_indices() }
|
||||
}
|
||||
}
|
||||
|
@ -710,41 +710,41 @@ impl<'a, C: MultiCharEq> DoubleEndedSearcher<'a> for MultiCharEqSearcher<'a, C>
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! pattern_methods {
|
||||
($t:ty, $pmap:expr, $smap:expr) => {
|
||||
type Searcher = $t;
|
||||
($a:lifetime, $t:ty, $pmap:expr, $smap:expr) => {
|
||||
type Searcher<$a> = $t;
|
||||
|
||||
#[inline]
|
||||
fn into_searcher(self, haystack: &'a str) -> $t {
|
||||
fn into_searcher<$a>(self, haystack: &$a str) -> $t {
|
||||
($smap)(($pmap)(self).into_searcher(haystack))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||
fn is_contained_in<$a>(self, haystack: &$a str) -> bool {
|
||||
($pmap)(self).is_contained_in(haystack)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
||||
fn is_prefix_of<$a>(self, haystack: &$a str) -> bool {
|
||||
($pmap)(self).is_prefix_of(haystack)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
|
||||
fn strip_prefix_of<$a>(self, haystack: &$a str) -> Option<&$a str> {
|
||||
($pmap)(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
|
||||
$t: ReverseSearcher<'a>,
|
||||
$t: ReverseSearcher<$a>,
|
||||
{
|
||||
($pmap)(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<&$a str>
|
||||
where
|
||||
$t: ReverseSearcher<'a>,
|
||||
$t: ReverseSearcher<$a>,
|
||||
{
|
||||
($pmap)(self).strip_suffix_of(haystack)
|
||||
}
|
||||
|
@ -786,16 +786,16 @@ macro_rules! searcher_methods {
|
|||
};
|
||||
}
|
||||
|
||||
/// Associated type for `<[char; N] as Pattern<'a>>::Searcher`.
|
||||
/// Associated type for `<[char; N] as Pattern>::Searcher<'a>`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CharArraySearcher<'a, const N: usize>(
|
||||
<MultiCharEqPattern<[char; N]> as Pattern<'a>>::Searcher,
|
||||
<MultiCharEqPattern<[char; N]> as Pattern>::Searcher<'a>,
|
||||
);
|
||||
|
||||
/// Associated type for `<&[char; N] as Pattern<'a>>::Searcher`.
|
||||
/// Associated type for `<&[char; N] as Pattern>::Searcher<'a>`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CharArrayRefSearcher<'a, 'b, const N: usize>(
|
||||
<MultiCharEqPattern<&'b [char; N]> as Pattern<'a>>::Searcher,
|
||||
<MultiCharEqPattern<&'b [char; N]> as Pattern>::Searcher<'a>,
|
||||
);
|
||||
|
||||
/// Searches for chars that are equal to any of the [`char`]s in the array.
|
||||
|
@ -806,8 +806,8 @@ pub struct CharArrayRefSearcher<'a, 'b, const N: usize>(
|
|||
/// assert_eq!("Hello world".find(['o', 'l']), Some(2));
|
||||
/// assert_eq!("Hello world".find(['h', 'w']), Some(6));
|
||||
/// ```
|
||||
impl<'a, const N: usize> Pattern<'a> for [char; N] {
|
||||
pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
|
||||
impl<const N: usize> Pattern for [char; N] {
|
||||
pattern_methods!('a, CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
|
||||
}
|
||||
|
||||
unsafe impl<'a, const N: usize> Searcher<'a> for CharArraySearcher<'a, N> {
|
||||
|
@ -828,8 +828,8 @@ impl<'a, const N: usize> DoubleEndedSearcher<'a> for CharArraySearcher<'a, N> {}
|
|||
/// assert_eq!("Hello world".find(&['o', 'l']), Some(2));
|
||||
/// assert_eq!("Hello world".find(&['h', 'w']), Some(6));
|
||||
/// ```
|
||||
impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] {
|
||||
pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
|
||||
impl<'b, const N: usize> Pattern for &'b [char; N] {
|
||||
pattern_methods!('a, CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
|
||||
}
|
||||
|
||||
unsafe impl<'a, 'b, const N: usize> Searcher<'a> for CharArrayRefSearcher<'a, 'b, N> {
|
||||
|
@ -848,9 +848,9 @@ impl<'a, 'b, const N: usize> DoubleEndedSearcher<'a> for CharArrayRefSearcher<'a
|
|||
|
||||
// Todo: Change / Remove due to ambiguity in meaning.
|
||||
|
||||
/// Associated type for `<&[char] as Pattern<'a>>::Searcher`.
|
||||
/// Associated type for `<&[char] as Pattern>::Searcher<'a>`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CharSliceSearcher<'a, 'b>(<MultiCharEqPattern<&'b [char]> as Pattern<'a>>::Searcher);
|
||||
pub struct CharSliceSearcher<'a, 'b>(<MultiCharEqPattern<&'b [char]> as Pattern>::Searcher<'a>);
|
||||
|
||||
unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> {
|
||||
searcher_methods!(forward);
|
||||
|
@ -870,17 +870,17 @@ impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
|
|||
/// assert_eq!("Hello world".find(&['l', 'l'] as &[_]), Some(2));
|
||||
/// assert_eq!("Hello world".find(&['l', 'l'][..]), Some(2));
|
||||
/// ```
|
||||
impl<'a, 'b> Pattern<'a> for &'b [char] {
|
||||
pattern_methods!(CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher);
|
||||
impl<'b> Pattern for &'b [char] {
|
||||
pattern_methods!('a, CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Impl for F: FnMut(char) -> bool
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Associated type for `<F as Pattern<'a>>::Searcher`.
|
||||
/// Associated type for `<F as Pattern>::Searcher<'a>`.
|
||||
#[derive(Clone)]
|
||||
pub struct CharPredicateSearcher<'a, F>(<MultiCharEqPattern<F> as Pattern<'a>>::Searcher)
|
||||
pub struct CharPredicateSearcher<'a, F>(<MultiCharEqPattern<F> as Pattern>::Searcher<'a>)
|
||||
where
|
||||
F: FnMut(char) -> bool;
|
||||
|
||||
|
@ -919,11 +919,11 @@ impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> where F: Fn
|
|||
/// assert_eq!("Hello world".find(char::is_uppercase), Some(0));
|
||||
/// assert_eq!("Hello world".find(|c| "aeiou".contains(c)), Some(1));
|
||||
/// ```
|
||||
impl<'a, F> Pattern<'a> for F
|
||||
impl<F> Pattern for F
|
||||
where
|
||||
F: FnMut(char) -> bool,
|
||||
{
|
||||
pattern_methods!(CharPredicateSearcher<'a, F>, MultiCharEqPattern, CharPredicateSearcher);
|
||||
pattern_methods!('a, CharPredicateSearcher<'a, F>, MultiCharEqPattern, CharPredicateSearcher);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -931,8 +931,8 @@ where
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Delegates to the `&str` impl.
|
||||
impl<'a, 'b, 'c> Pattern<'a> for &'c &'b str {
|
||||
pattern_methods!(StrSearcher<'a, 'b>, |&s| s, |s| s);
|
||||
impl<'b, 'c> Pattern for &'c &'b str {
|
||||
pattern_methods!('a, StrSearcher<'a, 'b>, |&s| s, |s| s);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -949,23 +949,23 @@ impl<'a, 'b, 'c> Pattern<'a> for &'c &'b str {
|
|||
/// ```
|
||||
/// assert_eq!("Hello world".find("world"), Some(6));
|
||||
/// ```
|
||||
impl<'a, 'b> Pattern<'a> for &'b str {
|
||||
type Searcher = StrSearcher<'a, 'b>;
|
||||
impl<'b> Pattern for &'b str {
|
||||
type Searcher<'a> = StrSearcher<'a, 'b>;
|
||||
|
||||
#[inline]
|
||||
fn into_searcher(self, haystack: &'a str) -> StrSearcher<'a, 'b> {
|
||||
fn into_searcher(self, haystack: &str) -> StrSearcher<'_, 'b> {
|
||||
StrSearcher::new(haystack, self)
|
||||
}
|
||||
|
||||
/// Checks whether the pattern matches at the front of the haystack.
|
||||
#[inline]
|
||||
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
||||
fn is_prefix_of(self, haystack: &str) -> bool {
|
||||
haystack.as_bytes().starts_with(self.as_bytes())
|
||||
}
|
||||
|
||||
/// Checks whether the pattern matches anywhere in the haystack
|
||||
#[inline]
|
||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||
fn is_contained_in(self, haystack: &str) -> bool {
|
||||
if self.len() == 0 {
|
||||
return true;
|
||||
}
|
||||
|
@ -991,7 +991,7 @@ impl<'a, 'b> Pattern<'a> for &'b str {
|
|||
|
||||
/// Removes the pattern from the front of haystack, if it matches.
|
||||
#[inline]
|
||||
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
|
||||
fn strip_prefix_of(self, haystack: &str) -> Option<&str> {
|
||||
if self.is_prefix_of(haystack) {
|
||||
// SAFETY: prefix was just verified to exist.
|
||||
unsafe { Some(haystack.get_unchecked(self.as_bytes().len()..)) }
|
||||
|
@ -1002,13 +1002,19 @@ impl<'a, 'b> Pattern<'a> for &'b str {
|
|||
|
||||
/// Checks whether the pattern matches at the back of the 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>: ReverseSearcher<'a>,
|
||||
{
|
||||
haystack.as_bytes().ends_with(self.as_bytes())
|
||||
}
|
||||
|
||||
/// Removes the pattern from the back of haystack, if it matches.
|
||||
#[inline]
|
||||
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
|
||||
fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str>
|
||||
where
|
||||
Self::Searcher<'a>: ReverseSearcher<'a>,
|
||||
{
|
||||
if self.is_suffix_of(haystack) {
|
||||
let i = haystack.len() - self.as_bytes().len();
|
||||
// SAFETY: suffix was just verified to exist.
|
||||
|
@ -1024,7 +1030,7 @@ impl<'a, 'b> Pattern<'a> for &'b str {
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Associated type for `<&str as Pattern<'a>>::Searcher`.
|
||||
/// Associated type for `<&str as Pattern>::Searcher<'a>`.
|
||||
pub struct StrSearcher<'a, 'b> {
|
||||
haystack: &'a str,
|
||||
needle: &'b str,
|
||||
|
|
|
@ -463,15 +463,15 @@ impl FileAttr {
|
|||
#[cfg(target_os = "aix")]
|
||||
impl FileAttr {
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(self.stat.st_mtime.tv_sec as i64, self.stat.st_mtime.tv_nsec as i64))
|
||||
SystemTime::new(self.stat.st_mtime.tv_sec as i64, self.stat.st_mtime.tv_nsec as i64)
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(self.stat.st_atime.tv_sec as i64, self.stat.st_atime.tv_nsec as i64))
|
||||
SystemTime::new(self.stat.st_atime.tv_sec as i64, self.stat.st_atime.tv_nsec as i64)
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(self.stat.st_ctime.tv_sec as i64, self.stat.st_ctime.tv_nsec as i64))
|
||||
SystemTime::new(self.stat.st_ctime.tv_sec as i64, self.stat.st_ctime.tv_nsec as i64)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
use crate::ffi::CStr;
|
||||
use crate::mem;
|
||||
use crate::os::raw::{c_uint, c_ulong, c_ushort, c_void};
|
||||
use crate::os::windows::io::{AsRawHandle, BorrowedHandle};
|
||||
use crate::ptr;
|
||||
|
||||
pub(super) mod windows_targets;
|
||||
|
@ -114,89 +113,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
|
|||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "system" fn WriteFileEx(
|
||||
hFile: BorrowedHandle<'_>,
|
||||
lpBuffer: *mut ::core::ffi::c_void,
|
||||
nNumberOfBytesToWrite: u32,
|
||||
lpOverlapped: *mut OVERLAPPED,
|
||||
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
||||
) -> BOOL {
|
||||
windows_sys::WriteFileEx(
|
||||
hFile.as_raw_handle(),
|
||||
lpBuffer.cast::<u8>(),
|
||||
nNumberOfBytesToWrite,
|
||||
lpOverlapped,
|
||||
lpCompletionRoutine,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe extern "system" fn ReadFileEx(
|
||||
hFile: BorrowedHandle<'_>,
|
||||
lpBuffer: *mut ::core::ffi::c_void,
|
||||
nNumberOfBytesToRead: u32,
|
||||
lpOverlapped: *mut OVERLAPPED,
|
||||
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
||||
) -> BOOL {
|
||||
windows_sys::ReadFileEx(
|
||||
hFile.as_raw_handle(),
|
||||
lpBuffer.cast::<u8>(),
|
||||
nNumberOfBytesToRead,
|
||||
lpOverlapped,
|
||||
lpCompletionRoutine,
|
||||
)
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(target_vendor = "uwp"))] {
|
||||
pub unsafe fn NtReadFile(
|
||||
filehandle: BorrowedHandle<'_>,
|
||||
event: HANDLE,
|
||||
apcroutine: PIO_APC_ROUTINE,
|
||||
apccontext: *mut c_void,
|
||||
iostatusblock: &mut IO_STATUS_BLOCK,
|
||||
buffer: *mut crate::mem::MaybeUninit<u8>,
|
||||
length: u32,
|
||||
byteoffset: Option<&i64>,
|
||||
key: Option<&u32>,
|
||||
) -> NTSTATUS {
|
||||
windows_sys::NtReadFile(
|
||||
filehandle.as_raw_handle(),
|
||||
event,
|
||||
apcroutine,
|
||||
apccontext,
|
||||
iostatusblock,
|
||||
buffer.cast::<c_void>(),
|
||||
length,
|
||||
byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
|
||||
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
|
||||
)
|
||||
}
|
||||
pub unsafe fn NtWriteFile(
|
||||
filehandle: BorrowedHandle<'_>,
|
||||
event: HANDLE,
|
||||
apcroutine: PIO_APC_ROUTINE,
|
||||
apccontext: *mut c_void,
|
||||
iostatusblock: &mut IO_STATUS_BLOCK,
|
||||
buffer: *const u8,
|
||||
length: u32,
|
||||
byteoffset: Option<&i64>,
|
||||
key: Option<&u32>,
|
||||
) -> NTSTATUS {
|
||||
windows_sys::NtWriteFile(
|
||||
filehandle.as_raw_handle(),
|
||||
event,
|
||||
apcroutine,
|
||||
apccontext,
|
||||
iostatusblock,
|
||||
buffer.cast::<c_void>(),
|
||||
length,
|
||||
byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
|
||||
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use raw-dylib to import ProcessPrng as we can't rely on there being an import library.
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(target_vendor = "win7"))] {
|
||||
|
@ -331,29 +247,29 @@ compat_fn_with_fallback! {
|
|||
}
|
||||
#[cfg(target_vendor = "uwp")]
|
||||
pub fn NtReadFile(
|
||||
filehandle: BorrowedHandle<'_>,
|
||||
filehandle: HANDLE,
|
||||
event: HANDLE,
|
||||
apcroutine: PIO_APC_ROUTINE,
|
||||
apccontext: *mut c_void,
|
||||
iostatusblock: &mut IO_STATUS_BLOCK,
|
||||
buffer: *mut crate::mem::MaybeUninit<u8>,
|
||||
apccontext: *const core::ffi::c_void,
|
||||
iostatusblock: *mut IO_STATUS_BLOCK,
|
||||
buffer: *mut core::ffi::c_void,
|
||||
length: u32,
|
||||
byteoffset: Option<&i64>,
|
||||
key: Option<&u32>
|
||||
byteoffset: *const i64,
|
||||
key: *const u32
|
||||
) -> NTSTATUS {
|
||||
STATUS_NOT_IMPLEMENTED
|
||||
}
|
||||
#[cfg(target_vendor = "uwp")]
|
||||
pub fn NtWriteFile(
|
||||
filehandle: BorrowedHandle<'_>,
|
||||
filehandle: HANDLE,
|
||||
event: HANDLE,
|
||||
apcroutine: PIO_APC_ROUTINE,
|
||||
apccontext: *mut c_void,
|
||||
iostatusblock: &mut IO_STATUS_BLOCK,
|
||||
buffer: *const u8,
|
||||
apccontext: *const core::ffi::c_void,
|
||||
iostatusblock: *mut IO_STATUS_BLOCK,
|
||||
buffer: *const core::ffi::c_void,
|
||||
length: u32,
|
||||
byteoffset: Option<&i64>,
|
||||
key: Option<&u32>
|
||||
byteoffset: *const i64,
|
||||
key: *const u32
|
||||
) -> NTSTATUS {
|
||||
STATUS_NOT_IMPLEMENTED
|
||||
}
|
||||
|
|
|
@ -250,15 +250,15 @@ impl Handle {
|
|||
// the provided `len`.
|
||||
let status = unsafe {
|
||||
c::NtReadFile(
|
||||
self.as_handle(),
|
||||
self.as_raw_handle(),
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
ptr::null_mut(),
|
||||
&mut io_status,
|
||||
buf,
|
||||
buf.cast::<core::ffi::c_void>(),
|
||||
len,
|
||||
offset.map(|n| n as _).as_ref(),
|
||||
None,
|
||||
offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
|
||||
ptr::null(),
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -300,15 +300,15 @@ impl Handle {
|
|||
let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
|
||||
let status = unsafe {
|
||||
c::NtWriteFile(
|
||||
self.as_handle(),
|
||||
self.as_raw_handle(),
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
ptr::null_mut(),
|
||||
&mut io_status,
|
||||
buf.as_ptr(),
|
||||
buf.as_ptr().cast::<core::ffi::c_void>(),
|
||||
len,
|
||||
offset.map(|n| n as _).as_ref(),
|
||||
None,
|
||||
offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
|
||||
ptr::null(),
|
||||
)
|
||||
};
|
||||
let status = if status == c::STATUS_PENDING {
|
||||
|
|
|
@ -238,15 +238,6 @@ fn random_number() -> usize {
|
|||
}
|
||||
}
|
||||
|
||||
// Abstracts over `ReadFileEx` and `WriteFileEx`
|
||||
type AlertableIoFn = unsafe extern "system" fn(
|
||||
BorrowedHandle<'_>,
|
||||
*mut core::ffi::c_void,
|
||||
u32,
|
||||
*mut c::OVERLAPPED,
|
||||
c::LPOVERLAPPED_COMPLETION_ROUTINE,
|
||||
) -> c::BOOL;
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&self.inner
|
||||
|
@ -262,7 +253,10 @@ impl AnonPipe {
|
|||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let result = unsafe {
|
||||
let len = crate::cmp::min(buf.len(), u32::MAX as usize) as u32;
|
||||
self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len)
|
||||
let ptr = buf.as_mut_ptr();
|
||||
self.alertable_io_internal(|overlapped, callback| {
|
||||
c::ReadFileEx(self.inner.as_raw_handle(), ptr, len, overlapped, callback)
|
||||
})
|
||||
};
|
||||
|
||||
match result {
|
||||
|
@ -278,7 +272,10 @@ impl AnonPipe {
|
|||
pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
let result = unsafe {
|
||||
let len = crate::cmp::min(buf.capacity(), u32::MAX as usize) as u32;
|
||||
self.alertable_io_internal(c::ReadFileEx, buf.as_mut().as_mut_ptr() as _, len)
|
||||
let ptr = buf.as_mut().as_mut_ptr().cast::<u8>();
|
||||
self.alertable_io_internal(|overlapped, callback| {
|
||||
c::ReadFileEx(self.inner.as_raw_handle(), ptr, len, overlapped, callback)
|
||||
})
|
||||
};
|
||||
|
||||
match result {
|
||||
|
@ -313,7 +310,9 @@ impl AnonPipe {
|
|||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
let len = crate::cmp::min(buf.len(), u32::MAX as usize) as u32;
|
||||
self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len)
|
||||
self.alertable_io_internal(|overlapped, callback| {
|
||||
c::WriteFileEx(self.inner.as_raw_handle(), buf.as_ptr(), len, overlapped, callback)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,12 +340,9 @@ impl AnonPipe {
|
|||
/// [`ReadFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfileex
|
||||
/// [`WriteFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefileex
|
||||
/// [Asynchronous Procedure Call]: https://docs.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls
|
||||
#[allow(unsafe_op_in_unsafe_fn)]
|
||||
unsafe fn alertable_io_internal(
|
||||
&self,
|
||||
io: AlertableIoFn,
|
||||
buf: *mut core::ffi::c_void,
|
||||
len: u32,
|
||||
io: impl FnOnce(&mut c::OVERLAPPED, c::LPOVERLAPPED_COMPLETION_ROUTINE) -> c::BOOL,
|
||||
) -> io::Result<usize> {
|
||||
// Use "alertable I/O" to synchronize the pipe I/O.
|
||||
// This has four steps.
|
||||
|
@ -384,20 +380,25 @@ impl AnonPipe {
|
|||
lpOverlapped: *mut c::OVERLAPPED,
|
||||
) {
|
||||
// Set `async_result` using a pointer smuggled through `hEvent`.
|
||||
let result =
|
||||
AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred };
|
||||
*(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
|
||||
// SAFETY:
|
||||
// At this point, the OVERLAPPED struct will have been written to by the OS,
|
||||
// except for our `hEvent` field which we set to a valid AsyncResult pointer (see below)
|
||||
unsafe {
|
||||
let result =
|
||||
AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred };
|
||||
*(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP 1: Start the I/O operation.
|
||||
let mut overlapped: c::OVERLAPPED = crate::mem::zeroed();
|
||||
let mut overlapped: c::OVERLAPPED = unsafe { crate::mem::zeroed() };
|
||||
// `hEvent` is unused by `ReadFileEx` and `WriteFileEx`.
|
||||
// Therefore the documentation suggests using it to smuggle a pointer to the callback.
|
||||
overlapped.hEvent = core::ptr::addr_of_mut!(async_result) as *mut _;
|
||||
|
||||
// Asynchronous read of the pipe.
|
||||
// If successful, `callback` will be called once it completes.
|
||||
let result = io(self.inner.as_handle(), buf, len, &mut overlapped, Some(callback));
|
||||
let result = io(&mut overlapped, Some(callback));
|
||||
if result == c::FALSE {
|
||||
// We can return here because the call failed.
|
||||
// After this we must not return until the I/O completes.
|
||||
|
@ -408,7 +409,7 @@ impl AnonPipe {
|
|||
let result = loop {
|
||||
// STEP 2: Enter an alertable state.
|
||||
// The second parameter of `SleepEx` is used to make this sleep alertable.
|
||||
c::SleepEx(c::INFINITE, c::TRUE);
|
||||
unsafe { c::SleepEx(c::INFINITE, c::TRUE) };
|
||||
if let Some(result) = async_result {
|
||||
break result;
|
||||
}
|
||||
|
|
|
@ -1700,6 +1700,7 @@ impl Step for Assemble {
|
|||
|
||||
// If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
|
||||
if builder.download_rustc() {
|
||||
builder.ensure(Std::new(target_compiler, target_compiler.host));
|
||||
let sysroot =
|
||||
builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
|
||||
// Ensure that `libLLVM.so` ends up in the newly created target directory,
|
||||
|
|
|
@ -25,7 +25,7 @@ use build_helper::git::{get_git_modified_files, get_git_untracked_files};
|
|||
use core::panic;
|
||||
use getopts::Options;
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::OsString;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs;
|
||||
use std::io::{self, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -225,6 +225,29 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
// Avoid spawning an external command when we know tidy won't be used.
|
||||
false
|
||||
};
|
||||
let filters = if mode == Mode::RunMake {
|
||||
matches
|
||||
.free
|
||||
.iter()
|
||||
.map(|f| {
|
||||
let path = Path::new(f);
|
||||
let mut iter = path.iter().skip(1);
|
||||
|
||||
// We skip the test folder and check if the user passed `rmake.rs` or `Makefile`.
|
||||
if iter
|
||||
.next()
|
||||
.is_some_and(|s| s == OsStr::new("rmake.rs") || s == OsStr::new("Makefile"))
|
||||
&& iter.next().is_none()
|
||||
{
|
||||
path.parent().unwrap().to_str().unwrap().to_string()
|
||||
} else {
|
||||
f.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
matches.free.clone()
|
||||
};
|
||||
Config {
|
||||
bless: matches.opt_present("bless"),
|
||||
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
|
||||
|
@ -249,7 +272,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
debugger: None,
|
||||
run_ignored,
|
||||
with_debug_assertions,
|
||||
filters: matches.free.clone(),
|
||||
filters,
|
||||
skip: matches.opt_strs("skip"),
|
||||
filter_exact: matches.opt_present("exact"),
|
||||
force_pass_mode: matches.opt_str("pass").map(|mode| {
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
fn foo(x: &str) -> bool {
|
||||
x.starts_with(&("hi".to_string() + " you"))
|
||||
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `String: Pattern` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn foo2(x: &str) -> bool {
|
||||
x.starts_with(&"hi".to_string())
|
||||
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `String: Pattern` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
fn foo(x: &str) -> bool {
|
||||
x.starts_with("hi".to_string() + " you")
|
||||
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `String: Pattern` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn foo2(x: &str) -> bool {
|
||||
x.starts_with("hi".to_string())
|
||||
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
|
||||
//~^ ERROR the trait bound `String: Pattern` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
|
||||
error[E0277]: the trait bound `String: Pattern` is not satisfied
|
||||
--> $DIR/issue-104961.rs:4:19
|
||||
|
|
||||
LL | x.starts_with("hi".to_string() + " you")
|
||||
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
|
||||
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Pattern` is not implemented for `String`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `String` to implement `Pattern<'_>`
|
||||
= note: required for `String` to implement `Pattern`
|
||||
note: required by a bound in `core::str::<impl str>::starts_with`
|
||||
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
@ -14,15 +14,15 @@ help: consider borrowing here
|
|||
LL | x.starts_with(&("hi".to_string() + " you"))
|
||||
| ++ +
|
||||
|
||||
error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
|
||||
error[E0277]: the trait bound `String: Pattern` is not satisfied
|
||||
--> $DIR/issue-104961.rs:9:19
|
||||
|
|
||||
LL | x.starts_with("hi".to_string())
|
||||
| ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
|
||||
| ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern` is not implemented for `String`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `String` to implement `Pattern<'_>`
|
||||
= note: required for `String` to implement `Pattern`
|
||||
note: required by a bound in `core::str::<impl str>::starts_with`
|
||||
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
|
||||
error[E0277]: the trait bound `String: Pattern` is not satisfied
|
||||
--> $DIR/issue-62843.rs:4:32
|
||||
|
|
||||
LL | println!("{:?}", line.find(pattern));
|
||||
| ---- ^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
|
||||
| ---- ^^^^^^^ the trait `Pattern` is not implemented for `String`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `String` to implement `Pattern<'_>`
|
||||
= note: required for `String` to implement `Pattern`
|
||||
note: required by a bound in `core::str::<impl str>::find`
|
||||
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
|
||||
help: consider borrowing here
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
fn strip_lf(s: &str) -> &str {
|
||||
s.strip_suffix(b'\n').unwrap_or(s)
|
||||
//~^ ERROR expected a `FnMut(char)` closure, found `u8`
|
||||
//~| NOTE expected an `FnMut(char)` closure, found `u8`
|
||||
//~| HELP the trait `FnMut(char)` is not implemented for `u8`
|
||||
//~| HELP the following other types implement trait `Pattern<'a>`:
|
||||
//~| NOTE required for `u8` to implement `Pattern<'_>`
|
||||
|
||||
//~^ ERROR the trait bound `u8: Pattern` is not satisfied
|
||||
//~| NOTE required by a bound introduced by this call
|
||||
//~| NOTE the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern`
|
||||
//~| HELP the following other types implement trait `Pattern`:
|
||||
//~| NOTE required for `u8` to implement `Pattern`
|
||||
//~| NOTE required by a bound in `core::str::<impl str>::strip_suffix`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
error[E0277]: expected a `FnMut(char)` closure, found `u8`
|
||||
--> $DIR/assoc-fn-bound-root-obligation.rs:2:7
|
||||
error[E0277]: the trait bound `u8: Pattern` is not satisfied
|
||||
--> $DIR/assoc-fn-bound-root-obligation.rs:2:20
|
||||
|
|
||||
LL | s.strip_suffix(b'\n').unwrap_or(s)
|
||||
| ^^^^^^^^^^^^ expected an `FnMut(char)` closure, found `u8`
|
||||
| ------------ ^^^^^ the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern<'_>`
|
||||
= help: the following other types implement trait `Pattern<'a>`:
|
||||
= help: the following other types implement trait `Pattern`:
|
||||
&'b String
|
||||
&'b [char; N]
|
||||
&'b [char]
|
||||
|
@ -13,7 +14,9 @@ LL | s.strip_suffix(b'\n').unwrap_or(s)
|
|||
&'c &'b str
|
||||
[char; N]
|
||||
char
|
||||
= note: required for `u8` to implement `Pattern<'_>`
|
||||
= note: required for `u8` to implement `Pattern`
|
||||
note: required by a bound in `core::str::<impl str>::strip_suffix`
|
||||
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize {
|
|||
string
|
||||
.chars()
|
||||
.filter(|c| "aeiou".contains(*c))
|
||||
//~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied
|
||||
//~^ ERROR the trait bound `&char: Pattern` is not satisfied
|
||||
.count()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize {
|
|||
string
|
||||
.chars()
|
||||
.filter(|c| "aeiou".contains(c))
|
||||
//~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied
|
||||
//~^ ERROR the trait bound `&char: Pattern` is not satisfied
|
||||
.count()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
|
||||
error[E0277]: the trait bound `&char: Pattern` is not satisfied
|
||||
--> $DIR/root-obligation.rs:6:38
|
||||
|
|
||||
LL | .filter(|c| "aeiou".contains(c))
|
||||
| -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern<'_>`
|
||||
| -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `&char` to implement `FnOnce(char)`
|
||||
= note: required for `&char` to implement `Pattern<'_>`
|
||||
= note: required for `&char` to implement `Pattern`
|
||||
note: required by a bound in `core::str::<impl str>::contains`
|
||||
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
|
||||
help: consider dereferencing here
|
||||
|
|
Loading…
Add table
Reference in a new issue