[dev.typeparams] cmd/compile/internal/syntax: add type parameter tests

The file endings are not .go so that gofmt leaves these files alone.
They are also not .src to distinguish them from regular go source tests.

Change-Id: I741f5c037bad1ea9d6f7fda3673487d0be631350
Reviewed-on: https://go-review.googlesource.com/c/go/+/261219
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Robert Griesemer 2020-10-10 17:02:15 -07:00
parent b627988b0c
commit 7668f02dec
10 changed files with 1341 additions and 2 deletions

View file

@ -29,7 +29,24 @@ func TestParse(t *testing.T) {
ParseFile(*src_, func(err error) { t.Error(err) }, nil, 0)
}
func TestStdLib(t *testing.T) {
func TestParseGo2(t *testing.T) {
dir := filepath.Join(testdata, "go2")
list, err := ioutil.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
for _, fi := range list {
name := fi.Name()
if !fi.IsDir() && !strings.HasPrefix(name, ".") {
ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics)
}
}
}
func TestStdLib(t *testing.T) { testStdLib(t, 0) }
func TestStdLibGeneric(t *testing.T) { testStdLib(t, AllowGenerics) }
func testStdLib(t *testing.T, mode Mode) {
if testing.Short() {
t.Skip("skipping test in short mode")
}
@ -68,7 +85,7 @@ func TestStdLib(t *testing.T) {
if debug {
fmt.Printf("parsing %s\n", filename)
}
ast, err := ParseFile(filename, nil, nil, 0)
ast, err := ParseFile(filename, nil, nil, mode)
if err != nil {
t.Error(err)
return

View file

@ -0,0 +1,62 @@
package chans
import "runtime"
// Ranger returns a Sender and a Receiver. The Receiver provides a
// Next method to retrieve values. The Sender provides a Send method
// to send values and a Close method to stop sending values. The Next
// method indicates when the Sender has been closed, and the Send
// method indicates when the Receiver has been freed.
//
// This is a convenient way to exit a goroutine sending values when
// the receiver stops reading them.
func Ranger[T any]() (*Sender[T], *Receiver[T]) {
c := make(chan T)
d := make(chan bool)
s := &Sender[T]{values: c, done: d}
r := &Receiver[T]{values: c, done: d}
runtime.SetFinalizer(r, r.finalize)
return s, r
}
// A sender is used to send values to a Receiver.
type Sender[T any] struct {
values chan<- T
done <-chan bool
}
// Send sends a value to the receiver. It returns whether any more
// values may be sent; if it returns false the value was not sent.
func (s *Sender[T]) Send(v T) bool {
select {
case s.values <- v:
return true
case <-s.done:
return false
}
}
// Close tells the receiver that no more values will arrive.
// After Close is called, the Sender may no longer be used.
func (s *Sender[T]) Close() {
close(s.values)
}
// A Receiver receives values from a Sender.
type Receiver[T any] struct {
values <-chan T
done chan<- bool
}
// Next returns the next value from the channel. The bool result
// indicates whether the value is valid, or whether the Sender has
// been closed and no more values will be received.
func (r *Receiver[T]) Next() (T, bool) {
v, ok := <-r.values
return v, ok
}
// finalize is a finalizer for the receiver.
func (r *Receiver[T]) finalize() {
close(r.done)
}

View file

@ -0,0 +1,83 @@
// Copyright 2019 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 linalg
import "math"
// Numeric is type bound that matches any numeric type.
// It would likely be in a constraints package in the standard library.
type Numeric interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
complex64, complex128
}
func DotProduct[T Numeric](s1, s2 []T) T {
if len(s1) != len(s2) {
panic("DotProduct: slices of unequal length")
}
var r T
for i := range s1 {
r += s1[i] * s2[i]
}
return r
}
// NumericAbs matches numeric types with an Abs method.
type NumericAbs[T any] interface {
Numeric
Abs() T
}
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func AbsDifference[T NumericAbs[T]](a, b T) T {
d := a - b
return d.Abs()
}
// OrderedNumeric is a type bound that matches numeric types that support the < operator.
type OrderedNumeric interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64
}
// Complex is a type bound that matches the two complex types, which do not have a < operator.
type Complex interface {
type complex64, complex128
}
// OrderedAbs is a helper type that defines an Abs method for
// ordered numeric types.
type OrderedAbs[T OrderedNumeric] T
func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
if a < 0 {
return -a
}
return a
}
// ComplexAbs is a helper type that defines an Abs method for
// complex types.
type ComplexAbs[T Complex] T
func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
r := float64(real(a))
i := float64(imag(a))
d := math.Sqrt(r * r + i * i)
return ComplexAbs[T](complex(d, 0))
}
func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
}
func ComplexAbsDifference[T Complex](a, b T) T {
return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
}

