1
0
mirror of https://github.com/golang/go synced 2024-11-26 17:07:09 -07:00

[dev.typeparams] cmd/compile/internal/types2: add Config.AllowTypeLists to control type list handling

Eventually the flag should not be set anymore, but we set it in the
compiler until all tests have been converted.

Also, convert some more types2 tests to use the type set notation.

Change-Id: I616599a3473451ab75d67272016b2bd3de6835af
Reviewed-on: https://go-review.googlesource.com/c/go/+/324571
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-06-02 17:50:47 -07:00
parent 10d6b36ca3
commit 95c618e99a
6 changed files with 36 additions and 11 deletions

View File

@ -38,6 +38,7 @@ func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Pack
GoVersion: base.Flag.Lang, GoVersion: base.Flag.Lang,
IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode
CompilerErrorMessages: true, // use error strings matching existing compiler errors CompilerErrorMessages: true, // use error strings matching existing compiler errors
AllowTypeLists: true, // remove this line once all tests use type set syntax
Error: func(err error) { Error: func(err error) {
terr := err.(types2.Error) terr := err.(types2.Error)
base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg) base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg)

View File

@ -125,6 +125,12 @@ type Config struct {
// TODO(gri) Consolidate error messages and remove this flag. // TODO(gri) Consolidate error messages and remove this flag.
CompilerErrorMessages bool CompilerErrorMessages bool
// If AllowTypeLists is set, the type list syntax is permitted
// in an interface in addition to the type set syntax.
// TODO(gri) Remove once type lists are no longer supported by
// the parser.
AllowTypeLists bool
// If go115UsesCgo is set, the type checker expects the // If go115UsesCgo is set, the type checker expects the
// _cgo_gotypes.go file generated by running cmd/cgo to be // _cgo_gotypes.go file generated by running cmd/cgo to be
// provided as a package source file. Qualified identifiers // provided as a package source file. Qualified identifiers

View File

@ -345,7 +345,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]`}, {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`},
// issue 45096 // issue 45096
{genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`},
} }
for _, test := range tests { for _, test := range tests {
@ -454,38 +454,38 @@ func TestInferredInfo(t *testing.T) {
// `func(float64)`, // `func(float64)`,
// }, // },
{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`, `f`,
[]string{`string`, `*string`}, []string{`string`, `*string`},
`func(x 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`, `f`,
[]string{`int`, `*int`}, []string{`int`, `*int`},
`func(x []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`, `f`,
[]string{`int`, `chan<- int`}, []string{`int`, `chan<- int`},
`func(x []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`, `f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`}, []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func(x []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`, `f`,
[]string{`string`, `*string`}, []string{`string`, `*string`},
`func() 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`, `f`,
[]string{`int`, `chan<- int`}, []string{`int`, `chan<- int`},
`func() []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`, `f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`}, []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func() []int`, `func() []int`,

View File

@ -34,18 +34,25 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
continue // ignore continue // ignore
} }
// TODO(gri) Remove type list handling once the parser doesn't accept type lists anymore.
if name == "type" { if name == "type" {
// Report an error for the first type list per interface
// if we don't allow type lists, but continue.
if !check.conf.AllowTypeLists && tlist == nil {
check.softErrorf(f.Name, "use generalized embedding syntax instead of a type list")
}
// For now, collect all type list entries as if it // For now, collect all type list entries as if it
// were a single union, where each union element is // were a single union, where each union element is
// of the form ~T. // of the form ~T.
// TODO(gri) remove once we disallow type lists
op := new(syntax.Operation) op := new(syntax.Operation)
// We should also set the position (but there is no setter); // We should also set the position (but there is no setter);
// we don't care because this code will eventually go away. // we don't care because this code will eventually go away.
op.Op = syntax.Tilde op.Op = syntax.Tilde
op.X = f.Type op.X = f.Type
tlist = append(tlist, op) tlist = append(tlist, op)
if tname != nil && tname != f.Name { // Report an error if we have multiple type lists in an
// interface, but only if they are permitted in the first place.
if check.conf.AllowTypeLists && tname != nil && tname != f.Name {
check.error(f.Name, "cannot have multiple type lists in an interface") check.error(f.Name, "cannot have multiple type lists in an interface")
} }
tname = f.Name tname = f.Name

View File

@ -6,6 +6,18 @@
package p 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 ( type (
// Arbitrary types may be embedded like interfaces. // Arbitrary types may be embedded like interfaces.
_ interface{int} _ interface{int}

View File

@ -91,7 +91,6 @@ var independentTestTypes = []testEntry{
dup("interface{}"), dup("interface{}"),
dup("interface{m()}"), dup("interface{m()}"),
dup(`interface{String() string; m(int) float32}`), 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}"),
dup("interface{int|~float32|~complex128}"), dup("interface{int|~float32|~complex128}"),