diff --git a/impl/src/attr.rs b/impl/src/attr.rs index 4beb8c9..743c146 100644 --- a/impl/src/attr.rs +++ b/impl/src/attr.rs @@ -196,8 +196,23 @@ 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 use_write_str = self.args.is_empty() && { + let value = fmt.value(); + !value.contains('{') && !value.contains('}') + }; + + tokens.extend(if use_write_str { + quote! { + __formatter.write_str(#fmt) + } + } else { + quote! { + ::core::write!(__formatter, #fmt #args) + } }); } } diff --git a/tests/test_display.rs b/tests/test_display.rs index 6f60388..faa8968 100644 --- a/tests/test_display.rs +++ b/tests/test_display.rs @@ -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, + ); +}