-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
new lint: recursive_format_impl
#8188
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @giraffate (or someone else) soon. Please see the contribution instructions for more information. |
147cb29
to
a0ce3b0
Compare
It seems like the lint doesn't handle nested structures correctly. Here is a false positive:
|
Thanks, the issue is when the nested type is actually the same as the Self type. It seems the best thing to do would be to limit the lint to check whether it is actually the same self reference (not just the types). I'll add it as a test case and try to work around it, thanks! |
a0ce3b0
to
e88ec71
Compare
Fixed by dealing with the single deref of |
I realized with #8253 that this lint should work for any formatting trait (e.g. Debug). The two lints can share a LintPass and a naming convention. For the common part of the name I'm thinking either "fmt" or "format_impl". |
It's a good idea @camsteffen but note the implementations would differ a fair bit since atm this uses: if !arg.is_display() {
continue;
} to filter the format args, unfortunately there isn't an equivalent for debug atm. See the source code here - https://doc.rust-lang.org/nightly/nightly-rustc/src/clippy_utils/higher.rs.html#680-688 Also note that it's okay to use Debug in the Display Impl and vice versa. I'll try to look at adding the above for Debug when I get some time free. |
It would be perfectly fine to leave other traits as a future enhancement. I was just thinking about the lint name since we like to get that right the first time. |
da2cd64
to
6e97fc9
Compare
recursive_display_impl
recursive_format_trait_impl
6e97fc9
to
2f48fcc
Compare
@camsteffen renamed to atm I only check for Debug and Display, but one could add the others (Binary, etc.) pretty easily. It also doesn't check the case where there's a reference cycle i.e. Debug calls Display, and Display calls Debug - we could detect this if we store more information about the other format trait impls as we do the pass, but it doesn't seem like something that is likely to come up in real code anyway. |
I think |
2f48fcc
to
f201863
Compare
recursive_format_trait_impl
recursive_format_impl
@camsteffen You've already reviewed some of this, so can you review it as is? |
Okay. r? @camsteffen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good! Nice tests. I have some comments but it's pretty minor stuff.
It would be nice to have a separate commit to rename the lint. Also we need to add a register_renamed
call and add to the rename.rs
test.
&paths::PRINTLN_MACRO, | ||
&paths::WRITE_MACRO, | ||
&paths::WRITELN_MACRO, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid duplicating these lists. Instead we can have a util like is_format_macro(DefId) -> bool
.
But I'm also thinking it might be a good idea to just use the FormatArgs
LintPass. Up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, but I'll leave making the changes to the FormatArgs lint to another PR so as not to make this huge.
How could we re-use the lint pass, when here we need to check we are inside the impl Display or Debug, etc. ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, but I'll leave making the changes to the FormatArgs lint to another PR so as not to make this huge.
I still would like to avoid duplicating the list in this PR. I small refactor can be done in the other lint.
How could we re-use the lint pass, when here we need to check we are inside the impl Display or Debug, etc. ?
It seems like it should be possible to merge the two lint passes and maintain all cases. But I may be underestimating the difficulty. Again I'll leave it up to you to decide if that ultimately makes sense to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jamesmcm did you decide against merging the lint passes or still looking into it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took a look at it, in theory it should be possible, it's not trivial though since the format_args case also needs to work when the macro isn't nested. It might be best to do in another PR though.
Btw is there any way to share the pass without combining the source files (and error files)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we combine them, I think it would be better to do it in this PR since it would be less churn and reviewing. The tests can still be separated per lint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, looking at it in detail I don't think it is worth combining them. Since handling the nested macro difference means the code isn't really shared between the non format trait impl and format trait impl cases, so it's more just moving it around and I don't think that's worth merging them (since at that point you might as well merge #8253 too for example).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@camsteffen considering this, I think this is mergeable as is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay.
(since at that point you might as well merge #8253 too for example).
I am planning to have that lint merged with this one at least. But if that doesn't change your decision, yes this is ready to merge!
7de473e
to
cfb32b3
Compare
cfb32b3
to
0c615e6
Compare
☔ The latest upstream changes (presumably #8359) made this pull request unmergeable. Please resolve the merge conflicts. |
0c615e6
to
3bbd06d
Compare
☔ The latest upstream changes (presumably #8398) made this pull request unmergeable. Please resolve the merge conflicts. |
3bbd06d
to
d058516
Compare
☔ The latest upstream changes (presumably #8418) made this pull request unmergeable. Please resolve the merge conflicts. |
d058516
to
514b0fc
Compare
☔ The latest upstream changes (presumably #8425) made this pull request unmergeable. Please resolve the merge conflicts. |
The to_string_in_display lint is renamed to recursive_format_impl A check is added for the use of self formatted with Display or Debug inside any format string in the same impl The to_string_in_display check is kept as is - like in the format_in_format_args lint For now only Display and Debug are checked This could also be extended to other Format traits (Binary, etc.)
514b0fc
to
b162b11
Compare
Thanks for your patience, and great first contribution! @bors r+ |
📌 Commit b162b11 has been approved by |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
The to_string_in_display lint is renamed to recursive_format_impl
A check is added for the use of self formatted with Display or Debug inside any format string in the same impl
The to_string_in_display check is kept as is - like in the format_in_format_args lint
This is my first contribution so please check it for better / more idiomatic checks + error messages. Note the format macro paths are shared with the
format_in_format_args
lint - maybe those could be moved to clippy utils too.This relates to issues #2691 and #7830
changelog: Renamed
to_string_in_display
lint to [recursive_format_impl
] with new check for any use of self as Display or Debug inside the same format trait impl.