Skip to content

go/types, cmd/go: breaking change in 1.23rc2 with version constraints in GOPATH mode [1.22 backport] #69749

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
timothy-king opened this issue Oct 2, 2024 · 10 comments
Labels
CherryPickCandidate Used during the release process for point releases
Milestone

Comments

@timothy-king
Copy link
Contributor

@taking requested issue #68658 to be considered for backport to the next 1.22 minor release.

@gopherbot please backport this to 1.22. It's necessary to have consistent file versions with build tags with later versions.

@timothy-king timothy-king added GoCommand cmd/go CherryPickCandidate Used during the release process for point releases labels Oct 2, 2024
@timothy-king
Copy link
Contributor Author

timothy-king commented Oct 2, 2024

CC @griesemer .

https://go.dev/cl/615685 has some helpful context on why FileVersions from go/types has a different meaning in 1.22 and should maybe be updated.

@dmitshur dmitshur changed the title cmd/go: breaking change in 1.23rc2 with version constraints in GOPATH mode [1.22 backport] #69094 cmd/go: breaking change in 1.23rc2 with version constraints in GOPATH mode [1.22 backport] Oct 2, 2024
@gopherbot gopherbot added this to the Go1.22.9 milestone Oct 2, 2024
@timothy-king
Copy link
Contributor Author

Example that shows the discontinuity between 1.22 and 1.23:

package main

import (
	"fmt"
	"go/ast"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
)

func main() {
	contents := `

//go:build go1.18

// FileVersion == "go1.18"  according to go 1.22, 1.21.
// FileVersion == "go1.21"  according to go 1.23, tip.

package p

func p[T any, S []T](x T) {}

func f() {
	var f func(int) = p // Use a 1.21 feature.
	print(f)
}
	`

	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "p.go", contents, 0)
	if err != nil {
		panic(err)
	}

	conf := types.Config{
		Importer:  importer.Default(),
		GoVersion: "go1.21",
	}
	info := types.Info{}
	_, err = conf.Check("", fset, []*ast.File{file}, &info)

	fmt.Println(err)
}

1.23 says this type checks. 1.22 says this does not type check with the following error:

p.go:9:20: implicitly instantiated function in assignment requires go1.21 or later

@timothy-king
Copy link
Contributor Author

https://go.dev/cl/617635 has more examples where go/types.Info.FileVersions has a different meaning in 1.22.

Back porting would mean FileVersions would have a single consistent semantics going forward. This is also not a trivial backport or an issue that impacts many users directly. It may not be worth the risk.

But THB if someone came up and asked me how to use go/types.Info.FileVersions correctly, I would at this point tell them to skip to 1.23 or to only use it for the specific check 'is this file >= 1.22 or unknown (until you stop supporting 1.22)'. This way they could skip needing to specialize for both cases.

So we need to decide if we are going to accept go/types producing different FileVersion values as Unfortunate or to back port.

@timothy-king
Copy link
Contributor Author

timothy-king commented Oct 8, 2024

Moving from cmd/go review status to 'waiting on weekly review' and removing from CLI triage. This is a go/types decision.

@dmitshur dmitshur removed the GoCommand cmd/go label Oct 9, 2024
@dmitshur dmitshur changed the title cmd/go: breaking change in 1.23rc2 with version constraints in GOPATH mode [1.22 backport] go/types, cmd/go: breaking change in 1.23rc2 with version constraints in GOPATH mode [1.22 backport] Oct 9, 2024
@cherrymui
Copy link
Member

Discussed in the release meeting, we thought that that this is a subtle edge case that doesn’t seem to be causing problems for most users (if one wants 1.21 feature, they probably shouldn't use 1.18 build tag). So this is mostly potentially for tool authors? But we haven’t heard external reports so far. So might not be worth the risk of backporting fairly late in the 1.22 cycle.

@timothy-king what do you think? Thanks.

@timothy-king
Copy link
Contributor Author

So with some additional prodding and admittedly very strange choices, one can lift this to a compiler problem:

-- go.mod --
module example.com/m

go 1.21
-- main.go --
//go:build go1.16

package main

func P[T any]() {} // uses a go 1.18 feature

func main() {
        println("ran")
}

This builds with go1.20.14 and go1.23.1 while it fails to build with go1.21.13 and go1.22.7:

% go1.20.14 build; ./m
ran
% go1.21.13 build 
# example.com/m
./m.go:5:8: type parameter requires go1.18 or later (-lang was set to go1.21; check go.mod)
./m.go:5:10: predeclared any requires go1.18 or later (-lang was set to go1.21; check go.mod)
% go1.22.7 build
# example.com/m
./m.go:5:8: type parameter requires go1.18 or later (file declares //go:build go1.16)
./m.go:5:10: predeclared any requires go1.18 or later (file declares //go:build go1.16)
% go1.23.1 build; ./m
ran

There are multiple odd choices in this example: a 1.16 build tag, using a 1.18 feature, and using go1.20.14 with a go1.21 module. But still not backwards compatible in the strictest sense. A working example stopped compiling even if it is an edge case.

TBH the bit I really want to fix is that I want a simpler world where FileVersions has one meaning and the current 1.22 meaning is a bug. This is an obnoxious bit of tech debt I would like to get rid of.

It may not be worth the risk though as you said. I'll let other decide.

@cherrymui
Copy link
Member

Yes, this can leads to a compilation failure. But using 1.18 feature with a 1.16 build tag seems a bad choice, and is probably really are. It doesn't seem too bad that this doesn't compile with Go 1.22, given that this would also not compile with Go 1.21.

@prattmic
Copy link
Member

Given the lack of user-reported issues, we've decided not to backport.

@prattmic prattmic closed this as not planned Won't fix, can't repro, duplicate, stale Oct 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CherryPickCandidate Used during the release process for point releases
Projects
None yet
Development

No branches or pull requests

6 participants