[dev.typeparams] go/types: disallow type list handling

This is a port of CL 324571 to go/types, though type list handling is
guarded by a const rather than a config option.

Change-Id: I91c940fead048980603e0bb56fcc896dbef4f94c
Reviewed-on: https://go-review.googlesource.com/c/go/+/326683
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Rob Findley 2021-06-10 11:26:08 -04:00 committed by Robert Findley
parent 6e50f4f111
commit 6237e441bc
6 changed files with 31 additions and 10 deletions

View file

@ -34,6 +34,8 @@ import (
"go/token"
)
const allowTypeLists = false
// An Error describes a type-checking error; it implements the error interface.
// A "soft" error is an error that still permits a valid interpretation of a
// package (such as "unused variable"); "hard" errors may lead to unpredictable

View file

@ -349,7 +349,7 @@ func TestTypesInfo(t *testing.T) {
{genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`},
// issue 45096
{genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`},
{genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T₁`},
}
for _, test := range tests {

View file

@ -45,38 +45,38 @@ func TestInferredInfo(t *testing.T) {
`func(float64, *byte, ...[]byte)`,
},
{genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
{genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`,
`f`,
[]string{`string`, `*string`},
`func(x string)`,
},
{genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
{genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`,
`f`,
[]string{`int`, `*int`},
`func(x []int)`,
},
{genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
{genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
`f`,
[]string{`int`, `chan<- int`},
`func(x []int)`,
},
{genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
{genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
`f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func(x []int)`,
},
{genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
{genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`,
`f`,
[]string{`string`, `*string`},
`func() string`,
},
{genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
{genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
`f`,
[]string{`int`, `chan<- int`},
`func() []int`,
},
{genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
{genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
`f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func() []int`,

View file

@ -34,7 +34,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
continue // ignore
}
// TODO(rfindley) Remove type list handling once the parser doesn't accept type lists anymore.
if name.Name == "type" {
// Report an error for the first type list per interface
// if we don't allow type lists, but continue.
if !allowTypeLists && tlist == nil {
check.softErrorf(name, _Todo, "use generalized embedding syntax instead of a type list")
}
// For now, collect all type list entries as if it
// were a single union, where each union element is
// of the form ~T.
@ -43,7 +49,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
op.Op = token.TILDE
op.X = f.Type
tlist = append(tlist, op)
if tname != nil && tname != name {
// Report an error if we have multiple type lists in an
// interface, but only if they are permitted in the first place.
if allowTypeLists && tname != nil && tname != name {
check.errorf(name, _Todo, "cannot have multiple type lists in an interface")
}
tname = name

View file

@ -6,6 +6,18 @@
package p
type (
// Type lists are processed as unions but an error is reported.
// TODO(gri) remove this once the parser doesn't accept type lists anymore.
_ interface{
type /* ERROR use generalized embedding syntax instead of a type list */ int
}
_ interface{
type /* ERROR use generalized embedding syntax instead of a type list */ int
type float32
}
)
type (
// Arbitrary types may be embedded like interfaces.
_ interface{int}

View file

@ -95,7 +95,6 @@ var independentTestTypes = []testEntry{
dup("interface{}"),
dup("interface{m()}"),
dup(`interface{String() string; m(int) float32}`),
{"interface{type int, float32, complex128}", "interface{~int|~float32|~complex128}"},
dup("interface{int|float32|complex128}"),
dup("interface{int|~float32|~complex128}"),