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 <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Alan Donovan 2024-03-08 10:54:34 -05:00
Родитель 93c0ca5673
Коммит 9b64301ea6
1 изменённых файлов: 12 добавлений и 1 удалений

13
gopls/internal/cache/check.go поставляемый
Просмотреть файл

@ -9,6 +9,7 @@ import (
"crypto/sha256"
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/token"
"go/types"
@ -30,6 +31,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"
@ -1629,10 +1631,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
cfg.GoVersion = goVersion
}
}