Skip to content

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

Not planned
@timothy-king

Description

@timothy-king

@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.

Activity

timothy-king

timothy-king commented on Oct 2, 2024

@timothy-king
ContributorAuthor

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.

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][/+] on Oct 2, 2024
added this to the Go1.22.9 milestone on Oct 2, 2024
timothy-king

timothy-king commented on Oct 4, 2024

@timothy-king
ContributorAuthor

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

timothy-king commented on Oct 5, 2024

@timothy-king
ContributorAuthor

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

timothy-king commented on Oct 8, 2024

@timothy-king
ContributorAuthor

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

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][/+] on Oct 9, 2024
cherrymui

cherrymui commented on Oct 11, 2024

@cherrymui
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

timothy-king commented on Oct 11, 2024

@timothy-king
ContributorAuthor

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

cherrymui commented on Oct 11, 2024

@cherrymui
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

prattmic commented on Oct 23, 2024

@prattmic
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CherryPickCandidateUsed during the release process for point releases

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @timothy-king@prattmic@dmitshur@gopherbot@cherrymui

        Issue actions

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