Skip to content

Commit 83b4908

Browse files
authored
Unrolled build for rust-lang#138650
Rollup merge of rust-lang#138650 - thaliaarchi:io-write-fmt-known, r=ibraheemdev Optimize `io::Write::write_fmt` for constant strings When the formatting args to `fmt::Write::write_fmt` are a statically known string, it simplifies to only calling `write_str` without a runtime branch. Do the same in `io::Write::write_fmt` with `write_all`. Also, match the convention of `fmt::Write` for the name of `args`.
2 parents 5d85a71 + a0c3dd4 commit 83b4908

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

library/core/src/fmt/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -710,9 +710,10 @@ impl<'a> Arguments<'a> {
710710
}
711711

712712
/// Same as [`Arguments::as_str`], but will only return `Some(s)` if it can be determined at compile time.
713+
#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
713714
#[must_use]
714715
#[inline]
715-
fn as_statically_known_str(&self) -> Option<&'static str> {
716+
pub fn as_statically_known_str(&self) -> Option<&'static str> {
716717
let s = self.as_str();
717718
if core::intrinsics::is_val_statically_known(s.is_some()) { s } else { None }
718719
}

library/std/src/io/mod.rs

+46-35
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,47 @@ pub(crate) fn default_read_buf_exact<R: Read + ?Sized>(
612612
Ok(())
613613
}
614614

615+
pub(crate) fn default_write_fmt<W: Write + ?Sized>(
616+
this: &mut W,
617+
args: fmt::Arguments<'_>,
618+
) -> Result<()> {
619+
// Create a shim which translates a `Write` to a `fmt::Write` and saves off
620+
// I/O errors, instead of discarding them.
621+
struct Adapter<'a, T: ?Sized + 'a> {
622+
inner: &'a mut T,
623+
error: Result<()>,
624+
}
625+
626+
impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
627+
fn write_str(&mut self, s: &str) -> fmt::Result {
628+
match self.inner.write_all(s.as_bytes()) {
629+
Ok(()) => Ok(()),
630+
Err(e) => {
631+
self.error = Err(e);
632+
Err(fmt::Error)
633+
}
634+
}
635+
}
636+
}
637+
638+
let mut output = Adapter { inner: this, error: Ok(()) };
639+
match fmt::write(&mut output, args) {
640+
Ok(()) => Ok(()),
641+
Err(..) => {
642+
// Check whether the error came from the underlying `Write`.
643+
if output.error.is_err() {
644+
output.error
645+
} else {
646+
// This shouldn't happen: the underlying stream did not error,
647+
// but somehow the formatter still errored?
648+
panic!(
649+
"a formatting trait implementation returned an error when the underlying stream did not"
650+
);
651+
}
652+
}
653+
}
654+
}
655+
615656
/// The `Read` trait allows for reading bytes from a source.
616657
///
617658
/// Implementors of the `Read` trait are called 'readers'.
@@ -1866,41 +1907,11 @@ pub trait Write {
18661907
/// }
18671908
/// ```
18681909
#[stable(feature = "rust1", since = "1.0.0")]
1869-
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
1870-
// Create a shim which translates a Write to a fmt::Write and saves
1871-
// off I/O errors. instead of discarding them
1872-
struct Adapter<'a, T: ?Sized + 'a> {
1873-
inner: &'a mut T,
1874-
error: Result<()>,
1875-
}
1876-
1877-
impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
1878-
fn write_str(&mut self, s: &str) -> fmt::Result {
1879-
match self.inner.write_all(s.as_bytes()) {
1880-
Ok(()) => Ok(()),
1881-
Err(e) => {
1882-
self.error = Err(e);
1883-
Err(fmt::Error)
1884-
}
1885-
}
1886-
}
1887-
}
1888-
1889-
let mut output = Adapter { inner: self, error: Ok(()) };
1890-
match fmt::write(&mut output, fmt) {
1891-
Ok(()) => Ok(()),
1892-
Err(..) => {
1893-
// check if the error came from the underlying `Write` or not
1894-
if output.error.is_err() {
1895-
output.error
1896-
} else {
1897-
// This shouldn't happen: the underlying stream did not error, but somehow
1898-
// the formatter still errored?
1899-
panic!(
1900-
"a formatting trait implementation returned an error when the underlying stream did not"
1901-
);
1902-
}
1903-
}
1910+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
1911+
if let Some(s) = args.as_statically_known_str() {
1912+
self.write_all(s.as_bytes())
1913+
} else {
1914+
default_write_fmt(self, args)
19041915
}
19051916
}
19061917

0 commit comments

Comments
 (0)