- fbase := base(file.Pos()) // fbase may be nil for tests
- check.recordFileVersion(fbase, check.conf.GoVersion) // record package version (possibly zero version)
- v, _ := parseGoVersion(file.GoVersion)
- if v.major > 0 {
- if v.equal(check.version) {
- continue
- }
- // Go 1.21 introduced the feature of setting the go.mod
- // go line to an early version of Go and allowing //go:build lines
- // to “upgrade” the Go version in a given file.
- // We can do that backwards compatibly.
- // Go 1.21 also introduced the feature of allowing //go:build lines
- // to “downgrade” the Go version in a given file.
- // That can't be done compatibly in general, since before the
- // 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 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(go1_21)) || check.version.equal(go0_0) {
- continue
- }
- if check.posVers == nil {
- check.posVers = make(map[*syntax.PosBase]version)
+ // use unaltered Config.GoVersion by default
+ // (This version string may contain dot-release numbers as in go1.20.1,
+ // unlike file versions which are Go language versions only, if valid.)
+ v := check.conf.GoVersion
+ // use the file version, if applicable
+ // (file versions are either the empty string or of the form go1.dd)
+ if pkgVersionOk {
+ fileVersion := asGoVersion(file.GoVersion)
+ if fileVersion.isValid() {
+ cmp := fileVersion.cmp(check.version)
+ // Go 1.21 introduced the feature of setting the go.mod
+ // go line to an early version of Go and allowing //go:build lines
+ // to “upgrade” (cmp > 0) the Go version in a given file.
+ // We can do that backwards compatibly.
+ //
+ // Go 1.21 also introduced the feature of allowing //go:build lines
+ // to “downgrade” (cmp < 0) the Go version in a given file.
+ // That can't be done compatibly in general, since before the
+ // 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 there is no valid 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 (!pkgVersionOk).
+ if cmp > 0 || cmp < 0 && downgradeOk {
+ v = file.GoVersion
+ }