View file

@ -0,0 +1,113 @@
// Copyright 2019 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 orderedmap provides an ordered map, implemented as a binary tree.
package orderedmap
// TODO(gri) fix imports for tests
import "chans" // ERROR could not import
// Map is an ordered map.
type Map[K, V any] struct {
root *node[K, V]
compare func(K, K) int
}
// node is the type of a node in the binary tree.
type node[K, V any] struct {
key K
val V
left, right *node[K, V]
}
// New returns a new map.
func New[K, V any](compare func(K, K) int) *Map[K, V] {
return &Map[K, V]{compare: compare}
}
// find looks up key in the map, and returns either a pointer
// to the node holding key, or a pointer to the location where
// such a node would go.
func (m *Map[K, V]) find(key K) **node[K, V] {
pn := &m.root
for *pn != nil {
switch cmp := m.compare(key, (*pn).key); {
case cmp < 0:
pn = &(*pn).left
case cmp > 0:
pn = &(*pn).right
default:
return pn
}
}
return pn
}
// Insert inserts a new key/value into the map.
// If the key is already present, the value is replaced.
// Returns true if this is a new key, false if already present.
func (m *Map[K, V]) Insert(key K, val V) bool {
pn := m.find(key)
if *pn != nil {
(*pn).val = val
return false
}
*pn = &node[K, V]{key: key, val: val}
return true
}
// Find returns the value associated with a key, or zero if not present.
// The found result reports whether the key was found.
func (m *Map[K, V]) Find(key K) (V, bool) {
pn := m.find(key)
if *pn == nil {
var zero V // see the discussion of zero values, above
return zero, false
}
return (*pn).val, true
}
// keyValue is a pair of key and value used when iterating.
type keyValue[K, V any] struct {
key K
val V
}
// InOrder returns an iterator that does an in-order traversal of the map.
func (m *Map[K, V]) InOrder() *Iterator[K, V] {
sender, receiver := chans.Ranger[keyValue[K, V]]()
var f func(*node[K, V]) bool
f = func(n *node[K, V]) bool {
if n == nil {
return true
}
// Stop sending values if sender.Send returns false,
// meaning that nothing is listening at the receiver end.
return f(n.left) &&
sender.Send(keyValue[K, V]{n.key, n.val}) &&
f(n.right)
}
go func() {
f(m.root)
sender.Close()
}()
return &Iterator[K, V]{receiver}
}
// Iterator is used to iterate over the map.
type Iterator[K, V any] struct {
r *chans.Receiver[keyValue[K, V]]
}
// Next returns the next key and value pair, and a boolean indicating
// whether they are valid or whether we have reached the end.
func (it *Iterator[K, V]) Next() (K, V, bool) {
keyval, ok := it.r.Next()
if !ok {
var zerok K
var zerov V
return zerok, zerov, false
}
return keyval.key, keyval.val, true
}

View file

