Skip to content

Commit 0b11b9b

Browse files
committed
Auto merge of rust-lang#148014 - jhpratt:rollup-aglren3, r=jhpratt
Rollup of 3 pull requests Successful merges: - rust-lang#134316 (Add `String::replace_first` and `String::replace_last`) - rust-lang#147713 (Retire ast::TyAliasWhereClauses.) - rust-lang#148011 (Revert constification of `AsRef for Cow` due to inference failure ) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7fff787 + 33f8b1d commit 0b11b9b

File tree

5 files changed

+103
-4
lines changed

5 files changed

+103
-4
lines changed

alloc/src/borrow.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,13 @@ where
441441
}
442442
}
443443

444+
// FIXME(inference): const bounds removed due to inference regressions found by crater;
445+
// see https://github.com/rust-lang/rust/issues/147964
446+
// #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
444447
#[stable(feature = "rust1", since = "1.0.0")]
445-
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
446-
impl<T: ?Sized + ToOwned> const AsRef<T> for Cow<'_, T>
447-
where
448-
T::Owned: [const] Borrow<T>,
448+
impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T>
449+
// where
450+
// T::Owned: [const] Borrow<T>,
449451
{
450452
fn as_ref(&self) -> &T {
451453
self

alloc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
//
8686
// Library features:
8787
// tidy-alphabetical-start
88+
#![cfg_attr(not(no_global_oom_handling), feature(string_replace_in_place))]
8889
#![feature(alloc_layout_extra)]
8990
#![feature(allocator_api)]
9091
#![feature(array_into_iter_constructors)]

alloc/src/string.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,67 @@ impl String {
20902090
unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes());
20912091
}
20922092

2093+
/// Replaces the leftmost occurrence of a pattern with another string, in-place.
2094+
///
2095+
/// This method can be preferred over [`string = string.replacen(..., 1);`][replacen],
2096+
/// as it can use the `String`'s existing capacity to prevent a reallocation if
2097+
/// sufficient space is available.
2098+
///
2099+
/// # Examples
2100+
///
2101+
/// Basic usage:
2102+
///
2103+
/// ```
2104+
/// #![feature(string_replace_in_place)]
2105+
///
2106+
/// let mut s = String::from("Test Results: ❌❌❌");
2107+
///
2108+
/// // Replace the leftmost ❌ with a ✅
2109+
/// s.replace_first('❌', "✅");
2110+
/// assert_eq!(s, "Test Results: ✅❌❌");
2111+
/// ```
2112+
///
2113+
/// [replacen]: ../../std/primitive.str.html#method.replacen
2114+
#[cfg(not(no_global_oom_handling))]
2115+
#[unstable(feature = "string_replace_in_place", issue = "147949")]
2116+
pub fn replace_first<P: Pattern>(&mut self, from: P, to: &str) {
2117+
let range = match self.match_indices(from).next() {
2118+
Some((start, match_str)) => start..start + match_str.len(),
2119+
None => return,
2120+
};
2121+
2122+
self.replace_range(range, to);
2123+
}
2124+
2125+
/// Replaces the rightmost occurrence of a pattern with another string, in-place.
2126+
///
2127+
/// # Examples
2128+
///
2129+
/// Basic usage:
2130+
///
2131+
/// ```
2132+
/// #![feature(string_replace_in_place)]
2133+
///
2134+
/// let mut s = String::from("Test Results: ❌❌❌");
2135+
///
2136+
/// // Replace the rightmost ❌ with a ✅
2137+
/// s.replace_last('❌', "✅");
2138+
/// assert_eq!(s, "Test Results: ❌❌✅");
2139+
/// ```
2140+
#[cfg(not(no_global_oom_handling))]
2141+
#[unstable(feature = "string_replace_in_place", issue = "147949")]
2142+
pub fn replace_last<P: Pattern>(&mut self, from: P, to: &str)
2143+
where
2144+
for<'a> P::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>,
2145+
{
2146+
let range = match self.rmatch_indices(from).next() {
2147+
Some((start, match_str)) => start..start + match_str.len(),
2148+
None => return,
2149+
};
2150+
2151+
self.replace_range(range, to);
2152+
}
2153+
20932154
/// Converts this `String` into a <code>[Box]<[str]></code>.
20942155
///
20952156
/// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`].

alloctests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#![feature(local_waker)]
3737
#![feature(str_as_str)]
3838
#![feature(strict_provenance_lints)]
39+
#![feature(string_replace_in_place)]
3940
#![feature(vec_deque_pop_if)]
4041
#![feature(vec_deque_truncate_front)]
4142
#![feature(unique_rc_arc)]

alloctests/tests/string.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,40 @@ fn test_replace_range_evil_end_bound() {
719719
assert_eq!(Ok(""), str::from_utf8(s.as_bytes()));
720720
}
721721

722+
#[test]
723+
fn test_replace_first() {
724+
let mut s = String::from("~ First ❌ Middle ❌ Last ❌ ~");
725+
s.replace_first("❌", "✅✅");
726+
assert_eq!(s, "~ First ✅✅ Middle ❌ Last ❌ ~");
727+
s.replace_first("🦀", "😳");
728+
assert_eq!(s, "~ First ✅✅ Middle ❌ Last ❌ ~");
729+
730+
let mut s = String::from("❌");
731+
s.replace_first('❌', "✅✅");
732+
assert_eq!(s, "✅✅");
733+
734+
let mut s = String::from("");
735+
s.replace_first('🌌', "❌");
736+
assert_eq!(s, "");
737+
}
738+
739+
#[test]
740+
fn test_replace_last() {
741+
let mut s = String::from("~ First ❌ Middle ❌ Last ❌ ~");
742+
s.replace_last("❌", "✅✅");
743+
assert_eq!(s, "~ First ❌ Middle ❌ Last ✅✅ ~");
744+
s.replace_last("🦀", "😳");
745+
assert_eq!(s, "~ First ❌ Middle ❌ Last ✅✅ ~");
746+
747+
let mut s = String::from("❌");
748+
s.replace_last::<char>('❌', "✅✅");
749+
assert_eq!(s, "✅✅");
750+
751+
let mut s = String::from("");
752+
s.replace_last::<char>('🌌', "❌");
753+
assert_eq!(s, "");
754+
}
755+
722756
#[test]
723757
fn test_extend_ref() {
724758
let mut a = "foo".to_string();

0 commit comments

Comments
 (0)