Skip to content

Commit 63b0f80

Browse files
matloobcagedmantis
authored andcommitted
[release-branch.go1.23] go/types, types2: only use fileVersion if 1.21 or greater
Only honor //go:build language version downgrades if the version specified is 1.21 or greater. Before 1.21 the version in //go:build lines didn't have the meaning of setting the file's language version. This fixes an issue that was appearing in GOPATH builds: Go 1.23 started providing -lang versions to the compiler in GOPATH mode (among other places) which it wasn't doing before. For example, take a go file with a //go:build line specifying go1.10. If that file used a 1.18 feature, that use would compile fine with a Go 1.22 toolchain. But, before this change, it would produce an error when compiling with the 1.23 toolchain because it set the language version to 1.10 and disallowed the 1.18 feature. This breaks backwards compatibility: when the build tag was added, it did not have the meaning of restricting the language version. Fixes #68658 Change-Id: I4ac2b45a981cd019183d52ba324ba8f0fed93a8e Reviewed-on: https://go-review.googlesource.com/c/go/+/603895 Reviewed-by: Robert Griesemer <[email protected]> Commit-Queue: Michael Matloob <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Michael Matloob <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/604935
1 parent 7adb012 commit 63b0f80

File tree

10 files changed

+87
-22
lines changed

10 files changed

+87
-22
lines changed