@ -0,0 +1,146 @@
// Copyright 2019 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.
// This file is like map.go2, but instead if importing chans, it contains
// the necessary functionality at the end of the file.
// Package orderedmap provides an ordered map, implemented as a binary tree.
package orderedmap
// Map is an ordered map.
type Map[K, V any] struct {
root *node[K, V]
compare func(K, K) int
}
// node is the type of a node in the binary tree.
type node[K, V any] struct {
key K
val V
left, right *node[K, V]
}
// New returns a new map.
func New[K, V any](compare func(K, K) int) *Map[K, V] {
return &Map[K, V]{compare: compare}
}
// find looks up key in the map, and returns either a pointer
// to the node holding key, or a pointer to the location where
// such a node would go.
func (m *Map[K, V]) find(key K) **node[K, V] {
pn := &m.root
for *pn != nil {
switch cmp := m.compare(key, (*pn).key); {
case cmp < 0:
pn = &(*pn).left
case cmp > 0:
pn = &(*pn).right
default:
return pn
}
}
return pn
}
// Insert inserts a new key/value into the map.
// If the key is already present, the value is replaced.
// Returns true if this is a new key, false if already present.
func (m *Map[K, V]) Insert(key K, val V) bool {
pn := m.find(key)
if *pn != nil {
(*pn).val = val
return false
}
*pn = &node[K, V]{key: key, val: val}
return true
}
// Find returns the value associated with a key, or zero if not present.
// The found result reports whether the key was found.
func (m *Map[K, V]) Find(key K) (V, bool) {
pn := m.find(key)
if *pn == nil {
var zero V // see the discussion of zero values, above
return zero, false
}
return (*pn).val, true
}
// keyValue is a pair of key and value used when iterating.
type keyValue[K, V any] struct {
key K
val V
}
// InOrder returns an iterator that does an in-order traversal of the map.
func (m *Map[K, V]) InOrder() *Iterator[K, V] {
sender, receiver := chans_Ranger[keyValue[K, V]]()
var f func(*node[K, V]) bool
f = func(n *node[K, V]) bool {
if n == nil {
return true
}
// Stop sending values if sender.Send returns false,
// meaning that nothing is listening at the receiver end.
return f(n.left) &&
sender.Send(keyValue[K, V]{n.key, n.val}) &&
f(n.right)
}
go func() {
f(m.root)
sender.Close()
}()
return &Iterator[K, V]{receiver}
}
// Iterator is used to iterate over the map.
type Iterator[K, V any] struct {
r *chans_Receiver[keyValue[K, V]]
}
// Next returns the next key and value pair, and a boolean indicating
// whether they are valid or whether we have reached the end.
func (it *Iterator[K, V]) Next() (K, V, bool) {
keyval, ok := it.r.Next()
if !ok {
var zerok K
var zerov V
return zerok, zerov, false
}
return keyval.key, keyval.val, true
}
// chans
func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T])
// A sender is used to send values to a Receiver.
type chans_Sender[T any] struct {
values chan<- T
done <-chan bool
}
func (s *chans_Sender[T]) Send(v T) bool {
select {
case s.values <- v:
return true
case <-s.done:
return false
}
}
func (s *chans_Sender[T]) Close() {
close(s.values)
}
type chans_Receiver[T any] struct {
values <-chan T
done chan<- bool
}
func (r *chans_Receiver[T]) Next() (T, bool) {
v, ok := <-r.values
return v, ok
}

View file

@ -0,0 +1,68 @@
// Copyright 2019 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 slices implements various slice algorithms.
package slices
// Map turns a []T1 to a []T2 using a mapping function.
func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 {
r := make([]T2, len(s))
for i, v := range s {
r[i] = f(v)
}
return r
}
// Reduce reduces a []T1 to a single value using a reduction function.
func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 {
r := initializer
for _, v := range s {
r = f(r, v)
}
return r
}
// Filter filters values from a slice using a filter function.
func Filter[T any](s []T, f func(T) bool) []T {
var r []T
for _, v := range s {
if f(v) {
r = append(r, v)
}
}
return r
}
// Example uses
func limiter(x int) byte {
switch {
case x < 0:
return 0
default:
return byte(x)
case x > 255:
return 255
}
}
var input = []int{-4, 68954, 7, 44, 0, -555, 6945}
var limited1 = Map[int, byte](input, limiter)
var limited2 = Map(input, limiter) // using type inference
func reducer(x float64, y int) float64 {
return x + float64(y)
}
var reduced1 = Reduce[int, float64](input, 0, reducer)
var reduced2 = Reduce(input, 1i /* ERROR overflows */, reducer) // using type inference
var reduced3 = Reduce(input, 1, reducer) // using type inference
func filter(x int) bool {
return x&1 != 0
}
var filtered1 = Filter[int](input, filter)
var filtered2 = Filter(input, filter) // using type inference

