Skip to content

gopls/modernize: "for i = range n {}" fix is wrong if there are later uses of i #71952

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

Closed
Tracked by #71847
adonovan opened this issue Feb 25, 2025 · 3 comments
Closed
Tracked by #71847
Assignees
Labels
BugReport Issues describing a possible bug in the Go implementation. gopls Issues related to the Go language server, gopls.

Comments

@adonovan
Copy link
Member

@dethi reports:

I found one additional bug in the transformation of i := 0; for i = 0; i < n; i++ -> for i = range n if i is used outside of the for loop body. See the minimal reproduction: https://go.dev/play/p/9tlB2oilyJn

In particular, the postcondition of the original loop is that i has the value n, whereas for the range loop it has the value n-1.

@gopherbot gopherbot added the gopls Issues related to the Go language server, gopls. label Feb 25, 2025
@adonovan adonovan self-assigned this Feb 25, 2025
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/652496 mentions this issue: gopls/internal/analysis/modernize: fix bug in rangeint

@gabyhelp gabyhelp added the BugReport Issues describing a possible bug in the Go implementation. label Feb 25, 2025
@golang golang deleted a comment from chingkonglim0815 Feb 28, 2025
@golang golang deleted a comment from chingkonglim0815 Feb 28, 2025
@adonovan adonovan marked this as a duplicate of #73073 Mar 28, 2025
@08d2
Copy link

08d2 commented Apr 3, 2025

Forgive me if this has already been addressed, but I think there may still be an issue here.

package main

func main() {
	x := &X{x: []int{1, 2, 3, 4, 5, 6}}
	for i := 0; i < x.Len(); i++ {
		println(i, x.Len())
		x.Drop()
	}
}

type X struct{ x []int }

func (x *X) Len() int { return len(x.x) }
func (x *X) Drop()    { x.x = x.x[1:] }
$ go run main.go
0 6
1 5
2 4
$ go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix .
--- main.go (old)
+++ main.go (new)
@@ -2,7 +2,7 @@
 

 func main() {
        x := &X{x: []int{1, 2, 3, 4, 5, 6}}
-       for i := 0; i < x.Len(); i++ {
+       for i := range x.Len() {
                println(i, x.Len())
                x.Drop()
        }
$ go run main.go
0 6
1 5
2 4
3 3
4 2
5 1

@adonovan
Copy link
Member Author

adonovan commented Apr 4, 2025

Forgive me if this has already been addressed, but I think there may still be an issue here.

You're right that this is a bug, but it's a different one: #72917. It was fixed at master but has not yet been released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BugReport Issues describing a possible bug in the Go implementation. gopls Issues related to the Go language server, gopls.
Projects
None yet
Development

No branches or pull requests

4 participants