-
Notifications
You must be signed in to change notification settings - Fork 18k
x/tools/gopls/internal/analysis/modernize: rangeint: transformation unsound when loop body has effects on iterated array #72917
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
Comments
Thanks for reporting. (Curious: was this an encountered bug or an a priori deduction?) Pretty much all our uses of equalSyntax in modernizers have some kind of exploitable edge case like this. Depending on how strict we want to be about aliasing and side effects, we may need to downgrade a number of modernizers if we are to achieve our goal of "first do no harm". Seeing how many subtle bugs we have had so far even among the easy cases, I am starting to wonder whether (continuing the medical analogy) modernizers are mere cosmetic surgery, a procedure of no medical benefit that is not without risk, and whether batch modernization is ever something we should recommend. The benefits may be clearer in cases of interactive modernization, when the user is already critically studying the code (to stretch the metaphor, a form of informed consent), or in the LLM-inference feedback loop, where the user has indicated a penchant for backstreet brain surgery. ;-) |
Found it during actual use. |
Milestoning for next minor. |
This bug caused a bad transformation in the regexp package too: func (m *machine) step(runq, nextq *queue, pos, nextPos int, c rune, nextCond *lazyFlag) {
longest := m.re.longest
for j := 0; j < len(runq.dense); j++ { // <--- don't use for/range: the length changes!
...
runq.dense = runq.dense[:0]
} Fortunately it was caught by tests. |
To be strictly correct--and that is the standard on which we find ourselves converging for modernizers--we would need to disable the transformation to |
for a slice: is assigned once and doesn't escape (All modernizers should probably punt if unsafe is imported.) |
rangeint doesn't touch maps, though I suppose it could replace
Unsafe access would require |
Change https://go.dev/cl/660435 mentions this issue: |
Go version
x/tools/gopls v0.18.1
Output of
go env
in your module/workspace:What did you do?
This program prints 1, 2, 3 4:
What did you see happen?
Gopls wants to modernize the for loop to
for i := range len(s)
.Since the range expression is evaluated only once instead of each time through the loop, the semantics change, and the program prints 1, 2 3.
What did you expect to see?
Behavior unchanged.
The text was updated successfully, but these errors were encountered: