[go] cmd/compile: allow `any` anywhere (as a type)

138 views
Skip to first unread message

Robert Griesemer (Gerrit)

unread,
Sep 22, 2021, 3:19:54 PM9/22/21
to Robert Griesemer, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Go Bot, Robert Findley, golang-co...@googlegroups.com

Robert Griesemer submitted this change.

View Change



2 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:

```
The name of the file: src/go/types/testdata/examples/types.go2
Insertions: 1, Deletions: 1.

@@ -219,7 +219,7 @@
}

// Valid and invalid variations.
-type B0 interface {}
+type B0 any
type B1[_ any] any
type B2[_, _ any] any

```
```
The name of the file: test/typeparam/tparam1.go
Insertions: 9, Deletions: 10.

@@ -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 @@
_[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
```

Approvals: Robert Findley: Looks good to me, approved Robert Griesemer: Trusted; Run TryBots Go Bot: TryBots succeeded
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 <g...@golang.org>
Run-TryBot: Robert Griesemer <g...@golang.org>
TryBot-Result: Go Bot <go...@golang.org>
Reviewed-by: Robert Findley <rfin...@google.com>
---
M src/cmd/compile/internal/types2/decl.go
M src/cmd/compile/internal/types2/testdata/check/typeparams.go2
M src/cmd/compile/internal/types2/testdata/examples/constraints.go2
M src/cmd/compile/internal/types2/testdata/examples/types.go2
M src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
M src/cmd/compile/internal/types2/typexpr.go
M src/go/types/decl.go
M src/go/types/testdata/check/typeparams.go2
M src/go/types/testdata/examples/constraints.go2
M src/go/types/testdata/examples/types.go2
M src/go/types/testdata/fixedbugs/issue47818.go2
M src/go/types/typexpr.go
M test/fixedbugs/issue14652.go
M test/typeparam/tparam1.go
14 files changed, 49 insertions(+), 80 deletions(-)

diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index 1926d93..994c19e 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -625,13 +625,7 @@
// 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
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
index 765d561..69b6925 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
@@ -6,11 +6,9 @@

// 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 }
diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2
index f40d18c..ecc75c1 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2
@@ -33,20 +33,20 @@
_ 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 }
diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2
index 97c9951..55b1b0d 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/types.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2
@@ -114,7 +114,7 @@
}

// 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 @@
}

// 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]]() {}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
index 5334695..166cc68 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
@@ -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]{}
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 5aacb94..7f75a96 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -38,16 +38,10 @@
}
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)

diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index 0fdcfa8..061fc01 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -668,27 +668,18 @@
*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)
}

diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2
index 57b6d7a..bfacb3e 100644
--- a/src/go/types/testdata/check/typeparams.go2
+++ b/src/go/types/testdata/check/typeparams.go2
@@ -6,11 +6,9 @@

// 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 }
diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2
index f40d18c..ecc75c1 100644
--- a/src/go/types/testdata/examples/constraints.go2
+++ b/src/go/types/testdata/examples/constraints.go2
@@ -33,20 +33,20 @@
_ 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 }
diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2
index 6f6f95e..2e6eeb2 100644
--- a/src/go/types/testdata/examples/types.go2
+++ b/src/go/types/testdata/examples/types.go2
@@ -114,7 +114,7 @@
}

// 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 @@
}

// 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]]() {}
diff --git a/src/go/types/testdata/fixedbugs/issue47818.go2 b/src/go/types/testdata/fixedbugs/issue47818.go2
index 68c6a94..e3e5a99 100644
--- a/src/go/types/testdata/fixedbugs/issue47818.go2
+++ b/src/go/types/testdata/fixedbugs/issue47818.go2
@@ -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]{}
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index a1b8bae..505c639 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -36,16 +36,10 @@
}
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)

diff --git a/test/fixedbugs/issue14652.go b/test/fixedbugs/issue14652.go
index 14a2239..586663b 100644
--- a/test/fixedbugs/issue14652.go
+++ b/test/fixedbugs/issue14652.go
@@ -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
diff --git a/test/typeparam/tparam1.go b/test/typeparam/tparam1.go
index 698877a..3b4260c 100644
--- a/test/typeparam/tparam1.go
+++ b/test/typeparam/tparam1.go
@@ -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 @@
_[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

To view, visit change 351456. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I85590c6094b07c3e494fef319e3a38d0217cf6f0
Gerrit-Change-Number: 351456
Gerrit-PatchSet: 5
Gerrit-Owner: Robert Griesemer <g...@golang.org>
Gerrit-Reviewer: Go Bot <go...@golang.org>
Gerrit-Reviewer: Robert Findley <rfin...@google.com>
Gerrit-Reviewer: Robert Griesemer <g...@golang.org>
Gerrit-MessageType: merged
Reply all
Reply to author
Forward
0 new messages