Skip to content

Commit c9afcba

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: require iterator yield to return bool (work-around)
The original implementation of the type checkers accepted any boolean result type for yield, but the compiler's front-end had a problem with it (#71131). As a temporary fix (for 1.24), adjust the type checkers to insist on the spec's literal wording and avoid the compiler panic. Fixes #71131. For #71164. Change-Id: Ie25f9a892e58b5e489d399b0bce2d0af55dc3c48 Reviewed-on: https://go-review.googlesource.com/c/go/+/640599 Reviewed-by: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> Reviewed-by: Tim King <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 54693a8 commit c9afcba

File tree

6 files changed

+34
-5
lines changed

6 files changed

+34
-5
lines changed

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

+7-2
Original file line numberDiff line numberDiff line change
@@ -1057,8 +1057,13 @@ func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, ca
10571057
return bad("func must be func(yield func(...) bool): argument is not func")
10581058
case cb.Params().Len() > 2:
10591059
return bad("func must be func(yield func(...) bool): yield func has too many parameters")
1060-
case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
1061-
return bad("func must be func(yield func(...) bool): yield func does not return bool")
1060+
case cb.Results().Len() != 1 || !Identical(cb.Results().At(0).Type(), universeBool):
1061+
// see go.dev/issues/71131, go.dev/issues/71164
1062+
if cb.Results().Len() == 1 && isBoolean(cb.Results().At(0).Type()) {
1063+
return bad("func must be func(yield func(...) bool): yield func returns user-defined boolean, not bool")
1064+
} else {
1065+
return bad("func must be func(yield func(...) bool): yield func does not return bool")
1066+
}
10621067
}
10631068
assert(cb.Recv() == nil)
10641069
// determine key and value types, if any

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

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var Unsafe *Package
2121

2222
var (
2323
universeIota Object
24+
universeBool Type
2425
universeByte Type // uint8 alias, but has name "byte"
2526
universeRune Type // int32 alias, but has name "rune"
2627
universeAnyNoAlias *TypeName
@@ -275,6 +276,7 @@ func init() {
275276
defPredeclaredFuncs()
276277

277278
universeIota = Universe.Lookup("iota")
279+
universeBool = Universe.Lookup("bool").Type()
278280
universeByte = Universe.Lookup("byte").Type()
279281
universeRune = Universe.Lookup("rune").Type()
280282
universeError = Universe.Lookup("error").Type()

src/go/types/stmt.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -1075,8 +1075,13 @@ func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, ca
10751075
return bad("func must be func(yield func(...) bool): argument is not func")
10761076
case cb.Params().Len() > 2:
10771077
return bad("func must be func(yield func(...) bool): yield func has too many parameters")
1078-
case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
1079-
return bad("func must be func(yield func(...) bool): yield func does not return bool")
1078+
case cb.Results().Len() != 1 || !Identical(cb.Results().At(0).Type(), universeBool):
1079+
// see go.dev/issues/71131, go.dev/issues/71164
1080+
if cb.Results().Len() == 1 && isBoolean(cb.Results().At(0).Type()) {
1081+
return bad("func must be func(yield func(...) bool): yield func returns user-defined boolean, not bool")
1082+
} else {
1083+
return bad("func must be func(yield func(...) bool): yield func does not return bool")
1084+
}
10801085
}
10811086
assert(cb.Recv() == nil)
10821087
// determine key and value types, if any

src/go/types/universe.go

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
func _() {
8+
type Bool bool
9+
for range func /* ERROR "yield func returns user-defined boolean, not bool" */ (func() Bool) {} {
10+
}
11+
for range func /* ERROR "yield func returns user-defined boolean, not bool" */ (func(int) Bool) {} {
12+
}
13+
for range func /* ERROR "yield func returns user-defined boolean, not bool" */ (func(int, string) Bool) {} {
14+
}
15+
}

src/internal/types/testdata/spec/range.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package p
66

77
type MyInt int32
8-
type MyBool bool
8+
type MyBool = bool // TODO(gri) remove alias declaration - see go.dev/issues/71131, go.dev/issues/71164
99
type MyString string
1010
type MyFunc1 func(func(int) bool)
1111
type MyFunc2 func(int) bool

0 commit comments

Comments
 (0)