Convert redundant_clone to an analysis pass take 2#14599
Convert redundant_clone to an analysis pass take 2#14599Jarcho wants to merge 3 commits intorust-lang:masterfrom
redundant_clone to an analysis pass take 2#14599Conversation
6ec4a89 to
651d371
Compare
Is this ready for review? Seems that it's still a single commit. |
|
I'm splitting it into multiple PRs right now. |
|
Lintcheck changes for 85441ab
This comment will be updated if you push new changes |
|
Ping @oli-obk for a review of the MIR related additions. This does not use rustc's dataflow framework. I would need a few non-trivial changes to make it work so it's going to be easier to keep this separate for now. The main difference are that blocks are pre-processed before the analysis is run. This was needed for A few other differences:
Overall this can result in a little extra boilerplate, but it also comes with a lot of flexibility for how things are done. The projection map works does more or less the same job as The actual lint itself is split into three parts: finding the lint calls, resolving The final part is where all the complexity comes in. There are still a few things to fix with it and I need to document what's happening better. The general idea of how it works is by tracking from each clone call when one of the values might be modified/consumed, and the other value is then read. |
|
☔ The latest upstream changes (possibly 35fb26f) made this pull request unmergeable. Please resolve the merge conflicts. |
supersedes #11364
fixes #10940
fixes #10893
fixes #10870
fixes #10577
fixes #10545
fixes #10517
Don't worry about reviewing this as a whole, I'll be splitting it up into smaller chunks to be reviewed separately.
This comes with a separate dataflow framework than rustc's since many changes would be needed to track values correctly. As an example a mutable borrow of a pair of strings
&mut (String, String)would need to cause both strings to hold different values and the only way to do that in rustc's framework is to track sub-statement positions. The new framework lets us easily do a preprocessing pass at the expense of not trivially supporting cursors.Arena allocation is used heavily throughout. This simplifies some lifetimes both by using only a single lifetime parameter and not having to store as many owning values. It also avoids having a large number of small allocations that need to also be dropped.
No suggestions are give with the lint. This is unfortunate but they are non-trivial to add since removing the clone call is only correct in a subset of cases. Future uses of a projection may need to be changed; the clone call might be changed to a move of a different name (
x.clone()->y) or changed to a borrow.mem::takeis needed in some cases as well.The diagnostic output is currently a stand-in. I will be adding notes about where the values diverge and where the lifetimes of the pair of values end. Basically a message saying one value is modified, but the other isn't used after that point before it's dropped.
changelog:
redundant_clone: Fix false positives where the clone result is stored in a local.changelog:
redundant_clone: Track the use of the clone throughout the function body rather than only checking for immediate consumption.changelog:
redundant_clone: Extended to analyze code in loopschangelog:
redundant_clone: Track values inside fields rather than just tracking top level locals.