View file

@ -0,0 +1,83 @@
// Copyright 2020 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.
// This file contains basic generic code snippets.
package p
// type parameter lists
type B[P any] struct{}
type _[P interface{}] struct{}
type _[P B] struct{}
type _[P B[P]] struct{}
type _[A, B, C any] struct{}
type _[A, B, C B] struct{}
type _[A, B, C B[A, B, C]] struct{}
type _[A1, A2 B1, A3 B2, A4, A5, A6 B3] struct{}
type _[A interface{}] struct{}
type _[A, B interface{ m() }] struct{}
type _[A, B, C any] struct{}
// in functions
func _[P any]()
func _[P interface{}]()
func _[P B]()
func _[P B[P]]()
// in methods
func (T) _[P any]()
func (T) _[P interface{}]()
func (T) _[P B]()
func (T) _[P B[P]]()
// type instantiations
type _ T[int]
// in expressions
var _ = T[int]{}
// in embedded types
type _ struct{ T[int] }
// interfaces
type _ interface{
m()
type int
}
type _ interface{
type int, float, string
type complex128
underlying(underlying underlying) underlying
}
type _ interface{
T
T[int]
}
// tricky cases
func _(T[P], T[P1, P2])
func _(a [N]T)
type _ struct{
T[P]
T[P1, P2]
f [N]
}
type _ interface{
m()
// generic methods - disabled for now
// m[] /* ERROR empty type parameter list */ ()
// m[ /* ERROR cannot have type parameters */ P any](P)
// instantiated types
// T[] /* ERROR empty type argument list */
T[P]
T[P1, P2]
}

View file

@ -0,0 +1,60 @@
// Copyright 2019 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 myInt int
// Parameterized type declarations
type T1[P any] P
type T2[P any] struct {
f P
g int // int should still be in scope chain
}
type List[P any] []P
// Alias type declarations cannot have type parameters. Syntax error.
// TODO(gri) Disabled for now as we don't check syntax error here.
// type A1[P any] = /* ERROR cannot be alias */ P
// But an alias may refer to a generic, uninstantiated type.
type A2 = List
var _ A2[int]
var _ A2 /* ERROR without instantiation */
type A3 = List[int]
var _ A3
// Parameterized type instantiations
var x int
type _ x /* ERROR not a type */ [int]
type _ int /* ERROR not a generic type */ [int]
type _ myInt /* ERROR not a generic type */ [int]
// TODO(gri) better error messages
type _ T1[int]
type _ T1[x /* ERROR not a type */ ]
type _ T1 /* ERROR got 2 arguments but 1 type parameters */ [int, float32]
var _ T2[int] = T2[int]{}
var _ List[int] = []int{1, 2, 3}
var _ List[[]int] = [][]int{{1, 2, 3}}
var _ List[List[List[int]]]
// Parameterized types containing parameterized types
type T3[P any] List[P]
var _ T3[int] = T3[int](List[int]{1, 2, 3})
// Self-recursive generic types are not permitted
type self1[P any] self1 /* ERROR illegal cycle */ [P]
type self2[P any] *self2[P] // this is ok

View file

