From 4f9a966926e2537c435e60e75e5c866374be07e7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 19 Apr 2023 16:05:37 -0400 Subject: [PATCH] go/types: fix version downgrade bug without Config.GoVersion The gVisor team reported a regression in their checkers, which don't set Config.GoVersion, processing files that say //go:build go1.13 but still use 'any' (which happened in Go 1.18). That situation should continue to work, since it worked before, so add a special case for not knowing the GoVersion. Change-Id: I8820d8ccbdf76d304e2c7e45f6aaa993ff3d16a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/486398 Run-TryBot: Russ Cox TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/api.go | 2 +- src/cmd/compile/internal/types2/check.go | 5 ++++- src/go/types/api.go | 2 +- src/go/types/check.go | 5 ++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 24131192f8..bd87945295 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -112,7 +112,7 @@ type Config struct { // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or ist must be - // empty; an empty string indicates the latest language version. + // empty; an empty string disables Go language version checks. // If the format is invalid, invoking the type checker will cause a // panic. GoVersion string diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 5f0c521a2a..550fb1cafd 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -299,7 +299,10 @@ func (check *Checker) initFiles(files []*syntax.File) { // build lines were ignored and code got the module's Go version. // To work around this, downgrades are only allowed when the // module's Go version is Go 1.21 or later. - if v.before(check.version) && check.version.before(version{1, 21}) { + // If there is no check.version, then we don't really know what Go version to apply. + // Legacy tools may do this, and they historically have accepted everything. + // Preserve that behavior by ignoring //go:build constraints entirely in that case. + if (v.before(check.version) && check.version.before(version{1, 21})) || check.version.equal(version{0, 0}) { continue } if check.posVers == nil { diff --git a/src/go/types/api.go b/src/go/types/api.go index a144462968..7af84fd244 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -116,7 +116,7 @@ type Config struct { // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or it must be - // empty; an empty string indicates the latest language version. + // empty; an empty string disables Go language version checks. // If the format is invalid, invoking the type checker will cause a // panic. GoVersion string diff --git a/src/go/types/check.go b/src/go/types/check.go index 58cf6d060c..5381b5db68 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -302,7 +302,10 @@ func (check *Checker) initFiles(files []*ast.File) { // build lines were ignored and code got the module's Go version. // To work around this, downgrades are only allowed when the // module's Go version is Go 1.21 or later. - if v.before(check.version) && check.version.before(version{1, 21}) { + // If there is no check.version, then we don't really know what Go version to apply. + // Legacy tools may do this, and they historically have accepted everything. + // Preserve that behavior by ignoring //go:build constraints entirely in that case. + if (v.before(check.version) && check.version.before(version{1, 21})) || check.version.equal(version{0, 0}) { continue } if check.posVers == nil { -- 2.48.1