Skip to content

Add new useless_concat lint#13829

Merged
samueltardieu merged 4 commits into
rust-lang:masterfrom
GuillaumeGomez:useless-concat
May 19, 2025
Merged

Add new useless_concat lint#13829
samueltardieu merged 4 commits into
rust-lang:masterfrom
GuillaumeGomez:useless-concat

Conversation

@GuillaumeGomez

Copy link
Copy Markdown
Member

Fixes #13793.

Interestingly enough, to actually check that the macro call has at least two arguments, we need to use the rust lexer after getting the original source code snippet.

changelog: Add new useless_concat lint

@rustbot

rustbot commented Dec 14, 2024

Copy link
Copy Markdown
Collaborator

r? @dswij

rustbot has assigned @dswij.
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 Dec 14, 2024
@GuillaumeGomez GuillaumeGomez force-pushed the useless-concat branch 2 times, most recently from 4918abc to b92d91b Compare December 15, 2024 20:51
@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Finally was able to only trigger the lint when appropriate.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

r? clippy

@rustbot rustbot assigned y21 and unassigned dswij Dec 25, 2024
Comment thread clippy_lints/src/useless_concat.rs Outdated
Comment thread clippy_lints/src/useless_concat.rs Outdated
Comment thread clippy_lints/src/useless_concat.rs Outdated
Comment thread clippy_lints/src/useless_concat.rs Outdated
@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Fixed dogfood. :)

github-merge-queue Bot pushed a commit that referenced this pull request Dec 30, 2024
I discovered that there were paths declared in `clippy_utils::paths` in
#13829 so moving a few
remaining hardcoded ones in one place.

changelog: Move more def paths into `clippy_utils::paths`

r? @y21
@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Fixed merge conflicts. If there is nothing else, should we start the FCP?

@y21 y21 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have a few more comments, but I'm going to open the FCP already because they shouldn't require major changes

Comment thread tests/ui/useless_concat.rs
Comment thread clippy_lints/src/useless_concat.rs Outdated
let literal = match literal {
Some(lit) => {
// Literals can also be number, so we need to check this case too.
if lit.starts_with('"') {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This also needs to handle r"" strings and character literals

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You cannot have '', no?

Comment on lines +64 to +67
// `builtin` macros don't seem to be found in `def_path_res`...
if path == ["core", "macros", "builtin", "concat"] {
return true;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm guessing this probably happens because it's a macro_rules! macro and gets resolved at core::concat by def_path_res. Anyway, usually we put #[expect(clippy::invalid_paths)] on the const in paths.rs instead of hardcoding it in the source here though. Can you do that instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

👍

@y21

y21 commented Feb 12, 2025

Copy link
Copy Markdown
Member

@y21 y21 added S-final-comment-period Status: final comment period it will be merged unless new objections are raised (~1 week) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Feb 12, 2025
@y21 y21 added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-final-comment-period Status: final comment period it will be merged unless new objections are raised (~1 week) labels Feb 22, 2025
@rustbot

This comment has been minimized.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Sorry for the (way too long) delay. Finally applied suggestions. Thanks a lot for them!

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

And fixed CI failure. :)

@samueltardieu samueltardieu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That won't work properly with suffixed numeric literals: concat!(1f32) should be replaced by "1" as the builtin macro ignores the suffix, not by "1f32". However, the whole part before the suffix must be kept: concat!(1.000f32) must expand into "1.000".

Also, concat!('c') should be replaced by "c", not "'c'".

It also looks like concat!(true) and concat!(false) are not handled while they could.

Reference in the compiler

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Thanks! Updated and added tests for each case.

@samueltardieu

Copy link
Copy Markdown
Member

You'll have to rebase when #14784 is merged.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Rebased!

@samueltardieu samueltardieu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will fail in at least those two situations:

  • concat!('"') will suggest """ (escaping is missing)
  • concat!(1_f32) will suggest 1_ (underscore should be removed)

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Good catch, thanks! Handled these cases as well.

@samueltardieu samueltardieu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yet another round of non-conforming substitution:

  • concat!(1__f32) suggests "1_" instead of the expected "1" (yes, you can use as many underscores as you like as part of the input)
  • concat!(0xf_f32) suggests "0xf" instead of "65530"
  • concat!(1_2) suggests "1_2" instead of "12"
  • concat!(1___2.00__100___f32) suggests "1___2.00__100__" instead of "12.00100"
  • As we're at it, concat!('\'') could suggest "'" instead of "'" (no need for escaping anymore)

Isn't there a way to invoke the compiler macro programmatically on the token stream once you've determined that there is only one argument? That would cover all those cases, and maybe even more, and simplify the code a lot.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

That would be much better indeed... Let's ask today at the conference if someone has an idea. =D

@samueltardieu

samueltardieu commented May 13, 2025

Copy link
Copy Markdown
Member

That would be much better indeed... Let's ask today at the conference if someone has an idea. =D

Now that I think about it… isn't the result of the expansion right under our noses in the HIR, even being the trigger for this lint? Checking the arguments, then issuing the string with proper escaping should be enough. WDYT? No need for replicating the macro call, it has been done by the compiler already.

@GuillaumeGomez GuillaumeGomez force-pushed the useless-concat branch 2 times, most recently from 16049de to 3a4bfb4 Compare May 14, 2025 16:50

@samueltardieu samueltardieu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Other that the version and the reformatting, fine with me! You should also fix dogfood for the unlined format arg.

Comment thread clippy_lints/src/useless_concat.rs Outdated
@samueltardieu

Copy link
Copy Markdown
Member

@rustbot label S-blocked

I'd like to check something before it gets merged, it looks like I can trigger an ICE when I merge this with my snippet diagnostics patch, I'll remove the block ASAP.

@rustbot rustbot added the S-blocked Status: marked as blocked ❌ on something else such as an RFC or other implementation work label May 19, 2025
@samueltardieu

Copy link
Copy Markdown
Member

There is indeed a problem with obtaining the snippet for the declare_tool_lint!() macro source, but this PR handles this properly. I'll investigate the other problem separately. Thanks!

I'll merge it since I approved the FCP a long time ago, and since did many reviews of this code back and forth.

@rustbot review
r? @samueltardieu

@rustbot rustbot assigned samueltardieu and unassigned y21 May 19, 2025
@samueltardieu samueltardieu removed the S-blocked Status: marked as blocked ❌ on something else such as an RFC or other implementation work label May 19, 2025
@samueltardieu samueltardieu added this pull request to the merge queue May 19, 2025
Merged via the queue into rust-lang:master with commit ebc2a68 May 19, 2025
11 checks passed
@GuillaumeGomez GuillaumeGomez deleted the useless-concat branch May 19, 2025 15:28
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.

Add useless_concat

5 participants