mirror of
https://github.com/golang/go
synced 2024-11-17 00:04:40 -07:00
go/types, types2: report error for range over int if Go version < 1.22
Fixes #64704. Change-Id: Ied3af46ab534343cdafba5ee27680b9c6ef3d37a Reviewed-on: https://go-review.googlesource.com/c/go/+/549459 Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com> Reviewed-by: Alan Donovan <adonovan@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
d95e25e83c
commit
6146a73d27
@ -861,7 +861,9 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
|
||||
var key, val Type
|
||||
if x.mode != invalid {
|
||||
// Ranging over a type parameter is permitted if it has a core type.
|
||||
k, v, cause, isFunc, ok := rangeKeyVal(x.typ)
|
||||
k, v, cause, isFunc, ok := rangeKeyVal(x.typ, func(v goVersion) bool {
|
||||
return check.allowVersion(check.pkg, x.expr, v)
|
||||
})
|
||||
switch {
|
||||
case !ok && cause != "":
|
||||
check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s: %s", &x, cause)
|
||||
@ -964,16 +966,18 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
|
||||
}
|
||||
|
||||
// RangeKeyVal returns the key and value types for a range over typ.
|
||||
// Exported for use by the compiler (does not exist in go/types).
|
||||
func RangeKeyVal(typ Type) (Type, Type) {
|
||||
key, val, _, _, _ := rangeKeyVal(typ)
|
||||
key, val, _, _, _ := rangeKeyVal(typ, nil)
|
||||
return key, val
|
||||
}
|
||||
|
||||
// rangeKeyVal returns the key and value type produced by a range clause
|
||||
// over an expression of type typ. If the range clause is not permitted,
|
||||
// rangeKeyVal returns ok = false. When ok = false, rangeKeyVal may also
|
||||
// return a reason in cause.
|
||||
func rangeKeyVal(typ Type) (key, val Type, cause string, isFunc, ok bool) {
|
||||
// over an expression of type typ.
|
||||
// If allowVersion != nil, it is used to check the required language version.
|
||||
// If the range clause is not permitted, rangeKeyVal returns ok = false.
|
||||
// When ok = false, rangeKeyVal may also return a reason in cause.
|
||||
func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
|
||||
bad := func(cause string) (Type, Type, string, bool, bool) {
|
||||
return Typ[Invalid], Typ[Invalid], cause, false, false
|
||||
}
|
||||
@ -991,6 +995,9 @@ func rangeKeyVal(typ Type) (key, val Type, cause string, isFunc, ok bool) {
|
||||
return Typ[Int], universeRune, "", false, true // use 'rune' name
|
||||
}
|
||||
if isInteger(typ) {
|
||||
if allowVersion != nil && !allowVersion(go1_22) {
|
||||
return bad("requires go1.22 or later")
|
||||
}
|
||||
return orig, nil, "", false, true
|
||||
}
|
||||
case *Array:
|
||||
@ -1005,6 +1012,7 @@ func rangeKeyVal(typ Type) (key, val Type, cause string, isFunc, ok bool) {
|
||||
}
|
||||
return typ.elem, nil, "", false, true
|
||||
case *Signature:
|
||||
// TODO(gri) when this becomes enabled permanently, add version check
|
||||
if !buildcfg.Experiment.RangeFunc {
|
||||
break
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ var (
|
||||
go1_18 = asGoVersion("go1.18")
|
||||
go1_20 = asGoVersion("go1.20")
|
||||
go1_21 = asGoVersion("go1.21")
|
||||
go1_22 = asGoVersion("go1.22")
|
||||
|
||||
// current (deployed) Go version
|
||||
go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version))
|
||||
|
@ -852,7 +852,9 @@ func (check *Checker) rangeStmt(inner stmtContext, s *ast.RangeStmt) {
|
||||
var key, val Type
|
||||
if x.mode != invalid {
|
||||
// Ranging over a type parameter is permitted if it has a core type.
|
||||
k, v, cause, isFunc, ok := rangeKeyVal(x.typ)
|
||||
k, v, cause, isFunc, ok := rangeKeyVal(x.typ, func(v goVersion) bool {
|
||||
return check.allowVersion(check.pkg, x.expr, v)
|
||||
})
|
||||
switch {
|
||||
case !ok && cause != "":
|
||||
check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s: %s", &x, cause)
|
||||
@ -955,10 +957,11 @@ func (check *Checker) rangeStmt(inner stmtContext, s *ast.RangeStmt) {
|
||||
}
|
||||
|
||||
// rangeKeyVal returns the key and value type produced by a range clause
|
||||
// over an expression of type typ. If the range clause is not permitted,
|
||||
// rangeKeyVal returns ok = false. When ok = false, rangeKeyVal may also
|
||||
// return a reason in cause.
|
||||
func rangeKeyVal(typ Type) (key, val Type, cause string, isFunc, ok bool) {
|
||||
// over an expression of type typ.
|
||||
// If allowVersion != nil, it is used to check the required language version.
|
||||
// If the range clause is not permitted, rangeKeyVal returns ok = false.
|
||||
// When ok = false, rangeKeyVal may also return a reason in cause.
|
||||
func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
|
||||
bad := func(cause string) (Type, Type, string, bool, bool) {
|
||||
return Typ[Invalid], Typ[Invalid], cause, false, false
|
||||
}
|
||||
@ -976,6 +979,9 @@ func rangeKeyVal(typ Type) (key, val Type, cause string, isFunc, ok bool) {
|
||||
return Typ[Int], universeRune, "", false, true // use 'rune' name
|
||||
}
|
||||
if isInteger(typ) {
|
||||
if allowVersion != nil && !allowVersion(go1_22) {
|
||||
return bad("requires go1.22 or later")
|
||||
}
|
||||
return orig, nil, "", false, true
|
||||
}
|
||||
case *Array:
|
||||
@ -990,6 +996,7 @@ func rangeKeyVal(typ Type) (key, val Type, cause string, isFunc, ok bool) {
|
||||
}
|
||||
return typ.elem, nil, "", false, true
|
||||
case *Signature:
|
||||
// TODO(gri) when this becomes enabled permanently, add version check
|
||||
if !buildcfg.Experiment.RangeFunc {
|
||||
break
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ var (
|
||||
go1_18 = asGoVersion("go1.18")
|
||||
go1_20 = asGoVersion("go1.20")
|
||||
go1_21 = asGoVersion("go1.21")
|
||||
go1_22 = asGoVersion("go1.22")
|
||||
|
||||
// current (deployed) Go version
|
||||
go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version))
|
||||
|
12
src/internal/types/testdata/fixedbugs/issue64704.go
vendored
Normal file
12
src/internal/types/testdata/fixedbugs/issue64704.go
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// -lang=go1.21
|
||||
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
func _() {
|
||||
for range 10 /* ERROR "cannot range over 10 (untyped int constant): requires go1.22 or later" */ {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user