diff options
| author | Dan Scales <danscales@google.com> | 2022-01-18 12:55:17 -0800 |
|---|---|---|
| committer | Dan Scales <danscales@google.com> | 2022-01-21 00:39:55 +0000 |
| commit | 32636cd1ffc6cd9ef81d09b8320d2aaad4a21117 (patch) | |
| tree | 76ef77c1dc05ceb0eef3b7c279d3f0b971e4b100 /test/typeparam | |
| parent | 2c2e08144f79d8746384c2a483bf03532dc0c443 (diff) | |
| download | go-32636cd1ffc6cd9ef81d09b8320d2aaad4a21117.tar.xz | |
cmd/compile: make sure multiple blank typeparams remain unique
In a method declaration "func (f *Foo[_, _]) String() string { ... }",
the two blank typeparams have the same name, but our current design with
types1 needs unique names for type params. Similarly, for export/import,
we need unique names to keep the type params straight in generic types
and connect the proper type param with the proper constraint. We make
blank type params unique by changing them to $1, $2, etc in noder.typ0()
via typecheck.TparamExportName(). We then revert $<num> back to _ during
type2 import via typecheck.TparamName(). We similarly revert
during gcimporter import. We don't need/want to revert in the types1
importer, since we want unique names for type params.
Rob Findley has made a similar change to x/tools (and we tried to make
the source code changes similar for the gcimporter and types2 importer
changes).
Fixes #50419
Change-Id: I855cc3d90d06bcf59541ed0c879e9a0e4ede45bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/379194
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Dan Scales <danscales@google.com>
Diffstat (limited to 'test/typeparam')
| -rw-r--r-- | test/typeparam/issue50419.go | 33 | ||||
| -rw-r--r-- | test/typeparam/issue50481.go | 21 | ||||
| -rw-r--r-- | test/typeparam/issue50481b.dir/b.go | 16 | ||||
| -rw-r--r-- | test/typeparam/issue50481b.dir/main.go | 23 | ||||
| -rw-r--r-- | test/typeparam/issue50481b.go | 7 | ||||
| -rw-r--r-- | test/typeparam/issue50481c.dir/a.go | 30 | ||||
| -rw-r--r-- | test/typeparam/issue50481c.dir/main.go | 18 | ||||
| -rw-r--r-- | test/typeparam/issue50481c.go | 7 | ||||
| -rw-r--r-- | test/typeparam/issue50481c.out | 1 |
9 files changed, 135 insertions, 21 deletions
diff --git a/test/typeparam/issue50419.go b/test/typeparam/issue50419.go new file mode 100644 index 0000000000..ff9d08d089 --- /dev/null +++ b/test/typeparam/issue50419.go @@ -0,0 +1,33 @@ +// run -gcflags=-G=3 + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that type substitution works correctly even for a method of a generic type +// that has multiple blank type params. + +package main + +import ( + "fmt" +) + +func main() { + foo := &Foo[string, int]{ + valueA: "i am a string", + valueB: 123, + } + if got, want := fmt.Sprintln(foo), "i am a string 123\n"; got != want { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } +} + +type Foo[T1 any, T2 any] struct { + valueA T1 + valueB T2 +} + +func (f *Foo[_, _]) String() string { + return fmt.Sprintf("%v %v", f.valueA, f.valueB) +} diff --git a/test/typeparam/issue50481.go b/test/typeparam/issue50481.go deleted file mode 100644 index 23038356bf..0000000000 --- a/test/typeparam/issue50481.go +++ /dev/null @@ -1,21 +0,0 @@ -// errorcheck -G=3 - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package p - -type _[_ any] struct{} -type _[_, _ any] struct{} // ERROR "cannot have multiple blank type parameters" -type _[_, _, _ any] struct{} // ERROR "cannot have multiple blank type parameters" -type _[a, _, b, _, c, _ any] struct{} // ERROR "cannot have multiple blank type parameters" - -func _[_ any]() {} -func _[_, _ any]() {} // ERROR "cannot have multiple blank type parameters" -func _[_, _, _ any]() {} // ERROR "cannot have multiple blank type parameters" -func _[a, _, b, _, c, _ any]() {} // ERROR "cannot have multiple blank type parameters" - -type S[P1, P2 any] struct{} - -func (_ S[_, _]) m() {} // this is ok diff --git a/test/typeparam/issue50481b.dir/b.go b/test/typeparam/issue50481b.dir/b.go new file mode 100644 index 0000000000..d458357c51 --- /dev/null +++ b/test/typeparam/issue50481b.dir/b.go @@ -0,0 +1,16 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "fmt" + +type Foo[T1 ~string, T2 ~int] struct { + ValueA T1 + ValueB T2 +} + +func (f *Foo[_, _]) String() string { + return fmt.Sprintf("%v %v", f.ValueA, f.ValueB) +} diff --git a/test/typeparam/issue50481b.dir/main.go b/test/typeparam/issue50481b.dir/main.go new file mode 100644 index 0000000000..909d6e43fd --- /dev/null +++ b/test/typeparam/issue50481b.dir/main.go @@ -0,0 +1,23 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that type substitution and export/import works correctly even for a method of +// a generic type that has multiple blank type params. + +package main + +import ( + "b" + "fmt" +) + +func main() { + foo := &b.Foo[string, int]{ + ValueA: "i am a string", + ValueB: 123, + } + if got, want := fmt.Sprintln(foo), "i am a string 123\n"; got != want { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } +} diff --git a/test/typeparam/issue50481b.go b/test/typeparam/issue50481b.go new file mode 100644 index 0000000000..642f4bf49f --- /dev/null +++ b/test/typeparam/issue50481b.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/issue50481c.dir/a.go b/test/typeparam/issue50481c.dir/a.go new file mode 100644 index 0000000000..384ba23f98 --- /dev/null +++ b/test/typeparam/issue50481c.dir/a.go @@ -0,0 +1,30 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type A interface { + int | int64 +} + +type B interface { + string +} + +type C interface { + String() string +} + +type Myint int + +func (i Myint) String() string { + return "aa" +} + +type T[P A, _ C, _ B] int + +func (v T[P, Q, R]) test() { + var r Q + r.String() +} diff --git a/test/typeparam/issue50481c.dir/main.go b/test/typeparam/issue50481c.dir/main.go new file mode 100644 index 0000000000..4661976034 --- /dev/null +++ b/test/typeparam/issue50481c.dir/main.go @@ -0,0 +1,18 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that type substitution works and export/import works correctly even for a +// generic type that has multiple blank type params. + +package main + +import ( + "a" + "fmt" +) + +func main() { + var x a.T[int, a.Myint, string] + fmt.Printf("%v\n", x) +} diff --git a/test/typeparam/issue50481c.go b/test/typeparam/issue50481c.go new file mode 100644 index 0000000000..642f4bf49f --- /dev/null +++ b/test/typeparam/issue50481c.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/issue50481c.out b/test/typeparam/issue50481c.out new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/test/typeparam/issue50481c.out @@ -0,0 +1 @@ +0 |