src/cmd/compile/internal/types2/api_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,17 +2903,21 @@ func TestFileVersions(t *testing.T) {
29032903
{"", "go1.20", ""}, // file upgrade ignored
29042904
{"go1.19", "go1.20", "go1.20"}, // file upgrade permitted
29052905
{"go1.20", "go1.19", "go1.20"}, // file downgrade not permitted
2906-
{"go1.21", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
2906+
{"go1.21", "go1.20", "go1.21"}, // file downgrade not permitted
2907+
{"go1.22", "go1.21", "go1.21"}, // file downgrade permitted (file and module version are >= go1.21)
29072908

29082909
// versions containing release numbers
29092910
// (file versions containing release numbers are considered invalid)
29102911
{"go1.19.0", "", "go1.19.0"}, // no file version specified
29112912
{"go1.20", "go1.20.1", "go1.20"}, // file upgrade ignored
29122913
{"go1.20.1", "go1.20", "go1.20.1"}, // file upgrade ignored
2914+
{"go1.21.0", "go1.21.1", "go1.21.0"}, // file upgrade ignored
2915+
{"go1.21", "go1.21.1", "go1.21"}, // file upgrade ignored
29132916
{"go1.20.1", "go1.21", "go1.21"}, // file upgrade permitted
2917+
{"go1.21.1", "go1.21", "go1.21.1"}, // file downgrade ignored
29142918
{"go1.20.1", "go1.19", "go1.20.1"}, // file downgrade not permitted
29152919
{"go1.21.1", "go1.19.1", "go1.21.1"}, // file downgrade not permitted (invalid file version)
2916-
{"go1.21.1", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
2920+
{"go1.22.1", "go1.21", "go1.21"}, // file downgrade permitted (file and module version is >= go1.21)
29172921
} {
29182922
var src string
29192923
if test.fileVersion != "" {

src/cmd/compile/internal/types2/check.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,12 +354,25 @@ func (check *Checker) initFiles(files []*syntax.File) {
354354
// To work around this, downgrades are only allowed when the
355355
// module's Go version is Go 1.21 or later.
356356
//
357+
// Downgrades are also only allowed to Go versions Go 1.21 or later.
358+
// In GOPATH mode, there's no way to set a module version and the
359+
// -lang is set to the local toolchain version to allow the use of
360+
// new features in GOPATH mode. But //go:build lines added before go1.21
361+
// weren't intended to downgrade, so code with //go:build lines for
362+
// go versions earlier than 1.21 may use language features added
363+
// in later versions and compile.
364+
//
365+
// We should probably change the downgradeOk condition to capture this
366+
// instead of adding an extra condition, but to make the change simpler,
367+
// we've tried to limit it to one line.
368+
// TODO(gri): simplify this code after 1.23 has shipped
369+
//
357370
// If there is no valid check.version, then we don't really know what
358371
// Go version to apply.
359372
// Legacy tools may do this, and they historically have accepted everything.
360373
// Preserve that behavior by ignoring //go:build constraints entirely in that
361374
// case (!pkgVersionOk).
362-
if cmp > 0 || cmp < 0 && downgradeOk {
375+
if cmp > 0 || cmp < 0 && downgradeOk && fileVersion.cmp(go1_21) >= 0 {
363376
v = file.GoVersion
364377
}
365378
}

src/go/types/api_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,17 +2909,21 @@ func TestFileVersions(t *testing.T) {
29092909
{"", "go1.20", ""}, // file upgrade ignored
29102910
{"go1.19", "go1.20", "go1.20"}, // file upgrade permitted
29112911
{"go1.20", "go1.19", "go1.20"}, // file downgrade not permitted
2912-
{"go1.21", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
2912+
{"go1.21", "go1.20", "go1.21"}, // file downgrade not permitted
2913+
{"go1.22", "go1.21", "go1.21"}, // file downgrade permitted (file and module version are >= go1.21)
29132914

29142915
// versions containing release numbers
29152916
// (file versions containing release numbers are considered invalid)
29162917
{"go1.19.0", "", "go1.19.0"}, // no file version specified
29172918
{"go1.20", "go1.20.1", "go1.20"}, // file upgrade ignored
29182919
{"go1.20.1", "go1.20", "go1.20.1"}, // file upgrade ignored
2920+
{"go1.21.0", "go1.21.1", "go1.21.0"}, // file upgrade ignored
2921+
{"go1.21", "go1.21.1", "go1.21"}, // file upgrade ignored
29192922
{"go1.20.1", "go1.21", "go1.21"}, // file upgrade permitted
2923+
{"go1.21.1", "go1.21", "go1.21.1"}, // file downgrade ignored
29202924
{"go1.20.1", "go1.19", "go1.20.1"}, // file downgrade not permitted
29212925
{"go1.21.1", "go1.19.1", "go1.21.1"}, // file downgrade not permitted (invalid file version)
2922-
{"go1.21.1", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
2926+
{"go1.22.1", "go1.21", "go1.21"}, // file downgrade permitted (file and module version is >= go1.21)
29232927
} {
29242928
var src string
29252929
if test.fileVersion != "" {

src/go/types/check.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,25 @@ func (check *Checker) initFiles(files []*ast.File) {
376376
// To work around this, downgrades are only allowed when the
377377
// module's Go version is Go 1.21 or later.
378378
//
379+
// Downgrades are also only allowed to Go versions Go 1.21 or later.
380+
// In GOPATH mode, there's no way to set a module version and the
381+
// -lang is set to the local toolchain version to allow the use of
382+
// new features in GOPATH mode. But //go:build lines added before go1.21
383+
// weren't intended to downgrade, so code with //go:build lines for
384+
// go versions earlier than 1.21 may use language features added
385+
// in later versions and compile.
386+
//
387+
// We should probably change the downgradeOk condition to capture this
388+
// instead of adding an extra condition, but to make the change simpler,
389+
// we've tried to limit it to one line.
390+
// TODO(gri): simplify this code after 1.23 has shipped
391+
//
379392
// If there is no valid check.version, then we don't really know what
380393
// Go version to apply.
381394
// Legacy tools may do this, and they historically have accepted everything.
382395
// Preserve that behavior by ignoring //go:build constraints entirely in that
383396
// case (!pkgVersionOk).
384-
if cmp > 0 || cmp < 0 && downgradeOk {
397+
if cmp > 0 || cmp < 0 && downgradeOk && fileVersion.cmp(go1_21) >= 0 {
385398
v = file.GoVersion
386399
}
387400
}

src/internal/types/testdata/check/go1_20_19.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ type Slice []byte
1414
type Array [8]byte
1515

1616
var s Slice
17-
var p = (Array)(s /* ok because Go 1.20 ignored the //go:build go1.19 */)
17+
var p = (Array)(s /* ok because downgrades below 1.21 are ignored */)

src/internal/types/testdata/check/go1_21_19.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ type Slice []byte
1414
type Array [8]byte
1515

1616
var s Slice
17-
var p = (Array)(s /* ERROR "requires go1.20 or later" */)
17+
var p = (Array)(s /* ok because downgrades below 1.21 are ignored */)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// -lang=go1.21
2+
3+
// Copyright 2022 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Check Go language version-specific errors.
8+
9+
//go:build go1.22
10+
11+
package p
12+
13+
func f() {
14+
for _ = range /* ok because of upgrade to 1.22 */ 10 {
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// -lang=go1.22
2+
3+
// Copyright 2024 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Check Go language version-specific errors.
8+
9+
//go:build go1.21
10+
11+
package p
12+
13+
func f() {
14+
for _ = range 10 /* ERROR "requires go1.22 or later" */ {
15+
}
16+
}

src/internal/types/testdata/fixedbugs/issue66285.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
// -lang=go1.21
1+
// -lang=go1.13
22

33
// Copyright 2024 The Go Authors. All rights reserved.
44
// Use of this source code is governed by a BSD-style
55
// license that can be found in the LICENSE file.
66

7-
// Note: Downgrading to go1.13 requires at least go1.21,
8-
// hence the need for -lang=go1.21 at the top.
9-
10-
//go:build go1.13
11-
127
package p
138

149
import "io"

test/fixedbugs/issue63489a.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
// errorcheck -lang=go1.21
1+
// errorcheck -lang=go1.22
22

33
// Copyright 2023 The Go Authors. All rights reserved.
44
// Use of this source code is governed by a BSD-style
55
// license that can be found in the LICENSE file.
66

7-
//go:build go1.4
7+
// This file has been changed from its original version as
8+
// //go:build language downgrades below go1.21 are no longer
9+
// supported. The original tested a downgrade from go1.21 to
10+
// go1.4 while this new version tests a downgrade from go1.22
11+
// to go1.21
812

9-
package p
10-
11-
const c = 0o123 // ERROR "file declares //go:build go1.4"
13+
//go:build go1.21
1214

13-
// ERROR "file declares //go:build go1.4"
15+
package p
1416

15-
//line issue63489a.go:13:1
16-
const d = 0o124
17+
func f() {
18+
for _ = range 10 { // ERROR "file declares //go:build go1.21"
19+
}
20+
}

0 commit comments

Comments
 (0)