Skip to content
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

cmd/go: vet incorrectly flags loop variable captured by func literal in GOPATH mode #70641

Closed
rittneje opened this issue Dec 2, 2024 · 9 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@rittneje
Copy link
Contributor

rittneje commented Dec 2, 2024

Go version

go version go1.22.9 darwin/amd64

Output of go env in your module/workspace:

n/a

What did you do?

I wrote the follow unit test in GOPATH mode.

package looptest

import "testing"

func TestLoopSemantics(t *testing.T) {
	values := []string{"1", "2"}
	for _, x := range values {
		t.Run(x, func(t *testing.T) {
			t.Parallel()
			t.Log(&x)
		})
	}
}

Then I ran go vet on the package.

What did you see happen?

$ go vet looptest
# looptest
# [looptest]
src/looptest/loop_test.go:10:11: loop variable x captured by func literal

What did you expect to see?

No issues.

In Go 1.22+, the compiler uses the new loop semantics, even in GOPATH mode. This is proven by running the test, which gives output like so. (The exact address is different each time of course, but the important part is that x has a different address in each test case.)

$ go test looptest -v
=== RUN   TestLoopSemantics
=== RUN   TestLoopSemantics/1
=== PAUSE TestLoopSemantics/1
=== RUN   TestLoopSemantics/2
=== PAUSE TestLoopSemantics/2
=== CONT  TestLoopSemantics/1
=== CONT  TestLoopSemantics/2
=== NAME  TestLoopSemantics/1
    loop_test.go:10: 0xc000032350
=== NAME  TestLoopSemantics/2
    loop_test.go:10: 0xc0000323d0
--- PASS: TestLoopSemantics (0.00s)
    --- PASS: TestLoopSemantics/1 (0.00s)
    --- PASS: TestLoopSemantics/2 (0.00s)
PASS
ok      looptest        0.498s

Therefore, go vet should not have applied this check at all.

@mknyszek mknyszek added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Dec 2, 2024
@mknyszek
Copy link
Contributor

mknyszek commented Dec 2, 2024

CC @golang/tools-team

@mknyszek mknyszek added this to the Backlog milestone Dec 2, 2024
@findleyr
Copy link
Member

findleyr commented Dec 2, 2024

CC @adonovan @timothy-king

It sounds like the loopvar analyzer needs to be made aware of this behavior in GOPATH mode.

@matloob can you clarify the semantics here? Should we assume the effective language version in GOPATH mode is the runtime version?

@ianlancetaylor
Copy link
Member

My understanding is that in the absence of a go.mod file the go tool uses Go 1.16 semantics. So the warning is correct when not using modules.

@rsc
Copy link
Contributor

rsc commented Dec 2, 2024

@ianlancetaylor I think we intended to limit GOPATH mode to Go 1.16 at first, but when we decided to keep GOPATH mode around for people who are for one reason or another not using modules, we decided to let the language version float forward, since otherwise you couldn't use generics ever, for example. The behavior of the 'go test' confirms that. Or at least, 'go test' and 'go vet' clearly disagree here.

@ianlancetaylor
Copy link
Member

Ah, thanks.

@matloob
Copy link
Contributor

matloob commented Dec 2, 2024

This was previously reported as #65612 in the command-line-arguments context, but it's the same underlying issue for GOPATH. We fixed this in 1.23 with https://go.dev/cl/593156, explicitly setting the go version to the toolchain version when outside of a module.

We considered backporting the change to Go 1.22 but decided not to because it didn't seem to be a serious problem that prevented a program from working at all (and Go 1.22 already had issues with not passing in -lang to the compiler that we wanted to fix at the same time, and would change the behavior for building programs).

(edit: also good job gaby for surfacing #65612 in the related issues!)

@findleyr
Copy link
Member

findleyr commented Dec 2, 2024

Thanks @matloob, I'd missed (or forgotten) that context.

I think it's reasonable not to backport this fix for 1.22 GOPATH mode. Therefore, closing as a dupe.

@findleyr findleyr closed this as not planned Won't fix, can't repro, duplicate, stale Dec 2, 2024
@zigo101
Copy link

zigo101 commented Dec 3, 2024

Just FRI: The PR https://go.dev/cl/593156 tired to fix #66092 but not totally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

8 participants