@ -0,0 +1,256 @@
// Copyright 2019 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 List[E any] []E
var _ List[List[List[int]]]
var _ List[List[List[int]]] = []List[List[int]]{}
type (
T1[P1 any] struct {
f1 T2[P1, float32]
}
T2[P2, P3 any] struct {
f2 P2
f3 P3
}
)
func _() {
var x1 T1[int]
var x2 T2[int, float32]
x1.f1.f2 = 0
x1.f1 = x2
}
type T3[P any] T1[T2[P, P]]
func _() {
var x1 T3[int]
var x2 T2[int, int]
x1.f1.f2 = x2
}
func f[P any] (x P) List[P] {
return List[P]{x}
}
var (
_ []int = f(0)
_ []float32 = f[float32](10)
_ List[complex128] = f(1i)
_ []List[int] = f(List[int]{})
_ List[List[int]] = []List[int]{}
_ = []List[int]{}
)
// Parameterized types with methods
func (l List[E]) Head() (_ E, _ bool) {
if len(l) > 0 {
return l[0], true
}
return
}
// A test case for instantiating types with other types (extracted from map.go2)
type Pair[K any] struct {
key K
}
type Receiver[T any] struct {
values T
}
type Iterator[K any] struct {
r Receiver[Pair[K]]
}
func Values [T any] (r Receiver[T]) T {
return r.values
}
func (it Iterator[K]) Next() K {
return Values[Pair[K]](it.r).key
}
// A more complex test case testing type bounds (extracted from linalg.go2 and reduced to essence)
type NumericAbs[T any] interface {
Abs() T
}
func AbsDifference[T NumericAbs[T]](x T)
type OrderedAbs[T any] T
func (a OrderedAbs[T]) Abs() OrderedAbs[T]
func OrderedAbsDifference[T any](x T) {
AbsDifference(OrderedAbs[T](x))
}
// same code, reduced to essence
func g[P interface{ m() P }](x P)
type T4[P any] P
func (_ T4[P]) m() T4[P]
func _[Q any](x Q) {
g(T4[Q](x))
}
// Another test case that caused problems in the past
type T5[_ interface { a() }, _ interface{}] struct{}
type A[P any] struct{ x P }
func (_ A[P]) a() {}
var _ T5[A[int], int]
// Invoking methods with parameterized receiver types uses
// type inference to determine the actual type arguments matching
// the receiver type parameters from the actual receiver argument.
// Go does implicit address-taking and dereferenciation depending
// on the actual receiver and the method's receiver type. To make
// type inference work, the type-checker matches "pointer-ness"
// of the actual receiver and the method's receiver type.
// The following code tests this mechanism.
type R1[A any] struct{}
func (_ R1[A]) vm()
func (_ *R1[A]) pm()
func _[T any](r R1[T], p *R1[T]) {
r.vm()
r.pm()
p.vm()
p.pm()
}
type R2[A, B any] struct{}
func (_ R2[A, B]) vm()
func (_ *R2[A, B]) pm()
func _[T any](r R2[T, int], p *R2[string, T]) {
r.vm()
r.pm()
p.vm()
p.pm()
}
// An interface can (explicitly) declare at most one type list.
type _ interface {
m0()
type int, string, bool
type /* ERROR multiple type lists */ float32, float64
m1()
m2()
type /* ERROR multiple type lists */ complex64, complex128
type /* ERROR multiple type lists */ rune
}
// Interface type lists may contain each type at most once.
// (If there are multiple lists, we assume the author intended
// for them to be all in a single list, and we report the error
// as well.)
type _ interface {
type int, int /* ERROR duplicate type int */
type /* ERROR multiple type lists */ int /* ERROR duplicate type int */
}
type _ interface {
type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int}
}
// Interface type lists can contain any type, incl. *Named types.
// Verify that we use the underlying type to compute the operational type.
type MyInt int
func add1[T interface{type MyInt}](x T) T {
return x + 1
}
type MyString string
func double[T interface{type MyInt, MyString}](x T) T {
return x + x
}
// Embedding of interfaces with type lists leads to interfaces
// with type lists that are the intersection of the embedded
// type lists.
type E0 interface {
type int, bool, string
}
type E1 interface {
type int, float64, string
}
type E2 interface {
type float64
}
type I0 interface {
E0
}
func f0[T I0]()
var _ = f0[int]
var _ = f0[bool]
var _ = f0[string]
var _ = f0[float64 /* ERROR does not satisfy I0 */ ]
type I01 interface {
E0
E1
}
func f01[T I01]()
var _ = f01[int]
var _ = f01[bool /* ERROR does not satisfy I0 */ ]
var _ = f01[string]
var _ = f01[float64 /* ERROR does not satisfy I0 */ ]
type I012 interface {
E0
E1
E2
}
func f012[T I012]()
var _ = f012[int /* ERROR does not satisfy I012 */ ]
var _ = f012[bool /* ERROR does not satisfy I012 */ ]
var _ = f012[string /* ERROR does not satisfy I012 */ ]
var _ = f012[float64 /* ERROR does not satisfy I012 */ ]
type I12 interface {
E1
E2
}
func f12[T I12]()
var _ = f12[int /* ERROR does not satisfy I12 */ ]
var _ = f12[bool /* ERROR does not satisfy I12 */ ]
var _ = f12[string /* ERROR does not satisfy I12 */ ]
var _ = f12[float64]
type I0_ interface {
E0
type int
}
func f0_[T I0_]()
var _ = f0_[int]
var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ]

