mirror of https://github.com/golang/go.git
cmd/compile, go/types: allow `any` anywhere (as a type)
Adjust types2 and go/types and some test cases. Because `any` is not treated specially anymore in constraint position we get additional errors in constraints if `any` is used before Go1.18 (in addition to the error that type parameter lists are not permitted before Go1.18). Fixes #33232. Change-Id: I85590c6094b07c3e494fef319e3a38d0217cf6f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/351456 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
7a03ca65b3
commit
1e57748892
|
|
@ -625,13 +625,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel
|
|||
// This also preserves the grouped output of type parameter lists
|
||||
// when printing type strings.
|
||||
if i == 0 || f.Type != list[i-1].Type {
|
||||
// The predeclared identifier "any" is visible only as a type bound in a type parameter list.
|
||||
// If we allow "any" for general use, this if-statement can be removed (issue #33232).
|
||||
if name, _ := unparen(f.Type).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == universeAny {
|
||||
bound = universeAny.Type()
|
||||
} else {
|
||||
bound = check.typ(f.Type)
|
||||
}
|
||||
bound = check.typ(f.Type)
|
||||
}
|
||||
tparams[i].bound = bound
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ package p
|
|||
|
||||
// import "io" // for type assertion tests
|
||||
|
||||
// The predeclared identifier "any" can only be used as a constraint
|
||||
// in a type parameter list.
|
||||
var _ any // ERROR cannot use any outside constraint position
|
||||
func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) {
|
||||
var _ any /* ERROR constraint */
|
||||
var _ any // ok to use any anywhere
|
||||
func _[_ any, _ interface{any}](any) {
|
||||
var _ any
|
||||
}
|
||||
|
||||
func identity[T any](x T) T { return x }
|
||||
|
|
|
|||
|
|
@ -33,20 +33,20 @@ type (
|
|||
_ interface{int|~ /* ERROR overlapping terms ~int */ int }
|
||||
_ interface{~int|~ /* ERROR overlapping terms ~int */ int }
|
||||
_ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ }
|
||||
_ interface{int|interface{}}
|
||||
_ interface{int|any}
|
||||
_ interface{int|~string|union}
|
||||
_ interface{int|~string|interface{int}}
|
||||
_ interface{union|union /* ERROR overlapping terms p.union and p.union */ }
|
||||
|
||||
// For now we do not permit interfaces with methods in unions.
|
||||
_ interface{~ /* ERROR invalid use of ~ */ interface{}}
|
||||
_ interface{~ /* ERROR invalid use of ~ */ any}
|
||||
_ interface{int|interface /* ERROR cannot use .* in union */ { m() }}
|
||||
)
|
||||
|
||||
type (
|
||||
// Tilde is not permitted on defined types or interfaces.
|
||||
foo int
|
||||
bar interface{}
|
||||
bar any
|
||||
_ interface{foo}
|
||||
_ interface{~ /* ERROR invalid use of ~ */ foo }
|
||||
_ interface{~ /* ERROR invalid use of ~ */ bar }
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ type I1[T any] interface{
|
|||
}
|
||||
|
||||
// There is no such thing as a variadic generic type.
|
||||
type _[T ... /* ERROR invalid use of ... */ interface{}] struct{}
|
||||
type _[T ... /* ERROR invalid use of ... */ any] struct{}
|
||||
|
||||
// Generic interfaces may be embedded as one would expect.
|
||||
type I2 interface {
|
||||
|
|
@ -213,9 +213,9 @@ func Sum[T Adder[T]](list []T) T {
|
|||
}
|
||||
|
||||
// Valid and invalid variations.
|
||||
type B0 interface {}
|
||||
type B1[_ any] interface{}
|
||||
type B2[_, _ any] interface{}
|
||||
type B0 any
|
||||
type B1[_ any] any
|
||||
type B2[_, _ any] any
|
||||
|
||||
func _[T1 B0]() {}
|
||||
func _[T1 B1[T1]]() {}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
package go1_17
|
||||
|
||||
type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{}
|
||||
type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
|
||||
|
||||
// for init (and main, but we're not in package main) we should only get one error
|
||||
func init[P /* ERROR func init must have no type parameters */ any]() {}
|
||||
func main[P /* ERROR type parameters require go1\.18 or later */ any]() {}
|
||||
func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
|
||||
func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
|
||||
|
||||
func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) {
|
||||
func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
|
||||
var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int]
|
||||
var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int])
|
||||
_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{}
|
||||
|
|
|
|||
|
|
@ -38,16 +38,10 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
|
|||
}
|
||||
return
|
||||
case universeAny, universeComparable:
|
||||
// complain if necessary
|
||||
if !check.allowVersion(check.pkg, 1, 18) {
|
||||
check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value)
|
||||
return // avoid follow-on errors
|
||||
}
|
||||
if obj == universeAny {
|
||||
// If we allow "any" for general use, this if-statement can be removed (issue #33232).
|
||||
check.softErrorf(e, "cannot use any outside constraint position")
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
check.recordUse(e, obj)
|
||||
|
||||
|
|
|
|||
|
|
@ -668,27 +668,18 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
|
|||
*dst = bindTParams(tparams)
|
||||
|
||||
index := 0
|
||||
var bound Type
|
||||
var bounds []Type
|
||||
var posns []positioner // bound positions
|
||||
for _, f := range list.List {
|
||||
if f.Type == nil {
|
||||
goto next
|
||||
// TODO(rfindley) we should be able to rely on f.Type != nil at this point
|
||||
if f.Type != nil {
|
||||
bound := check.typ(f.Type)
|
||||
bounds = append(bounds, bound)
|
||||
posns = append(posns, f.Type)
|
||||
for i := range f.Names {
|
||||
tparams[index+i].bound = bound
|
||||
}
|
||||
}
|
||||
// The predeclared identifier "any" is visible only as a type bound in a type parameter list.
|
||||
// If we allow "any" for general use, this if-statement can be removed (issue #33232).
|
||||
if name, _ := unparen(f.Type).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == universeAny {
|
||||
bound = universeAny.Type()
|
||||
} else {
|
||||
bound = check.typ(f.Type)
|
||||
}
|
||||
bounds = append(bounds, bound)
|
||||
posns = append(posns, f.Type)
|
||||
for i := range f.Names {
|
||||
tparams[index+i].bound = bound
|
||||
}
|
||||
|
||||
next:
|
||||
index += len(f.Names)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ package p
|
|||
|
||||
// import "io" // for type assertion tests
|
||||
|
||||
// The predeclared identifier "any" can only be used as a constraint
|
||||
// in a type parameter list.
|
||||
var _ any // ERROR cannot use any outside constraint position
|
||||
func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) {
|
||||
var _ any /* ERROR constraint */
|
||||
var _ any // ok to use any anywhere
|
||||
func _[_ any, _ interface{any}](any) {
|
||||
var _ any
|
||||
}
|
||||
|
||||
func identity[T any](x T) T { return x }
|
||||
|
|
|
|||
|
|
@ -33,20 +33,20 @@ type (
|
|||
_ interface{int|~ /* ERROR overlapping terms ~int */ int }
|
||||
_ interface{~int|~ /* ERROR overlapping terms ~int */ int }
|
||||
_ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ }
|
||||
_ interface{int|interface{}}
|
||||
_ interface{int|any}
|
||||
_ interface{int|~string|union}
|
||||
_ interface{int|~string|interface{int}}
|
||||
_ interface{union|union /* ERROR overlapping terms p.union and p.union */ }
|
||||
|
||||
// For now we do not permit interfaces with methods in unions.
|
||||
_ interface{~ /* ERROR invalid use of ~ */ interface{}}
|
||||
_ interface{~ /* ERROR invalid use of ~ */ any}
|
||||
_ interface{int|interface /* ERROR cannot use .* in union */ { m() }}
|
||||
)
|
||||
|
||||
type (
|
||||
// Tilde is not permitted on defined types or interfaces.
|
||||
foo int
|
||||
bar interface{}
|
||||
bar any
|
||||
_ interface{foo}
|
||||
_ interface{~ /* ERROR invalid use of ~ */ foo }
|
||||
_ interface{~ /* ERROR invalid use of ~ */ bar }
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ type I1[T any] interface{
|
|||
}
|
||||
|
||||
// There is no such thing as a variadic generic type.
|
||||
type _[T ... /* ERROR invalid use of ... */ interface{}] struct{}
|
||||
type _[T ... /* ERROR invalid use of ... */ any] struct{}
|
||||
|
||||
// Generic interfaces may be embedded as one would expect.
|
||||
type I2 interface {
|
||||
|
|
@ -219,9 +219,9 @@ func Sum[T Adder[T]](list []T) T {
|
|||
}
|
||||
|
||||
// Valid and invalid variations.
|
||||
type B0 interface {}
|
||||
type B1[_ any] interface{}
|
||||
type B2[_, _ any] interface{}
|
||||
type B0 any
|
||||
type B1[_ any] any
|
||||
type B2[_, _ any] any
|
||||
|
||||
func _[T1 B0]() {}
|
||||
func _[T1 B1[T1]]() {}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
package go1_17
|
||||
|
||||
type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{}
|
||||
type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
|
||||
|
||||
// for init (and main, but we're not in package main) we should only get one error
|
||||
func init[P /* ERROR func init must have no type parameters */ any]() {}
|
||||
func main[P /* ERROR type parameters require go1\.18 or later */ any]() {}
|
||||
func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
|
||||
func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
|
||||
|
||||
func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) {
|
||||
func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
|
||||
var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int]
|
||||
var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int])
|
||||
_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{}
|
||||
|
|
|
|||
|
|
@ -36,16 +36,10 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
|
|||
}
|
||||
return
|
||||
case universeAny, universeComparable:
|
||||
// complain if necessary
|
||||
if !check.allowVersion(check.pkg, 1, 18) {
|
||||
check.errorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name)
|
||||
return // avoid follow-on errors
|
||||
}
|
||||
if obj == universeAny {
|
||||
// If we allow "any" for general use, this if-statement can be removed (issue #33232).
|
||||
check.softErrorf(e, _Todo, "cannot use any outside constraint position")
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
check.recordUse(e, obj)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// errorcheck
|
||||
// compile
|
||||
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
|
|
@ -6,4 +6,5 @@
|
|||
|
||||
package p
|
||||
|
||||
var x any // ERROR "undefined: any|undefined type .*any.*|cannot use any outside constraint position"
|
||||
// any is now permitted instead of interface{}
|
||||
var x any
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@
|
|||
|
||||
package tparam1
|
||||
|
||||
// The predeclared identifier "any" is only visible as a constraint
|
||||
// in a type parameter list.
|
||||
var _ any // ERROR "cannot use any outside constraint position"
|
||||
func _(_ any) // ERROR "cannot use any outside constraint position"
|
||||
type _[_ any /* ok here */] struct{}
|
||||
// The predeclared identifier "any" may be used in place of interface{}.
|
||||
var _ any
|
||||
func _(_ any)
|
||||
type _[_ any] struct{}
|
||||
|
||||
const N = 10
|
||||
|
||||
|
|
@ -24,16 +23,16 @@ type (
|
|||
_[T1, T2 any, T3 any] struct{}
|
||||
)
|
||||
|
||||
func _[T any]() {}
|
||||
func _[T, T any]() {} // ERROR "T redeclared"
|
||||
func _[T any]() {}
|
||||
func _[T, T any]() {} // ERROR "T redeclared"
|
||||
func _[T1, T2 any](x T1) T2 { panic(0) }
|
||||
|
||||
// Type parameters are visible from opening [ to end of function.
|
||||
type C interface{}
|
||||
|
||||
func _[T interface{}]() {}
|
||||
func _[T C]() {}
|
||||
func _[T struct{}]() {}// ERROR "not an interface"
|
||||
func _[T interface{}]() {}
|
||||
func _[T C]() {}
|
||||
func _[T struct{}]() {} // ERROR "not an interface"
|
||||
func _[T interface{ m() T }]() {}
|
||||
func _[T1 interface{ m() T2 }, T2 interface{ m() T1 }]() {
|
||||
var _ T1
|
||||
|
|
|
|||
Loading…
Reference in New Issue