From 68630b32f58b502bc9b3ac8d8ba4f5d5a9266deb Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 8 Mar 2024 10:54:34 -0500 Subject: [PATCH] [gopls-release-branch.0.15] gopls/internal/cache: avoid go/types panic on version "go1.2.3" This change fixes a gopls panic caused by giving go/types@go.1.20 a Go version string with three components, e.g. go1.2.3. Unfortunately this is hard to write a test for, since it requires building gopls with go1.20 and running it with a go1.21 toolchain. Fixes golang/go#66195 Change-Id: I09257e6ded69568812b367ee80cafea30add93d3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/570135 LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Findley (cherry picked from commit 9b64301ea6a8b54b65ae8822dda04d4800de9b53) Reviewed-on: https://go-review.googlesource.com/c/tools/+/569879 Reviewed-by: Alan Donovan Auto-Submit: Robert Findley --- gopls/internal/cache/check.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/gopls/internal/cache/check.go b/gopls/internal/cache/check.go index 61eb98f9641..c159410a2f5 100644 --- a/gopls/internal/cache/check.go +++ b/gopls/internal/cache/check.go @@ -9,6 +9,7 @@ import ( "crypto/sha256" "fmt" "go/ast" + "go/build" "go/parser" "go/token" "go/types" @@ -29,6 +30,7 @@ import ( "golang.org/x/tools/gopls/internal/protocol" "golang.org/x/tools/gopls/internal/util/bug" "golang.org/x/tools/gopls/internal/util/safetoken" + "golang.org/x/tools/gopls/internal/util/slices" "golang.org/x/tools/internal/analysisinternal" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/tag" @@ -1628,10 +1630,19 @@ func (b *typeCheckBatch) typesConfig(ctx context.Context, inputs typeCheckInputs if inputs.goVersion != "" { goVersion := "go" + inputs.goVersion + // types.NewChecker panics if GoVersion is invalid. An unparsable mod // file should probably stop us before we get here, but double check // just in case. - if goVersionRx.MatchString(goVersion) { + // + // Prior to go/types@go1.21 the precondition was stricter: + // no patch version. That's not a problem when also using go1.20 list, + // as it would reject go.mod files containing a patch version, but + // go/types@go1.20 will panic on go.mod versions that are returned + // by go1.21 list, hence the need for the extra check. + if goVersionRx.MatchString(goVersion) && + (slices.Contains(build.Default.ReleaseTags, "go1.21") || + strings.Count(goVersion, ".") < 2) { // no patch version typesinternal.SetGoVersion(cfg, goVersion) } }