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

Add new literal_string_with_formatting_arg lint #13410

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

GuillaumeGomez
Copy link
Member

Fixes #10195.

changelog: Add new literal_string_with_formatting_arg lint

@rustbot
Copy link
Collaborator

rustbot commented Sep 17, 2024

r? @Jarcho

rustbot has assigned @Jarcho.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Sep 17, 2024
@GuillaumeGomez GuillaumeGomez changed the title Literal string with formatting arg Add new literal_string_with_formatting_arg lint Sep 17, 2024
@GuillaumeGomez GuillaumeGomez changed the title Add new literal_string_with_formatting_arg lint Add new literal_string_with_formatting_arg lint Sep 17, 2024
})
.collect::<Vec<_>>();
if spans.len() == 1 {
span_lint(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could emit a suggestion for both cases by wrapping the literal into &format!(). Not sure if it's a good idea since it could be wrong in a lot of cases so for now I didn't do it.

@matthiaskrgr
Copy link
Member

Would like to see a test for malformed fmt attemps such as {y:?}} or "{y:?} y:?}" to make sure we don't lint there by accident


// Should not lint!
format!("{y:?}");
println!("{y:?}");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("{y:?}");
println!("{y:?}");
let code = "fn main {\n\
}";

@emilk
Copy link

emilk commented Sep 18, 2024

I did a little bit of testing, and it seems to work like it should! ❤️ A few more unit tests would be nice though

@GuillaumeGomez
Copy link
Member Author

I just found a much better idea: using the rustc format parser directly. :3

@GuillaumeGomez GuillaumeGomez force-pushed the literal_string_with_formatting_arg branch 3 times, most recently from d720088 to 2356854 Compare September 18, 2024 21:59
@GuillaumeGomez
Copy link
Member Author

So it now uses the rustc format parser, making things much better overall: no more regex, less false positive, simpler code.

I also added all suggested test cases and some more.

@y21
Copy link
Member

y21 commented Sep 18, 2024

What does the lint do for the empty JSON object {} which is also a valid formatting specifier? Would probably be a good to have as a negative test too.

cx,
LITERAL_STRING_WITH_FORMATTING_ARG,
spans,
"this is a formatting argument but it is not part of a formatting macro",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a less strong wording would be good, e.g. "this looks like a formatting argument…" ? Just in case of false positives

@GuillaumeGomez GuillaumeGomez force-pushed the literal_string_with_formatting_arg branch from 2356854 to c662397 Compare September 19, 2024 10:11
@GuillaumeGomez
Copy link
Member Author

What does the lint do for the empty JSON object {} which is also a valid formatting specifier? Would probably be a good to have as a negative test too.

It lints (as expected 😄). There was a test for that with other characters but created a new one with just {} just in case.

Maybe a less strong wording would be good, e.g. "this looks like a formatting argument…" ? Just in case of false positives

Good idea! I changed the wording.

@GuillaumeGomez GuillaumeGomez force-pushed the literal_string_with_formatting_arg branch 2 times, most recently from 6a3f320 to c027b98 Compare September 19, 2024 13:55
@y21
Copy link
Member

y21 commented Sep 19, 2024

It lints (as expected 😄).

Realistically speaking, I feel like {} would run into more false positives than true positives if we decide to lint that.

{foo}/{foo:?} etc. all make sense since they can work with format! alone (that is, format!("{foo}") works), but you can't make that argument for just {}. Not only is it missing the format macro, but it's also missing a formatting argument.

If someone writes let foo = "{}";, it seems fairly unlikely to me that they actually meant to use a formatting macro there, because there is nothing to format.

@GuillaumeGomez
Copy link
Member Author

Good point. Should I only lint against non-empty {} like {y}/{:?}/{y:?} and eventually we can add an option to look for everything?

@GuillaumeGomez GuillaumeGomez force-pushed the literal_string_with_formatting_arg branch 3 times, most recently from 2d7c05d to 852f1e3 Compare September 19, 2024 16:05
@GuillaumeGomez
Copy link
Member Author

I removed the check for {} for the time being.

@bors
Copy link
Collaborator

bors commented Sep 22, 2024

☔ The latest upstream changes (presumably #13322) made this pull request unmergeable. Please resolve the merge conflicts.

@GuillaumeGomez GuillaumeGomez force-pushed the literal_string_with_formatting_arg branch from 852f1e3 to d9c9ad4 Compare September 22, 2024 15:10
@GuillaumeGomez
Copy link
Member Author

Fixed merge conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties
Projects
None yet
Development

Successfully merging this pull request may close these issues.

warn on strings that look like inline format strings but aren't
7 participants