View file

@ -0,0 +1,451 @@
// Copyright 2018 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
// import "io" // for type assertion tests
// The predeclared identifier "any" is only visible as a constraint
// in a type parameter list.
var _ any // ERROR undeclared
func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) {
var _ any /* ERROR undeclared */
}
func identity[T any](x T) T { return x }
func _[_ any](x int) int
func _[T any](T /* ERROR redeclared */ T)()
func _[T, T /* ERROR redeclared */ any]()
func reverse[T any](list []T) []T {
rlist := make([]T, len(list))
i := len(list)
for _, x := range list {
i--
rlist[i] = x
}
return rlist
}
var _ = reverse /* ERROR cannot use generic function reverse */
var _ = reverse[int, float32 /* ERROR got 2 type arguments */ ] ([]int{1, 2, 3})
var _ = reverse[int]([ /* ERROR cannot use */ ]float32{1, 2, 3})
var f = reverse[chan int]
var _ = f(0 /* ERROR cannot convert 0 .* to \[\]chan int */ )
func swap[A, B any](a A, b B) (B, A) { return b, a }
var _ = swap /* ERROR single value is expected */ [int, float32](1, 2)
var f32, i = swap[int, float32](swap(float32, int)(1, 2))
var _ float32 = f32
var _ int = i
func swapswap[A, B any](a A, b B) (A, B) {
return swap[B, A](b, a)
}
type F[A, B any] func(A, B) (B, A)
func min[T interface{ type int }](x, y T) T {
if x < y {
return x
}
return y
}
func _[T interface{type int, float32}](x, y T) bool { return x < y }
func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y }
func _[T interface{type int, float32, bool}](x, y T) bool { return x /* ERROR cannot compare */ < y }
func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y }
func _[T C2[T]](x, y T) bool { return x < y }
type C1[T any] interface{}
type C2[T any] interface{ type int, float32 }
func new[T any]() *T {
var x T
return &x
}
var _ = new /* ERROR cannot use generic function new */
var _ *int = new[int]()
func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable
func f1[T1 any](struct{T1}) int
var _ = f1(int)(struct{T1}{})
type T1 = int
func f2[t1 any](struct{t1; x float32}) int
var _ = f2(t1)(struct{t1; x float32}{})
type t1 = int
func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int
var _ = f3[int, rune, bool](1, struct{x rune}{}, nil)
// indexing
func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _[T interface{ type string }] (x T, i int) { _ = x[i] }
func _[T interface{ type []int }] (x T, i int) { _ = x[i] }
func _[T interface{ type [10]int, *[20]int, map[string]int }] (x T, i int) { _ = x[i] }
func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] }
func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
// slicing
// TODO(gri) implement this
func _[T interface{ type string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] }
// len/cap built-ins
func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) }
func _[T interface{ type int }](x T) { _ = len(x /* ERROR invalid argument */ ) }
func _[T interface{ type string, []byte, int }](x T) { _ = len(x /* ERROR invalid argument */ ) }
func _[T interface{ type string }](x T) { _ = len(x) }
func _[T interface{ type [10]int }](x T) { _ = len(x) }
func _[T interface{ type []byte }](x T) { _ = len(x) }
func _[T interface{ type map[int]int }](x T) { _ = len(x) }
func _[T interface{ type chan int }](x T) { _ = len(x) }
func _[T interface{ type string, []byte, chan int }](x T) { _ = len(x) }
func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ type int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ type string, []byte, int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ type string }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ type [10]int }](x T) { _ = cap(x) }
func _[T interface{ type []byte }](x T) { _ = cap(x) }
func _[T interface{ type map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) }
func _[T interface{ type chan int }](x T) { _ = cap(x) }
func _[T interface{ type []byte, chan int }](x T) { _ = cap(x) }
// range iteration
func _[T interface{}](x T) {
for range x /* ERROR cannot range */ {}
}
func _[T interface{ type string, []string }](x T) {
for range x {}
for i := range x { _ = i }
for i, _ := range x { _ = i }
for i, e := range x /* ERROR must have the same element type */ { _ = i }
for _, e := range x /* ERROR must have the same element type */ {}
var e rune
_ = e
for _, (e) = range x /* ERROR must have the same element type */ {}
}
func _[T interface{ type string, []rune, map[int]rune }](x T) {
for _, e := range x { _ = e }
for i, e := range x { _ = i; _ = e }
}
func _[T interface{ type string, []rune, map[string]rune }](x T) {
for _, e := range x { _ = e }
for i, e := range x /* ERROR must have the same key type */ { _ = e }
}
func _[T interface{ type string, chan int }](x T) {
for range x {}
for i := range x { _ = i }
for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value
}
func _[T interface{ type string, chan<-int }](x T) {
for i := range x /* ERROR send-only channel */ { _ = i }
}
// type inference checks
var _ = new() /* ERROR cannot infer T */
func f4[A, B, C any](A, B) C
var _ = f4(1, 2) /* ERROR cannot infer C */
var _ = f4[int, float32, complex128](1, 2)
func f5[A, B, C any](A, []*B, struct{f []C}) int
var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{})
var _ = f5(0, nil, struct{f []complex128}{}) // ERROR cannot infer
var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{})
func f6[A any](A, []A) int
var _ = f6(0, nil)
func f6nil[A any](A) int
var _ = f6nil(nil) // ERROR cannot infer
// type inference with variadic functions
func f7[T any](...T) T
var _ int = f7() /* ERROR cannot infer T */
var _ int = f7(1)
var _ int = f7(1, 2)
var _ int = f7([]int{}...)
var _ int = f7 /* ERROR cannot use */ ([]float64{}...)
var _ float64 = f7([]float64{}...)
var _ = f7[float64](1, 2.3)
var _ = f7(float64(1), 2.3)
var _ = f7(1, 2.3 /* ERROR does not match */ )
var _ = f7(1.2, 3 /* ERROR does not match */ )
func f8[A, B any](A, B, ...B) int
var _ = f8(1) /* ERROR not enough arguments */
var _ = f8(1, 2.3)
var _ = f8(1, 2.3, 3.4, 4.5)
var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ )
var _ = f8(int, float64)(1, 2.3, 3.4, 4)
var _ = f8(int, float64)(0, 0, nil...) // test case for #18268
// init functions cannot have type parameters
func init() {}
func init[/* ERROR func init must have no type parameters */ _ any]() {}
func init[/* ERROR func init must have no type parameters */ P any]() {}
type T struct {}
func (T) m1() {}
// The type checker accepts method type parameters if configured accordingly.
func (T) m2[_ any]() {}
func (T) m3[P any]() {}
// type inference across parameterized types
type S1[P any] struct { f P }
func f9[P any](x S1[P])
func _() {
f9[int](S1[int]{42})
f9(S1[int]{42})
}
type S2[A, B, C any] struct{}
func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool])
func _[P any]() {
f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{})
f10(S2[int, int, string]{}, S2[int, float32, bool]{})
f10(S2[P, int, P]{}, S2[P, float32, bool]{})
}
// corner case for type inference
// (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic)
func f11[T any]()
func _() {
f11[int]()
}
// the previous example was extracted from
func f12[T interface{m() T}]()
type A[T any] T
func (a A[T]) m() A[T]
func _[T any]() {
f12(A[T])()
}
// method expressions
func (_ S1[P]) m()
func _() {
m := S1[int].m
m(struct { f int }{42})
}
func _[T any] (x T) {
m := S1[T].m
m(S1[T]{x})
}
// type parameters in methods (generalization)
type R0 struct{}
func (R0) _[T any](x T)
func (R0 /* ERROR invalid receiver */ ) _[R0 any]() // scope of type parameters starts at "func"
type R1[A, B any] struct{}
func (_ R1[A, B]) m0(A, B)
func (_ R1[A, B]) m1[T any](A, B, T) T
func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B)
func _() {
var r R1[int, string]
r.m1[rune](42, "foo", 'a')
r.m1[rune](42, "foo", 1.2 /* ERROR truncated to rune */)
r.m1(42, "foo", 1.2) // using type inference
var _ float64 = r.m1(42, "foo", 1.2)
}
type I1[A any] interface {
m1(A)
}
var _ I1[int] = r1[int]{}
type r1[T any] struct{}
func (_ r1[T]) m1(T)
type I2[A, B any] interface {
m1(A)
m2(A) B
}
var _ I2[int, float32] = R2[int, float32]{}
type R2[P, Q any] struct{}
func (_ R2[X, Y]) m1(X)
func (_ R2[X, Y]) m2(X) Y
// type assertions and type switches over generic types
// NOTE: These are currently disabled because it's unclear what the correct
// approach is, and one can always work around by assigning the variable to
// an interface first.
// // ReadByte1 corresponds to the ReadByte example in the draft design.
// func ReadByte1[T io.Reader](r T) (byte, error) {
// if br, ok := r.(io.ByteReader); ok {
// return br.ReadByte()
// }
// var b [1]byte
// _, err := r.Read(b[:])
// return b[0], err
// }
//
// // ReadBytes2 is like ReadByte1 but uses a type switch instead.
// func ReadByte2[T io.Reader](r T) (byte, error) {
// switch br := r.(type) {
// case io.ByteReader:
// return br.ReadByte()
// }
// var b [1]byte
// _, err := r.Read(b[:])
// return b[0], err
// }
//
// // type assertions and type switches over generic types are strict
// type I3 interface {
// m(int)
// }
//
// type I4 interface {
// m() int // different signature from I3.m
// }
//
// func _[T I3](x I3, p T) {
// // type assertions and type switches over interfaces are not strict
// _ = x.(I4)
// switch x.(type) {
// case I4:
// }
//
// // type assertions and type switches over generic types are strict
// _ = p /* ERROR cannot have dynamic type I4 */.(I4)
// switch p.(type) {
// case I4 /* ERROR cannot have dynamic type I4 */ :
// }
// }
// type assertions and type switches over generic types lead to errors for now
func _[T any](x T) {
_ = x /* ERROR not an interface */ .(int)
switch x /* ERROR not an interface */ .(type) {
}
// work-around
var t interface{} = x
_ = t.(int)
switch t.(type) {
}
}
func _[T interface{type int}](x T) {
_ = x /* ERROR not an interface */ .(int)
switch x /* ERROR not an interface */ .(type) {
}
// work-around
var t interface{} = x
_ = t.(int)
switch t.(type) {
}
}
// error messages related to type bounds mention those bounds
type C[P any] interface{}
func _[P C[P]] (x P) {
x.m /* ERROR x.m undefined */ ()
}
type I interface {}
func _[P I] (x P) {
x.m /* ERROR interface I has no method m */ ()
}
func _[P interface{}] (x P) {
x.m /* ERROR type bound for P has no method m */ ()
}
func _[P any] (x P) {
x.m /* ERROR type bound for P has no method m */ ()
}
// automatic distinguishing between array and generic types
// NOTE: Disabled when using unified parameter list syntax.
/*
const P = 10
type A1 [P]byte
func _(a A1) {
assert(len(a) == 10)
}
type A2 [P]struct{
f [P]byte
}
func _(a A2) {
assert(len(a) == 10)
assert(len(a[0].f) == 10)
}
type A3 [P]func(x [P]A3)
func _(a A3) {
assert(len(a) == 10)
}
type T2[P] struct{ P }
var _ T2[int]
type T3[P] func(P)
var _ T3[int]
*/