Skip to content

Commit 26607c3

Browse files
authored
Unrolled build for rust-lang#137777
Rollup merge of rust-lang#137777 - thaliaarchi:os_string-push-str, r=joboet Specialize `OsString::push` and `OsString as From` for UTF-8 When concatenating two WTF-8 strings, surrogate pairs at the boundaries need to be joined. However, since UTF-8 strings cannot contain surrogate halves, this check can be skipped when one string is UTF-8. Specialize `OsString::push` to use a more efficient concatenation in this case. The WTF-8 version of `OsString` tracks whether it is known to be valid UTF-8 with its `is_known_utf8` field. Specialize `From<AsRef<OsStr>>` so this can be set for UTF-8 string types. Unfortunately, a specialization for `T: AsRef<str>` conflicts with `T: AsRef<OsStr>`, so stamp out string types with a macro. r? ``@ChrisDenton``
2 parents 91a0e16 + 83407b8 commit 26607c3

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

library/std/src/ffi/os_str.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,30 @@ impl OsString {
257257
#[inline]
258258
#[rustc_confusables("append", "put")]
259259
pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
260-
self.inner.push_slice(&s.as_ref().inner)
260+
trait SpecPushTo {
261+
fn spec_push_to(&self, buf: &mut OsString);
262+
}
263+
264+
impl<T: AsRef<OsStr>> SpecPushTo for T {
265+
#[inline]
266+
default fn spec_push_to(&self, buf: &mut OsString) {
267+
buf.inner.push_slice(&self.as_ref().inner);
268+
}
269+
}
270+
271+
// Use a more efficient implementation when the string is UTF-8.
272+
macro spec_str($T:ty) {
273+
impl SpecPushTo for $T {
274+
#[inline]
275+
fn spec_push_to(&self, buf: &mut OsString) {
276+
buf.inner.push_str(self);
277+
}
278+
}
279+
}
280+
spec_str!(str);
281+
spec_str!(String);
282+
283+
s.spec_push_to(self)
261284
}
262285

263286
/// Creates a new `OsString` with at least the given capacity.
@@ -587,7 +610,30 @@ impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
587610
/// Copies any value implementing <code>[AsRef]&lt;[OsStr]&gt;</code>
588611
/// into a newly allocated [`OsString`].
589612
fn from(s: &T) -> OsString {
590-
s.as_ref().to_os_string()
613+
trait SpecToOsString {
614+
fn spec_to_os_string(&self) -> OsString;
615+
}
616+
617+
impl<T: AsRef<OsStr>> SpecToOsString for T {
618+
#[inline]
619+
default fn spec_to_os_string(&self) -> OsString {
620+
self.as_ref().to_os_string()
621+
}
622+
}
623+
624+
// Preserve the known-UTF-8 property for strings.
625+
macro spec_str($T:ty) {
626+
impl SpecToOsString for $T {
627+
#[inline]
628+
fn spec_to_os_string(&self) -> OsString {
629+
OsString::from(String::from(self))
630+
}
631+
}
632+
}
633+
spec_str!(str);
634+
spec_str!(String);
635+
636+
s.spec_to_os_string()
591637
}
592638
}
593639

library/std/src/sys/os_str/bytes.rs

+5
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ impl Buf {
139139
self.inner.extend_from_slice(&s.inner)
140140
}
141141

142+
#[inline]
143+
pub fn push_str(&mut self, s: &str) {
144+
self.inner.extend_from_slice(s.as_bytes());
145+
}
146+
142147
#[inline]
143148
pub fn reserve(&mut self, additional: usize) {
144149
self.inner.reserve(additional)

library/std/src/sys/os_str/wtf8.rs

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ impl Buf {
116116
self.inner.push_wtf8(&s.inner)
117117
}
118118

119+
#[inline]
120+
pub fn push_str(&mut self, s: &str) {
121+
self.inner.push_str(s);
122+
}
123+
119124
#[inline]
120125
pub fn reserve(&mut self, additional: usize) {
121126
self.inner.reserve(additional)

0 commit comments

Comments
 (0)