Skip to content

Commit

Permalink
Optimize simple literals for Display::fmt
Browse files Browse the repository at this point in the history
Compiler is unable to generate as efficient code for `write!(f, "text")` as it does for `f.write_str("text")`.  This PR checks if the `#[error("text")]` uses a simple string literal without the `{` and `}` characters, and without arguments, and uses `write_str` if so.
  • Loading branch information
nyurik committed Feb 9, 2024
1 parent 0717de3 commit cb80183
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
20 changes: 18 additions & 2 deletions impl/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,24 @@ impl ToTokens for Display<'_> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let fmt = &self.fmt;
let args = &self.args;
tokens.extend(quote! {
::core::write!(__formatter, #fmt #args)

// Currently compiler is unable to generate as efficient code for
// write!(f, "text") as it does for f.write_str("text"),
// so handle it here when the literal string has no braces/no args.
let mut use_write_str = self.args.is_empty();
if use_write_str {
let fmt = self.fmt.value();
use_write_str = !fmt.contains('{') && !fmt.contains('}');
}

tokens.extend(if use_write_str {
quote! {
__formatter.write_str(#fmt)
}
} else {
quote! {
::core::write!(__formatter, #fmt #args)
}
});
}
}
Expand Down
56 changes: 56 additions & 0 deletions tests/test_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,59 @@ fn test_keyword() {

assert("error: 1", Error);
}

#[test]
fn test_str_special_chars() {
#[derive(Error, Debug)]
pub enum Error {
#[error("text")]
Text,
#[error("braces {{}}")]
Braces,
#[error("braces2 \x7B\x7B\x7D\x7D")]
Braces2,
#[error("braces3 \u{7B}\u{7B}\u{7D}\u{7D}")]
Braces3,
#[error(
"new_\
line"
)]
NewLine,
#[error("escape24 \u{78}")]
Escape24,
}

assert("text", Error::Text);
assert("braces {}", Error::Braces);
assert("braces2 {}", Error::Braces2);
assert("braces3 {}", Error::Braces3);
assert("new_line", Error::NewLine);
assert("escape24 x", Error::Escape24);
}

#[test]
fn test_raw_str() {
#[derive(Error, Debug)]
pub enum Error {
#[error(r#"raw_text"#)]
Text,
#[error(r#"raw_braces {{}}"#)]
Braces,
#[error(r#"raw_braces2 \x7B\x7D"#)]
Braces2,
#[error(
r#"raw_new_\
line"#
)]
NewLine,
}

assert(r#"raw_text"#, Error::Text);
assert(r#"raw_braces {}"#, Error::Braces);
assert(r#"raw_braces2 \x7B\x7D"#, Error::Braces2);
assert(
r#"raw_new_\
line"#,
Error::NewLine,
);
}

0 comments on commit cb80183

Please sign in to comment.