Skip to content

cmd/compile: go1.22+ cmd with go.mod 1.21 generates per-loop variable when using line directive #77248

@xieyuschen

Description

@xieyuschen

Go version

go version go1.25.1 darwin/arm64

Output of go env in your module/workspace:

irrelevant

What did you do?

-- go.mod --
module test

go 1.21
-- main.go --
//line main.go:1
package main

import "fmt"

func main() {
	var fns []func()
	for i := 0; i < 3; i++ {
		fns = append(fns, func() { fmt.Println("loop", i) })
	}
	for _, fn := range fns {
		fn()
	}
}
go build .
./test

What did you see happen?

The output is:

loop 0
loop 1
loop 2

What did you expect to see?

It should output loop 3 3 times, as the same behavior as the code without //line main.go:1.

loop 3
loop 3
loop 3

Background

The background is we have some test framework internally like goc which will insert some code lines and directives(like go line directive) before go build and use it in test env.

In test env everything goes well because of this flaw, but when released the service to live without the test coverage framework(without go line directive), the code behaves different and it's not expected.

I believe we can fix it to make the behavior consistent regardless line directive exists or not. Also it will be great if we can backport it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsFixThe path to resolution is known, but the work has not been done.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions