Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special-case format!("{}", string_like) for increased performance #52804

Open
killercup opened this issue Jul 28, 2018 · 5 comments
Open

Special-case format!("{}", string_like) for increased performance #52804

killercup opened this issue Jul 28, 2018 · 5 comments
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@killercup
Copy link
Member

Changes like #52767 and existence of the useless_format clippy lint show that people end up writing format!("{}", a_string) way more often than they should (i.e., >0 times).

Since format is a proc macro/builtin in the compiler, and since this specific case should not have any side effects other than producing a String, I want to propose adding this special case:

When expanding a call of the format macro (and before using format_args!), check if the formatting string is literally "{}", and, if the only other parameter x is either of type &str, String, or Cow<str>, expand the macro to ToString::to_string(x).

This is quite a conservative and concrete refinement. It could easily be adjusted to support more string-like types.

And additional special case to consider is format!("foo") (with only a literal formatting string). It should expand to String::from("foo").

@ExpHP
Copy link
Contributor

ExpHP commented Jul 28, 2018

if the only other parameter x is either of type &str, String, or Cow<str>, expand the macro to ToString::to_string(x).

Is this really possible? Normally I wouldn't think so as I'd expect that even built-in macros still expand before there is any notion of types. (But it's very possible that you know more than I do!)

I think that maybe instead it could simply expand to use another trait which is specialized for these types, but which cannot be specialized by types outside the standard library. (e.g. using #[allow_internal_unstable])

@killercup
Copy link
Member Author

Normally I wouldn't think so as I'd expect that even built-in macros still expand before there is any notion of types.

It's a compiler built-in, if you want to do magic, you probably can.

OTOH, it may be possible to always expand the single-argument case to ToString::to_string(x), but I haven't verified that.

@ljedrz
Copy link
Contributor

ljedrz commented Jul 28, 2018

if the only other parameter x is either of type &str, String, or Cow<str>, expand the macro to ToString::to_string(x)

I think this could just apply to any type, as ToString is applicable to anything that can be an argument of format!().

@eddyb
Copy link
Member

eddyb commented Jul 28, 2018

It's a compiler built-in, if you want to do magic, you probably can.

But you shouldn't. We should enact some official policy about this: if you can't represent in source form, it's a really bad idea. The main/only offender I know about is asm!.

I like the ToString idea since the blanket impl ensures compatibility with format!("{}").

In fact... since format! isn't built-in anyway (it's a macro_rules macro), we should be able to add this case to its definition: ("{}", $($args:tt)*) => (ToString::to_string($($args)*)).

Sadly I don't see a way to pass the same arguments to both format_args! (for built-in validation) and to to_string - even if in dead code, if there's anything nested in the argument expressions, you could end up duplicating entire declarations/definitions where you previously weren't.

One way around it could be calling format_args! then extracting the pointer to the first (and only) argument and somehow getting its type to call ToString but that seems sketchy at best.

Oh and you don't really want ToString::to_string, but instead some wrapper that requires fmt::Display instead, to avoid relaxing the bounds or changing the error messages.

@estebank estebank added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jan 11, 2019
@RReverser
Copy link
Contributor

to both format_args! (for built-in validation)

Why would you need that? If it's just a single argument with "{}", then enforcing Display should be enough of a restriction even without calling out to format_args!.

@hdhoang hdhoang added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Nov 21, 2019
@jyn514 jyn514 added the I-slow Issue: Problems and improvements with respect to performance of generated code. label Sep 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants