From 6237e441bca7f3429abde413bf71c7840fec9bf2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 10 Jun 2021 11:26:08 -0400 Subject: [PATCH] [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 Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 2 ++ src/go/types/api_test.go | 2 +- src/go/types/api_typeparams_test.go | 14 +++++++------- src/go/types/interface.go | 10 +++++++++- src/go/types/testdata/examples/constraints.go2 | 12 ++++++++++++ src/go/types/typestring_test.go | 1 - 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index 30f8ded744..d3a95bc991 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -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 diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 5a2d4a4ca3..6a7218d90f 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -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 { diff --git a/src/go/types/api_typeparams_test.go b/src/go/types/api_typeparams_test.go index 4a2adce9a2..d9117b8412 100644 --- a/src/go/types/api_typeparams_test.go +++ b/src/go/types/api_typeparams_test.go @@ -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`, diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 9b4d080c81..947e76dc17 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -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 diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index f6291ccf7d..61992e4c2a 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -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} diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index 0e35a3dbf1..f02c0d9c18 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -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}"), -- 2.50.0