// A generic (non-instantiated) function value cannot be assigned to a variable.
if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
- check.errorf(x, 0, "cannot use generic function %s without instantiation in %s", x, context)
+ check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context)
}
// spec: "If a left-hand side is the blank identifier, any typed or
case _Alignof:
// unsafe.Alignof(x T) uintptr
if asTypeParam(x.typ) != nil {
- check.invalidOp(call, 0, "unsafe.Alignof undefined for %s", x)
+ check.invalidOp(call, _Todo, "unsafe.Alignof undefined for %s", x)
return
}
check.assignment(x, nil, "argument to unsafe.Alignof")
case _Sizeof:
// unsafe.Sizeof(x T) uintptr
if asTypeParam(x.typ) != nil {
- check.invalidOp(call, 0, "unsafe.Sizeof undefined for %s", x)
+ check.invalidOp(call, _Todo, "unsafe.Sizeof undefined for %s", x)
return
}
check.assignment(x, nil, "argument to unsafe.Sizeof")
if t := asInterface(T); t != nil {
check.completeInterface(token.NoPos, t)
if t.IsConstraint() {
- check.errorf(call, 0, "cannot use interface %s in conversion (contains type list or is comparable)", T)
+ check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T)
break
}
}
// check number of type arguments
if n > len(sig.tparams) {
- check.errorf(args[n-1], 0, "got %d type arguments but want %d", n, len(sig.tparams))
+ check.errorf(args[n-1], _Todo, "got %d type arguments but want %d", n, len(sig.tparams))
x.mode = invalid
x.expr = orig
return expression
assert(targs[failed] == nil)
tpar := sig.tparams[failed]
ppos := check.fset.Position(tpar.pos).String()
- check.errorf(inNode(call, call.Rparen), 0, "cannot infer %s (%s) (%s)", tpar.name, ppos, targs)
+ check.errorf(inNode(call, call.Rparen), _Todo, "cannot infer %s (%s) (%s)", tpar.name, ppos, targs)
return
}
}
// instantiatedOperand reports an error of x is an uninstantiated (generic) type and sets x.typ to Typ[Invalid].
func (check *Checker) instantiatedOperand(x *operand) {
if x.mode == typexpr && isGeneric(x.typ) {
- check.errorf(x, 0, "cannot use generic type %s without instantiation", x.typ)
+ check.errorf(x, _Todo, "cannot use generic type %s without instantiation", x.typ)
x.typ = Typ[Invalid]
}
}
return
}
-func parseFiles(t *testing.T, filenames []string) ([]*ast.File, []error) {
+func parseFiles(t *testing.T, filenames []string, mode parser.Mode) ([]*ast.File, []error) {
var files []*ast.File
var errlist []error
for _, filename := range filenames {
- file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
+ file, err := parser.ParseFile(fset, filename, nil, mode)
if file == nil {
t.Fatalf("%s: %s", filename, err)
}
}
func checkFiles(t *testing.T, sources []string) {
+ if len(sources) == 0 {
+ t.Fatal("no source files")
+ }
+
+ mode := parser.AllErrors
+ if strings.HasSuffix(sources[0], ".go2") {
+ mode |= parser.ParseTypeParams
+ }
+
// parse files and collect parser errors
- files, errlist := parseFiles(t, sources)
+ files, errlist := parseFiles(t, sources, mode)
pkgName := "<no package>"
if len(files) > 0 {
// typecheck and collect typechecker errors
var conf Config
- // TODO(rFindley) parse generics when given a .go2 suffix.
// special case for importC.src
if len(sources) == 1 && strings.HasSuffix(sources[0], "importC.src") {
checkFiles(t, strings.Split(*testFiles, " "))
}
-func TestTestdata(t *testing.T) { DefPredeclaredTestFuncs(); testDir(t, "testdata") }
-
-// TODO(rFindley) add go2 examples.
-// func TestExamples(t *testing.T) { testDir(t, "examples") }
-
+func TestTestdata(t *testing.T) { DefPredeclaredTestFuncs(); testDir(t, "testdata") }
+func TestExamples(t *testing.T) { testDir(t, "examples") }
func TestFixedbugs(t *testing.T) { testDir(t, "fixedbugs") }
func testDir(t *testing.T, dir string) {
return
}
- for count, fi := range fis {
+ for _, fi := range fis {
path := filepath.Join(dir, fi.Name())
// if fi is a directory, its files make up a single package
+ var files []string
if fi.IsDir() {
- if testing.Verbose() {
- fmt.Printf("%3d %s\n", count, path)
- }
fis, err := ioutil.ReadDir(path)
if err != nil {
t.Error(err)
continue
}
- files := make([]string, len(fis))
+ files = make([]string, len(fis))
for i, fi := range fis {
// if fi is a directory, checkFiles below will complain
files[i] = filepath.Join(path, fi.Name())
fmt.Printf("\t%s\n", files[i])
}
}
- checkFiles(t, files)
- continue
- }
-
- // otherwise, fi is a stand-alone file
- if testing.Verbose() {
- fmt.Printf("%3d %s\n", count, path)
+ } else {
+ files = []string{path}
}
- checkFiles(t, []string{path})
+ t.Run(filepath.Base(path), func(t *testing.T) {
+ checkFiles(t, files)
+ })
}
}
setBoundAt(index+i, bound)
}
} else if bound != Typ[Invalid] {
- check.errorf(f.Type, 0, "%s is not an interface", bound)
+ check.errorf(f.Type, _Todo, "%s is not an interface", bound)
}
next:
// return i
// }
_InvalidGo
+
+ // _Todo is a placeholder for error codes that have not been decided.
+ // TODO(rFindley) remove this error code after deciding on errors for generics code.
+ _Todo
)
--- /dev/null
+// 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 shows some examples of type-parameterized functions.
+
+package p
+
+// Reverse is a generic function that takes a []T argument and
+// reverses that slice in place.
+func Reverse[T any](list []T) {
+ i := 0
+ j := len(list)-1
+ for i < j {
+ list[i], list[j] = list[j], list[i]
+ i++
+ j--
+ }
+}
+
+func _() {
+ // Reverse can be called with an explicit type argument.
+ Reverse[int](nil)
+ Reverse[string]([]string{"foo", "bar"})
+ Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
+
+ // Since the type parameter is used for an incoming argument,
+ // it can be inferred from the provided argument's type.
+ Reverse([]string{"foo", "bar"})
+ Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
+
+ // But the incoming argument must have a type, even if it's a
+ // default type. An untyped nil won't work.
+ // Reverse(nil) // this won't type-check
+
+ // A typed nil will work, though.
+ Reverse([]int(nil))
+}
+
+// Certain functions, such as the built-in `new` could be written using
+// type parameters.
+func new[T any]() *T {
+ var x T
+ return &x
+}
+
+// When calling our own `new`, we need to pass the type parameter
+// explicitly since there is no (value) argument from which the
+// result type could be inferred. We don't try to infer the
+// result type from the assignment to keep things simple and
+// easy to understand.
+var _ = new[int]()
+var _ *float64 = new(float64)() // the result type is indeed *float64
+
+// A function may have multiple type parameters, of course.
+func foo[A, B, C any](a A, b []B, c *C) B {
+ // do something here
+ return b[0]
+}
+
+// As before, we can pass type parameters explicitly.
+var s = foo[int, string, float64](1, []string{"first"}, new(float64)())
+
+// Or we can use type inference.
+var _ float64 = foo(42, []float64{1.0}, &s)
+
+// Type inference works in a straight-forward manner even
+// for variadic functions.
+func variadic[A, B any](A, B, ...B) int
+
+// var _ = variadic(1) // ERROR not enough arguments
+var _ = variadic(1, 2.3)
+var _ = variadic(1, 2.3, 3.4, 4.5)
+var _ = variadic[int, float64](1, 2.3, 3.4, 4)
+
+// Type inference also works in recursive function calls where
+// the inferred type is the type parameter of the caller.
+func f1[T any](x T) {
+ f1(x)
+}
+
+func f2a[T any](x, y T) {
+ f2a(x, y)
+}
+
+func f2b[T any](x, y T) {
+ f2b(y, x)
+}
+
+func g2a[P, Q any](x P, y Q) {
+ g2a(x, y)
+}
+
+func g2b[P, Q any](x P, y Q) {
+ g2b(y, x)
+}
+
+// Here's an example of a recursive function call with variadic
+// arguments and type inference inferring the type parameter of
+// the caller (i.e., itself).
+func max[T interface{ type int }](x ...T) T {
+ var x0 T
+ if len(x) > 0 {
+ x0 = x[0]
+ }
+ if len(x) > 1 {
+ x1 := max(x[1:]...)
+ if x1 > x0 {
+ return x1
+ }
+ }
+ return x0
+}
+
+// When inferring channel types, the channel direction is ignored
+// for the purpose of type inference. Once the type has been in-
+// fered, the usual parameter passing rules are applied.
+// Thus even if a type can be inferred successfully, the function
+// call may not be valid.
+
+func fboth[T any](chan T)
+func frecv[T any](<-chan T)
+func fsend[T any](chan<- T)
+
+func _() {
+ var both chan int
+ var recv <-chan int
+ var send chan<-int
+
+ fboth(both)
+ fboth(recv /* ERROR cannot use */ )
+ fboth(send /* ERROR cannot use */ )
+
+ frecv(both)
+ frecv(recv)
+ frecv(send /* ERROR cannot use */ )
+
+ fsend(both)
+ fsend(recv /* ERROR cannot use */)
+ fsend(send)
+}
+
+func ffboth[T any](func(chan T))
+func ffrecv[T any](func(<-chan T))
+func ffsend[T any](func(chan<- T))
+
+func _() {
+ var both func(chan int)
+ var recv func(<-chan int)
+ var send func(chan<- int)
+
+ ffboth(both)
+ ffboth(recv /* ERROR cannot use */ )
+ ffboth(send /* ERROR cannot use */ )
+
+ ffrecv(both /* ERROR cannot use */ )
+ ffrecv(recv)
+ ffrecv(send /* ERROR cannot use */ )
+
+ ffsend(both /* ERROR cannot use */ )
+ ffsend(recv /* ERROR cannot use */ )
+ ffsend(send)
+}
+
+// When inferring elements of unnamed composite parameter types,
+// if the arguments are defined types, use their underlying types.
+// Even though the matching types are not exactly structurally the
+// same (one is a type literal, the other a named type), because
+// assignment is permitted, parameter passing is permitted as well,
+// so type inference should be able to handle these cases well.
+
+func g1[T any]([]T)
+func g2[T any]([]T, T)
+func g3[T any](*T, ...T)
+
+func _() {
+ type intSlize []int
+ g1([]int{})
+ g1(intSlize{})
+ g2(nil, 0)
+
+ type myString string
+ var s1 string
+ g3(nil, "1", myString("2"), "3")
+ g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3")
+
+ type myStruct struct{x int}
+ var s2 myStruct
+ g3(nil, struct{x int}{}, myStruct{})
+ g3(&s2, struct{x int}{}, myStruct{})
+ g3(nil, myStruct{}, struct{x int}{})
+ g3(&s2, myStruct{}, struct{x int}{})
+}
+
+// Here's a realistic example.
+
+func append[T any](s []T, t ...T) []T
+
+func _() {
+ var f func()
+ type Funcs []func()
+ var funcs Funcs
+ _ = append(funcs, f)
+}
+
+// Generic type declarations cannot have empty type parameter lists
+// (that would indicate a slice type). Thus, generic functions cannot
+// have empty type parameter lists, either. This is a syntax error.
+
+func h[] /* ERROR empty type parameter list */ ()
+
+func _() {
+ h[] /* ERROR operand */ ()
+}
--- /dev/null
+// 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 shows some examples of methods on type-parameterized types.
+
+package p
+
+// Parameterized types may have methods.
+type T1[A any] struct{ a A }
+
+// When declaring a method for a parameterized type, the "instantiated"
+// receiver type acts as an implicit declaration of the type parameters
+// for the receiver type. In the example below, method m1 on type T1 has
+// the receiver type T1[A] which declares the type parameter A for use
+// with this method. That is, within the method m1, A stands for the
+// actual type argument provided to an instantiated T1.
+func (t T1[A]) m1() A { return t.a }
+
+// For instance, if T1 is instantiated with the type int, the type
+// parameter A in m1 assumes that type (int) as well and we can write
+// code like this:
+var x T1[int]
+var _ int = x.m1()
+
+// Because the type parameter provided to a parameterized receiver type
+// is declared through that receiver declaration, it must be an identifier.
+// It cannot possibly be some other type because the receiver type is not
+// instantiated with concrete types, it is standing for the parameterized
+// receiver type.
+func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {}
+
+// Note that using what looks like a predeclared identifier, say int,
+// as type parameter in this situation is deceptive and considered bad
+// style. In m3 below, int is the name of the local receiver type parameter
+// and it shadows the predeclared identifier int which then cannot be used
+// anymore as expected.
+// This is no different from locally redelaring a predeclared identifier
+// and usually should be avoided. There are some notable exceptions; e.g.,
+// sometimes it makes sense to use the identifier "copy" which happens to
+// also be the name of a predeclared built-in function.
+func (t T1[int]) m3() { var _ int = 42 /* ERROR cannot use 42 .* as int */ }
+
+// The names of the type parameters used in a parameterized receiver
+// type don't have to match the type parameter names in the the declaration
+// of the type used for the receiver. In our example, even though T1 is
+// declared with type parameter named A, methods using that receiver type
+// are free to use their own name for that type parameter. That is, the
+// name of type parameters is always local to the declaration where they
+// are introduced. In our example we can write a method m2 and use the
+// name X instead of A for the type parameter w/o any difference.
+func (t T1[X]) m4() X { return t.a }
+
+// If the receiver type is parameterized, type parameters must always be
+// provided: this simply follows from the general rule that a parameterized
+// type must be instantiated before it can be used. A method receiver
+// declaration using a parameterized receiver type is no exception. It is
+// simply that such receiver type expressions perform two tasks simultaneously:
+// they declare the (local) type parameters and then use them to instantiate
+// the receiver type. Forgetting to provide a type parameter leads to an error.
+func (t T1 /* ERROR generic type .* without instantiation */ ) m5() {}
+
+// However, sometimes we don't need the type parameter, and thus it is
+// inconvenient to have to choose a name. Since the receiver type expression
+// serves as a declaration for its type parameters, we are free to choose the
+// blank identifier:
+func (t T1[_]) m6() {}
+
+// Naturally, these rules apply to any number of type parameters on the receiver
+// type. Here are some more complex examples.
+type T2[A, B, C any] struct {
+ a A
+ b B
+ c C
+}
+
+// Naming of the type parameters is local and has no semantic impact:
+func (t T2[A, B, C]) m1() (A, B, C) { return t.a, t.b, t.c }
+func (t T2[C, B, A]) m2() (C, B, A) { return t.a, t.b, t.c }
+func (t T2[X, Y, Z]) m3() (X, Y, Z) { return t.a, t.b, t.c }
+
+// Type parameters may be left blank if they are not needed:
+func (t T2[A, _, C]) m4() (A, C) { return t.a, t.c }
+func (t T2[_, _, X]) m5() X { return t.c }
+func (t T2[_, _, _]) m6() {}
+
+// As usual, blank names may be used for any object which we don't care about
+// using later. For instance, we may write an unnamed method with a receiver
+// that cannot be accessed:
+func (_ T2[_, _, _]) _() int { return 42 }
+
+// Because a receiver parameter list is simply a parameter list, we can
+// leave the receiver argument away for receiver types.
+type T0 struct{}
+func (T0) _() {}
+func (T1[A]) _() {}
--- /dev/null
+// 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 shows some examples of generic types.
+
+package p
+
+// List is just what it says - a slice of E elements.
+type List[E any] []E
+
+// A generic (parameterized) type must always be instantiated
+// before it can be used to designate the type of a variable
+// (including a struct field, or function parameter); though
+// for the latter cases, the provided type may be another type
+// parameter. So:
+var _ List[byte] = []byte{}
+
+// A generic binary tree might be declared as follows.
+type Tree[E any] struct {
+ left, right *Tree[E]
+ payload E
+}
+
+// A simple instantiation of Tree:
+var root1 Tree[int]
+
+// The actual type parameter provided may be a generic type itself:
+var root2 Tree[List[int]]
+
+// A couple of more complex examples.
+// We don't need extra parentheses around the element type of the slices on
+// the right (unlike when we use ()'s rather than []'s for type parameters).
+var _ List[List[int]] = []List[int]{}
+var _ List[List[List[Tree[int]]]] = []List[List[Tree[int]]]{}
+
+// Type parameters act like type aliases when used in generic types
+// in the sense that we can "emulate" a specific type instantiation
+// with type aliases.
+type T1[P any] struct {
+ f P
+}
+
+type T2[P any] struct {
+ f struct {
+ g P
+ }
+}
+
+var x1 T1[struct{ g int }]
+var x2 T2[int]
+
+func _() {
+ // This assignment is invalid because the types of x1, x2 are T1(...)
+ // and T2(...) respectively, which are two different defined types.
+ x1 = x2 // ERROR assignment
+
+ // This assignment is valid because the types of x1.f and x2.f are
+ // both struct { g int }; the type parameters act like type aliases
+ // and their actual names don't come into play here.
+ x1.f = x2.f
+}
+
+// We can verify this behavior using type aliases instead:
+type T1a struct {
+ f A1
+}
+type A1 = struct { g int }
+
+type T2a struct {
+ f struct {
+ g A2
+ }
+}
+type A2 = int
+
+var x1a T1a
+var x2a T2a
+
+func _() {
+ x1a = x2a // ERROR assignment
+ x1a.f = x2a.f
+}
+
+// Another interesting corner case are generic types that don't use
+// their type arguments. For instance:
+type T[P any] struct{}
+
+var xint T[int]
+var xbool T[bool]
+
+// Are these two variables of the same type? After all, their underlying
+// types are identical. We consider them to be different because each type
+// instantiation creates a new named type, in this case T<int> and T<bool>
+// even if their underlying types are identical. This is sensible because
+// we might still have methods that have different signatures or behave
+// differently depending on the type arguments, and thus we can't possibly
+// consider such types identical. Consequently:
+func _() {
+ xint = xbool // ERROR assignment
+}
+
+// Generic types cannot be used without instantiation.
+var _ T // ERROR cannot use generic type T
+
+// In type context, generic (parameterized) types cannot be parenthesized before
+// being instantiated. See also NOTES entry from 12/4/2019.
+var _ (T /* ERROR cannot use generic type T */ )[ /* ERROR expected ';' */ int]
+
+// All types may be parameterized, including interfaces.
+type I1[T any] interface{
+ m1(T)
+}
+
+// Generic interfaces may be embedded as one would expect.
+type I2 interface {
+ I1(int) // method!
+ I1[string] // embedded I1
+}
+
+func _() {
+ var x I2
+ x.I1(0)
+ x.m1("foo")
+}
+
+type I0 interface {
+ m0()
+}
+
+type I3 interface {
+ I0
+ I1[bool]
+ m(string)
+}
+
+func _() {
+ var x I3
+ x.m0()
+ x.m1(true)
+ x.m("foo")
+}
+
+// We accept parenthesized embedded struct fields so we can distinguish between
+// a named field with a parenthesized type foo (T) and an embedded parameterized
+// type (foo(T)), similarly to interace embedding.
+// They still need to be valid embedded types after the parentheses are stripped
+// (i.e., in contrast to interfaces, we cannot embed a struct literal). The name
+// of the embedded field is derived as before, after stripping parentheses.
+// (7/14/2020: See comment above. We probably will revert this generalized ability
+// if we go with [] for type parameters.)
+type _ struct {
+ int8
+ *int16
+ *List[int]
+
+ int8 /* ERROR int8 redeclared */
+ * /* ERROR List redeclared */ List[int]
+}
+
+// It's possible to declare local types whose underlying types
+// are type parameters. As with ordinary type definitions, the
+// types underlying properties are "inherited" but the methods
+// are not.
+func _[T interface{ m(); type int }]() {
+ type L T
+ var x L
+
+ // m is not defined on L (it is not "inherited" from
+ // its underlying type).
+ x.m /* ERROR x.m undefined */ ()
+
+ // But the properties of T, such that as that it supports
+ // the operations of the types given by its type bound,
+ // are also the properties of L.
+ x++
+ _ = x - x
+
+ // On the other hand, if we define a local alias for T,
+ // that alias stands for T as expected.
+ type A = T
+ var y A
+ y.m()
+ _ = y < 0
+}
+
+// As a special case, an explicit type argument may be omitted
+// from a type parameter bound if the type bound expects exactly
+// one type argument. In that case, the type argument is the
+// respective type parameter to which the type bound applies.
+// Note: We may not permit this syntactic sugar at first.
+// Note: This is now disabled. All examples below are adjusted.
+type Adder[T any] interface {
+ Add(T) T
+}
+
+// We don't need to explicitly instantiate the Adder bound
+// if we have exactly one type parameter.
+func Sum[T Adder[T]](list []T) T {
+ var sum T
+ for _, x := range list {
+ sum = sum.Add(x)
+ }
+ return sum
+}
+
+// Valid and invalid variations.
+type B0 interface {}
+type B1[_ any] interface{}
+type B2[_, _ any] interface{}
+
+func _[T1 B0]()
+func _[T1 B1[T1]]()
+func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]()
+
+func _[T1, T2 B0]()
+func _[T1 B1[T1], T2 B1[T2]]()
+func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]()
+
+func _[T1 B0, T2 B1[T2]]() // here B1 applies to T2
+
+// When the type argument is left away, the type bound is
+// instantiated for each type parameter with that type
+// parameter.
+// Note: We may not permit this syntactic sugar at first.
+func _[A Adder[A], B Adder[B], C Adder[A]]() {
+ var a A // A's type bound is Adder[A]
+ a = a.Add(a)
+ var b B // B's type bound is Adder[B]
+ b = b.Add(b)
+ var c C // C's type bound is Adder[A]
+ a = c.Add(a)
+}
+
+// The type of variables (incl. parameters and return values) cannot
+// be an interface with type constraints or be/embed comparable.
+type I interface {
+ type int
+}
+
+var (
+ _ interface /* ERROR contains type constraints */ {type int}
+ _ I /* ERROR contains type constraints */
+)
+
+func _(I /* ERROR contains type constraints */ )
+func _(x, y, z I /* ERROR contains type constraints */ )
+func _() I /* ERROR contains type constraints */
+
+func _() {
+ var _ I /* ERROR contains type constraints */
+}
+
+type C interface {
+ comparable
+}
+
+var _ comparable /* ERROR comparable */
+var _ C /* ERROR comparable */
+
+func _(_ comparable /* ERROR comparable */ , _ C /* ERROR comparable */ )
+
+func _() {
+ var _ comparable /* ERROR comparable */
+ var _ C /* ERROR comparable */
+}
--- /dev/null
+// 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.
+
+// Examples adjusted to match new [T any] syntax for type parameters.
+// Also, previously permitted empty type parameter lists and instantiations
+// are now syntax errors.
+
+package p
+
+// crash 1
+type nt1[_ any]interface{g /* ERROR undeclared name */ }
+type ph1[e nt1[e],g(d /* ERROR undeclared name */ )]s /* ERROR undeclared name */
+func(*ph1[e,e /* ERROR redeclared */ ])h(d /* ERROR undeclared name */ )
+
+// crash 2
+// Disabled: empty []'s are now syntax errors. This example leads to too many follow-on errors.
+// type Numeric2 interface{t2 /* ERROR not a type */ }
+// func t2[T Numeric2](s[]T){0 /* ERROR not a type */ []{s /* ERROR cannot index */ [0][0]}}
+
+// crash 3
+type t3 *interface{ t3.p /* ERROR no field or method p */ }
+
+// crash 4
+type Numeric4 interface{t4 /* ERROR not a type */ }
+func t4[T Numeric4](s[]T){if( /* ERROR non-boolean */ 0){*s /* ERROR cannot indirect */ [0]}}
+
+// crash 7
+type foo7 interface { bar() }
+type x7[A any] struct{ foo7 }
+func main7() { var _ foo7 = x7[int]{} }
+
+// crash 8
+type foo8[A any] interface { type A }
+func bar8[A foo8[A]](a A) {}
+func main8() {}
+
+// crash 9
+type foo9[A any] interface { type foo9 /* ERROR interface contains type constraints */ [A] }
+func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) }
+
+// crash 12
+var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len)]c /* ERROR undeclared */ /* ERROR undeclared */
+
+// crash 15
+func y15() { var a /* ERROR declared but not used */ interface{ p() } = G15[string]{} }
+type G15[X any] s /* ERROR undeclared name */
+func (G15 /* ERROR generic type .* without instantiation */ ) p()
+
+// crash 16
+type Foo16[T any] r16 /* ERROR not a type */
+func r16[T any]() Foo16[Foo16[T]]
+
+// crash 17
+type Y17 interface{ c() }
+type Z17 interface {
+ c() Y17
+ Y17 /* ERROR duplicate method */
+}
+func F17[T Z17](T)
+
+// crash 18
+type o18[T any] []func(_ o18[[]_ /* ERROR cannot use _ */ ])
+
+// crash 19
+type Z19 [][[]Z19{}[0][0]]c19 /* ERROR undeclared */
+
+// crash 20
+type Z20 /* ERROR illegal cycle */ interface{ Z20 }
+func F20[t Z20]() { F20(t /* ERROR invalid composite literal type */ {}) }
+
+// crash 21
+type Z21 /* ERROR illegal cycle */ interface{ Z21 }
+func F21[T Z21]() { ( /* ERROR not used */ F21[Z21]) }
+
+// crash 24
+type T24[P any] P
+func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() }
+
+// crash 25
+type T25[A any] int
+func (t T25[A]) m1() {}
+var x T25 /* ERROR without instantiation */ .m1
+
+// crash 26
+type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any]() }
+func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ /* ERROR missing method */ [] /* ERROR operand */ }
+
+// crash 27
+func e27[T any]() interface{ x27 /* ERROR not a type */ }
+func x27() { e27() /* ERROR cannot infer T */ }
--- /dev/null
+// 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.
+
+package p
+
+type T[_ any] struct {}
+
+func (T /* ERROR instantiation */ ) m()
+
+func _() {
+ var x interface { m() }
+ x = T[int]{}
+ _ = x
+}
--- /dev/null
+// 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.
+
+package p
+
+import "fmt"
+
+// Minimal test case.
+func _[T interface{type T}](x T) T{
+ return x
+}
+
+// Test case from issue.
+type constr[T any] interface {
+ type T
+}
+
+func Print[T constr[T]](s []T) {
+ for _, v := range s {
+ fmt.Print(v)
+ }
+}
+
+func f() {
+ Print([]string{"Hello, ", "playground\n"})
+}
--- /dev/null
+// 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.
+
+package p
+
+type Number interface {
+ int /* ERROR int is not an interface */
+ float64 /* ERROR float64 is not an interface */
+}
+
+func Add[T Number](a, b T) T {
+ return a /* ERROR not defined */ + b
+}
--- /dev/null
+// 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.
+
+package p
+
+type T0 interface{
+}
+
+type T1 interface{
+ type int
+}
+
+type T2 interface{
+ comparable
+}
+
+type T3 interface {
+ T0
+ T1
+ T2
+}
+
+func _() {
+ _ = T0(0)
+ _ = T1 /* ERROR cannot use interface T1 in conversion */ (1)
+ _ = T2 /* ERROR cannot use interface T2 in conversion */ (2)
+ _ = T3 /* ERROR cannot use interface T3 in conversion */ (3)
+}
--- /dev/null
+// 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.
+
+package p
+
+// Do not report a duplicate type error for this type list.
+// (Check types after interfaces have been completed.)
+type _ interface {
+ type interface{ Error() string }, interface{ String() string }
+}
--- /dev/null
+// 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.
+
+package p
+
+// A constraint must be an interface; it cannot
+// be a type parameter, for instance.
+func _[A interface{ type interface{} }, B A /* ERROR not an interface */ ]()
--- /dev/null
+// 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.
+
+package p
+
+func f1[T1, T2 any](T1, T2, struct{a T1; b T2})
+func _() {
+ f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{})
+}
+
+// simplified test case from issue
+func f2[T any](_ []T, _ func(T))
+func _() {
+ f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {})
+}
--- /dev/null
+// Copyright 2020 The Go Authors. All rights reserved.\r
+// Use of this source code is governed by a BSD-style\r
+// license that can be found in the LICENSE file.\r
+\r
+package p\r
+\r
+type Optional[T any] struct {}\r
+\r
+func (_ Optional[T]) Val() (T, bool)\r
+\r
+type Box[T any] interface {\r
+ Val() (T, bool)\r
+}\r
+\r
+func f[V interface{}, A, B Box[V]]() {}\r
+\r
+func _() {\r
+ f[int, Optional[int], Optional[int]]()\r
+ // f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]()\r
+}\r
--- /dev/null
+// 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.
+
+package p
+
+func _[T interface{type map[string]int}](x T) {
+ _ = x == nil
+}
+
+// simplified test case from issue
+
+type PathParamsConstraint interface {
+ type map[string]string, []struct{key, value string}
+}
+
+type PathParams[T PathParamsConstraint] struct {
+ t T
+}
+
+func (pp *PathParams[T]) IsNil() bool {
+ return pp.t == nil // this must succeed
+}
--- /dev/null
+// 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.
+
+package p
+
+type T[P any] P
+type A = T
+var x A[int]
+var _ A /* ERROR cannot use generic type */
+
+type B = T[int]
+var y B = x
+var _ B /* ERROR not a generic type */ [int]
+
+// test case from issue
+
+type Vector[T any] []T
+type VectorAlias = Vector
+var v Vector[int]
--- /dev/null
+// 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.
+
+// Check "infinite expansion" cycle errors across instantiated types.
+
+package p
+
+type E0[P any] P
+type E1[P any] *P
+type E2[P any] struct{ P }
+type E3[P any] struct{ *P }
+
+type T0 /* ERROR illegal cycle */ struct {
+ _ E0[T0]
+}
+
+type T0_ /* ERROR illegal cycle */ struct {
+ E0[T0_]
+}
+
+type T1 struct {
+ _ E1[T1]
+}
+
+type T2 /* ERROR illegal cycle */ struct {
+ _ E2[T2]
+}
+
+type T3 struct {
+ _ E3[T3]
+}
+
+// some more complex cases
+
+type T4 /* ERROR illegal cycle */ struct {
+ _ E0[E2[T4]]
+}
+
+type T5 struct {
+ _ E0[E2[E0[E1[E2[[10]T5]]]]]
+}
+
+type T6 /* ERROR illegal cycle */ struct {
+ _ E0[[10]E2[E0[E2[E2[T6]]]]]
+}
+
+type T7 struct {
+ _ E0[[]E2[E0[E2[E2[T6]]]]]
+}
--- /dev/null
+// 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.
+
+package p
+
+type T[P any] interface{
+ P // ERROR P is a type parameter, not an interface
+}
--- /dev/null
+// 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.
+
+package p
+
+type policy[K, V any] interface{}
+type LRU[K, V any] struct{}
+
+func NewCache[K, V any](p policy[K, V])
+
+func _() {
+ var lru LRU[int, string]
+ NewCache[int, string](&lru)
+ NewCache(& /* ERROR does not match policy\[K, V\] \(cannot infer K and V\) */ lru)
+}
--- /dev/null
+// 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.
+
+package p
+
+type (
+ T[_ any] struct{}
+ S[_ any] struct {
+ data T[*T[int]]
+ }
+)
+
+func _() {
+ _ = S[int]{
+ data: T[*T[int]]{},
+ }
+}
+
+// full test case from issue
+
+type (
+ Element[TElem any] struct{}
+
+ entry[K comparable] struct{}
+
+ Cache[K comparable] struct {
+ data map[K]*Element[*entry[K]]
+ }
+)
+
+func _() {
+ _ = Cache[int]{
+ data: make(map[int](*Element[*entry[int]])),
+ }
+}
--- /dev/null
+// 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.
+
+package p
+
+type A[T any] int
+
+func (A[T]) m(A[T])
+
+func f[P interface{m(P)}]()
+
+func _() {
+ _ = f[A[int]]
+}
\ No newline at end of file
--- /dev/null
+// 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.
+
+package p
+
+func _() {
+ NewS() /* ERROR cannot infer T */ .M()
+}
+
+type S struct {}
+
+func NewS[T any]() *S
+
+func (_ *S /* ERROR S is not a generic type */ [T]) M()
\ No newline at end of file
--- /dev/null
+// 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.
+
+package p
+
+func _() {
+ var x interface{}
+ switch t := x.(type) {
+ case S /* ERROR cannot use generic type */ :
+ t.m()
+ }
+}
+
+type S[T any] struct {}
+
+func (_ S[T]) m()
--- /dev/null
+// 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.
+
+package p
+
+import "unsafe"
+
+func _[T any](x T) {
+ _ = unsafe /* ERROR undefined */ .Alignof(x)
+ _ = unsafe /* ERROR undefined */ .Sizeof(x)
+}
--- /dev/null
+// 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.
+
+package p
+
+type T[_ any] int
+
+func f[_ any]()
+func g[_, _ any]()
+
+func _() {
+ _ = f[T /* ERROR without instantiation */ ]
+ _ = g[T /* ERROR without instantiation */ , T /* ERROR without instantiation */ ]
+}
\ No newline at end of file
--- /dev/null
+// 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.
+
+package p
+
+// Test case from issue.
+
+type Nat interface {
+ type Zero, Succ
+}
+
+type Zero struct{}
+type Succ struct{
+ Nat // ERROR interface contains type constraints
+}
+
+// Struct tests.
+
+type I1 interface {
+ comparable
+}
+
+type I2 interface {
+ type int
+}
+
+type I3 interface {
+ I1
+ I2
+}
+
+type _ struct {
+ f I1 // ERROR interface is .* comparable
+}
+
+type _ struct {
+ comparable // ERROR interface is .* comparable
+}
+
+type _ struct{
+ I1 // ERROR interface is .* comparable
+}
+
+type _ struct{
+ I2 // ERROR interface contains type constraints
+}
+
+type _ struct{
+ I3 // ERROR interface contains type constraints
+}
+
+// General composite types.
+
+type (
+ _ [10]I1 // ERROR interface is .* comparable
+ _ [10]I2 // ERROR interface contains type constraints
+
+ _ []I1 // ERROR interface is .* comparable
+ _ []I2 // ERROR interface contains type constraints
+
+ _ *I3 // ERROR interface contains type constraints
+ _ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
+ _ chan I3 // ERROR interface contains type constraints
+ _ func(I1 /* ERROR interface is .* comparable */ )
+ _ func() I2 // ERROR interface contains type constraints
+)
+
+// Other cases.
+
+var _ = [...]I3 /* ERROR interface contains type constraints */ {}
+
+func _(x interface{}) {
+ _ = x.(I3 /* ERROR interface contains type constraints */ )
+}
+
+type T1[_ any] struct{}
+type T3[_, _, _ any] struct{}
+var _ T1[I2 /* ERROR interface contains type constraints */ ]
+var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32]
+
+func f1[_ any]() int
+var _ = f1[I2 /* ERROR interface contains type constraints */ ]()
+func f3[_, _, _ any]() int
+var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]()
+
+func _(x interface{}) {
+ switch x.(type) {
+ case I2 /* ERROR interface contains type constraints */ :
+ }
+}
--- /dev/null
+// 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.
+
+package p
+
+func _[T any](x interface{}){
+ switch x.(type) {
+ case T: // ok to use a type parameter
+ case int:
+ }
+
+ switch x.(type) {
+ case T:
+ case T /* ERROR duplicate case */ :
+ }
+}
+
+type constraint interface {
+ type int
+}
+
+func _[T constraint](x interface{}){
+ switch x.(type) {
+ case T: // ok to use a type parameter even if type list contains int
+ case int:
+ }
+}
+
+func _(x constraint /* ERROR contains type constraints */ ) {
+ switch x /* ERROR contains type constraints */ .(type) {
+ }
+}
}
}
if allFailed {
- check.errorf(arg, 0, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams))
+ check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams))
return
}
}
// TODO(rFindley): pass a positioner here, rather than arg.Pos().
inferred := check.subst(arg.Pos(), tpar, smap)
if inferred != tpar {
- check.errorf(arg, 0, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
+ check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar)
} else {
check.errorf(arg, 0, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar)
}
}
} else {
// method
- if d.decl.Type.TParams != nil {
- check.invalidAST(d.decl.Type.TParams, "method must have no type parameters")
- }
+
+ // TODO(rFindley) earlier versions of this code checked that methods
+ // have no type parameters, but this is checked later
+ // when type checking the function type. Confirm that
+ // we don't need to check tparams here.
+
ptr, recv, _ := check.unpackRecv(d.decl.Recv.List[0].Type, false)
// (Methods with invalid receiver cannot be associated to a type, and
// methods with blank _ names are never found; no need to collect any
case nil:
check.invalidAST(ptyp, "parameterized receiver contains nil parameters")
default:
- check.errorf(arg, 0, "receiver type parameter %s must be an identifier", arg)
+ check.errorf(arg, _Todo, "receiver type parameter %s must be an identifier", arg)
}
if par == nil {
par = &ast.Ident{NamePos: arg.Pos(), Name: "_"}
// the number of supplied types must match the number of type parameters
if len(targs) != len(tparams) {
// TODO(gri) provide better error message
- check.errorf(atPos(pos), 0, "got %d arguments but %d type parameters", len(targs), len(tparams))
+ check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams))
return Typ[Invalid]
}
} else if wrong != nil {
// TODO(gri) This can still report uninstantiated types which makes the error message
// more difficult to read then necessary.
- check.softErrorf(atPos(pos), 0,
+ // TODO(rFindley) should this use parentheses rather than ':' for qualification?
+ check.softErrorf(atPos(pos), _Todo,
"%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s",
targ, tpar.bound, wrong, m,
)
if targ := asTypeParam(targ); targ != nil {
targBound := targ.Bound()
if targBound.allTypes == nil {
- check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
+ check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
break
}
for _, t := range unpackType(targBound.allTypes) {
// Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
if !iface.isSatisfiedBy(targ) {
- check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes)
+ check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes)
break
}
}
--- /dev/null
+// 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 tests built-in calls on generic types.
+
+package builtins
+
+type Bmc interface {
+ type map[rune]string, chan int
+}
+
+type Bms interface {
+ type map[string]int, []int
+}
+
+type Bcs interface {
+ type chan bool, []float64
+}
+
+type Bss interface {
+ type []int, []string
+}
+
+func _[T any] () {
+ _ = make(T /* ERROR invalid argument */ )
+ _ = make(T /* ERROR invalid argument */ , 10)
+ _ = make(T /* ERROR invalid argument */ , 10, 20)
+}
+
+func _[T Bmc] () {
+ _ = make(T)
+ _ = make(T, 10)
+ _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20)
+}
+
+func _[T Bms] () {
+ _ = make /* ERROR expects 2 arguments */ (T)
+ _ = make(T, 10)
+ _ = make /* ERROR expects 2 arguments */ (T, 10, 20)
+}
+
+func _[T Bcs] () {
+ _ = make /* ERROR expects 2 arguments */ (T)
+ _ = make(T, 10)
+ _ = make /* ERROR expects 2 arguments */ (T, 10, 20)
+}
+
+func _[T Bss] () {
+ _ = make /* ERROR expects 2 or 3 arguments */ (T)
+ _ = make(T, 10)
+ _ = make(T, 10, 20)
+}
--- /dev/null
+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)
+}
--- /dev/null
+// 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 regression tests for bugs found.
+
+package p
+
+import "io"
+import "context"
+
+// Interfaces are always comparable (though the comparison may panic at runtime).
+func eql[T comparable](x, y T) bool {
+ return x == y
+}
+
+func _() {
+ var x interface{}
+ var y interface{ m() }
+ eql(x, y /* ERROR does not match */ ) // interfaces of different types
+ eql(x, x)
+ eql(y, y)
+ eql(y, nil)
+ eql(io.Reader)(nil, nil)
+}
+
+// If we have a receiver of pointer type (below: *T) we must ignore
+// the pointer in the implementation of the method lookup because
+// the type bound of T is an interface an pointer to interface types
+// have no methods and then the lookup would fail.
+type C[T any] interface {
+ m()
+}
+
+// using type bound C
+func _[T C[T]](x *T) {
+ x.m()
+}
+
+// using an interface literal as bound
+func _[T interface{ m() }](x *T) {
+ x.m()
+}
+
+// In a generic function body all method calls will be pointer method calls.
+// If necessary, the function body will insert temporary variables, not seen
+// by the user, in order to get an addressable variable to use to call the method.
+// Thus, assume an argument type for a generic function to be the type of addressable
+// values in the generic function when checking if the argument type satisfies the
+// generic function's type bound.
+func f2[_ interface{ m1(); m2() }]()
+
+type T struct{}
+func (T) m1()
+func (*T) m2()
+
+func _() {
+ f2(T /* ERROR wrong method signature */ )()
+ f2(*T)()
+}
+
+// When a type parameter is used as an argument to instantiate a parameterized
+// type with a type list constraint, all of the type argument's types in its
+// bound, but at least one (!), must be in the type list of the bound of the
+// corresponding parameterized type's type parameter.
+type T1[P interface{type uint}] struct{}
+
+func _[P any]() {
+ _ = T1[P /* ERROR P has no type constraints */ ]{}
+}
+
+// This is the original (simplified) program causing the same issue.
+type Unsigned interface {
+ type uint
+}
+
+type T2[U Unsigned] struct {
+ s U
+}
+
+func (u T2[U]) Add1() U {
+ return u.s + 1
+}
+
+func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] {
+ return T2[U /* ERROR U has no type constraints */ ]{}
+}
+
+func _() {
+ u := NewT2[string]()
+ _ = u.Add1()
+}
+
+// When we encounter an instantiated type such as Elem[T] we must
+// not "expand" the instantiation when the type to be instantiated
+// (Elem in this case) is not yet fully set up.
+type Elem[T any] struct {
+ next *Elem[T]
+ list *List[T]
+}
+
+type List[T any] struct {
+ root Elem[T]
+}
+
+func (l *List[T]) Init() {
+ l.root.next = &l.root
+}
+
+// This is the original program causing the same issue.
+type Element2[TElem any] struct {
+ next, prev *Element2[TElem]
+ list *List2[TElem]
+ Value TElem
+}
+
+type List2[TElem any] struct {
+ root Element2[TElem]
+ len int
+}
+
+func (l *List2[TElem]) Init() *List2[TElem] {
+ l.root.next = &l.root
+ l.root.prev = &l.root
+ l.len = 0
+ return l
+}
+
+// Self-recursive instantiations must work correctly.
+type A[P any] struct { _ *A[P] }
+
+type AB[P any] struct { _ *BA[P] }
+type BA[P any] struct { _ *AB[P] }
+
+// And a variation that also caused a problem with an
+// unresolved underlying type.
+type Element3[TElem any] struct {
+ next, prev *Element3[TElem]
+ list *List3[TElem]
+ Value TElem
+}
+
+func (e *Element3[TElem]) Next() *Element3[TElem] {
+ if p := e.next; e.list != nil && p != &e.list.root {
+ return p
+ }
+ return nil
+}
+
+type List3[TElem any] struct {
+ root Element3[TElem]
+ len int
+}
+
+// Infinite generic type declarations must lead to an error.
+type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] }
+type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] }
+
+// The implementation of conversions T(x) between integers and floating-point
+// numbers checks that both T and x have either integer or floating-point
+// type. When the type of T or x is a type parameter, the respective simple
+// predicate disjunction in the implementation was wrong because if a type list
+// contains both an integer and a floating-point type, the type parameter is
+// neither an integer or a floating-point number.
+func convert[T1, T2 interface{type int, uint, float32}](v T1) T2 {
+ return T2(v)
+}
+
+func _() {
+ convert[int, uint](5)
+}
+
+// When testing binary operators, for +, the operand types must either be
+// both numeric, or both strings. The implementation had the same problem
+// with this check as the conversion issue above (issue #39623).
+
+func issue39623[T interface{type int, string}](x, y T) T {
+ return x + y
+}
+
+// Simplified, from https://go2goplay.golang.org/p/efS6x6s-9NI:
+func Sum[T interface{type int, string}](s []T) (sum T) {
+ for _, v := range s {
+ sum += v
+ }
+ return
+}
+
+// Assignability of an unnamed pointer type to a type parameter that
+// has a matching underlying type.
+func _[T interface{}, PT interface{type *T}] (x T) PT {
+ return &x
+}
+
+// Indexing of generic types containing type parameters in their type list:
+func at[T interface{ type []E }, E interface{}](x T, i int) E {
+ return x[i]
+}
+
+// A generic type inside a function acts like a named type. Its underlying
+// type is itself, its "operational type" is defined by the type list in
+// the tybe bound, if any.
+func _[T interface{type int}](x T) {
+ type myint int
+ var _ int = int(x)
+ var _ T = 42
+ var _ T = T(myint(42))
+}
+
+// Indexing a generic type with an array type bound checks length.
+// (Example by mdempsky@.)
+func _[T interface { type [10]int }](x T) {
+ _ = x[9] // ok
+ _ = x[20 /* ERROR out of bounds */ ]
+}
+
+// Pointer indirection of a generic type.
+func _[T interface{ type *int }](p T) int {
+ return *p
+}
+
+// Channel sends and receives on generic types.
+func _[T interface{ type chan int }](ch T) int {
+ ch <- 0
+ return <- ch
+}
+
+// Calling of a generic variable.
+func _[T interface{ type func() }](f T) {
+ f()
+ go f()
+}
+
+// We must compare against the underlying type of type list entries
+// when checking if a constraint is satisfied by a type. The under-
+// lying type of each type list entry must be computed after the
+// interface has been instantiated as its typelist may contain a
+// type parameter that was substituted with a defined type.
+// Test case from an (originally) failing example.
+
+type sliceOf[E any] interface{ type []E }
+
+func append[T interface{}, S sliceOf[T], T2 interface{ type T }](s S, t ...T2) S
+
+var f func()
+var cancelSlice []context.CancelFunc
+var _ = append(context.CancelFunc, []context.CancelFunc, context.CancelFunc)(cancelSlice, f)
+
+// A generic function must be instantiated with a type, not a value.
+
+func g[T any](T) T
+
+var _ = g[int]
+var _ = g[nil /* ERROR is not a type */ ]
+var _ = g(0)
--- /dev/null
+// 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)))
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
+}
\ No newline at end of file
--- /dev/null
+// 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
+
--- /dev/null
+// 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.
+
+package tinferenceB
+
+import "strconv"
+
+type any interface{}
+
+// TODO(rFindley) the below partially applied function types should probably
+// not be permitted (spec question).
+
+func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D)
+func _() {
+ f := f0[string]
+ f("a", "b", "c", "d")
+ f0("a", "b", "c", "d")
+}
+
+func f1[A any, B interface{type A}](A, B)
+func _() {
+ f := f1[int]
+ f(int(0), int(0))
+ f1(int(0), int(0))
+}
+
+func f2[A any, B interface{type []A}](A, B)
+func _() {
+ f := f2[byte]
+ f(byte(0), []byte{})
+ f2(byte(0), []byte{})
+}
+
+func f3[A any, B interface{type C}, C interface{type *A}](A, B, C)
+func _() {
+ f := f3[int]
+ var x int
+ f(x, &x, &x)
+ f3(x, &x, &x)
+}
+
+func f4[A any, B interface{type []C}, C interface{type *A}](A, B, C)
+func _() {
+ f := f4[int]
+ var x int
+ f(x, []*int{}, &x)
+ f4(x, []*int{}, &x)
+}
+
+func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A
+func _() {
+ x := f5(1.2)
+ var _ float64 = x.b
+ var _ float64 = *x.c
+}
+
+func f6[A any, B interface{type struct{f []A}}](B) A
+func _() {
+ x := f6(struct{f []string}{})
+ var _ string = x
+}
+
+// TODO(gri) Need to flag invalid recursive constraints. At the
+// moment these cause infinite recursions and stack overflow.
+// func f7[A interface{type B}, B interface{type A}]()
+
+// More realistic examples
+
+func Double[S interface{ type []E }, E interface{ type int, int8, int16, int32, int64 }](s S) S {
+ r := make(S, len(s))
+ for i, v := range s {
+ r[i] = v + v
+ }
+ return r
+}
+
+type MySlice []int
+
+var _ = Double(MySlice{1})
+
+// From the draft design.
+
+type Setter[B any] interface {
+ Set(string)
+ type *B
+}
+
+func FromStrings[T interface{}, PT Setter[T]](s []string) []T {
+ result := make([]T, len(s))
+ for i, v := range s {
+ // The type of &result[i] is *T which is in the type list
+ // of Setter2, so we can convert it to PT.
+ p := PT(&result[i])
+ // PT has a Set method.
+ p.Set(v)
+ }
+ return result
+}
+
+type Settable int
+
+func (p *Settable) Set(s string) {
+ i, _ := strconv.Atoi(s) // real code should not ignore the error
+ *p = Settable(i)
+}
+
+var _ = FromStrings[Settable]([]string{"1", "2"})
--- /dev/null
+// 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 is meant as "dumping ground" for debugging code.
+
+package p
+
+// fun test case
+type C[P interface{m()}] P
+
+func (r C[P]) m() { r.m() }
+
+func f[T interface{m(); n()}](x T) {
+ y := C[T](x)
+ y.m()
+}
--- /dev/null
+// 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 is meant as "dumping ground" for tests
+// of not yet implemented features. It will grow and
+// shrink over time.
+
+package p
+
+// When using []'s instead of ()'s for type parameters
+// we don't need extra parentheses for some composite
+// literal types.
+type T1[P any] struct{}
+type T2[P, Q any] struct{}
+
+func _() {
+ _ = []T1[int]{} // ok if we use []'s
+ _ = [](T1[int]){}
+ _ = []T2[int, string]{} // ok if we use []'s
+ _ = [](T2[int, string]){}
+}
--- /dev/null
+// 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.
+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 */ []
+type _ myInt /* ERROR not a generic type */ []
+
+// TODO(gri) better error messages
+type _ T1 /* ERROR got 0 arguments but 1 type parameters */ []
+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
--- /dev/null
+// 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_ */ ]
--- /dev/null
+// 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 use 0 .* as \[\]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 incomparable 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[int]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] }
+
+// indexing with various combinations of map types in type lists (see issue #42616)
+func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = x[i] }
+func _[T interface{ type []E }, E any](x T, i int) { _ = &x[i] }
+func _[T interface{ type map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted
+func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] }
+func _[T interface{ type []E, map[int]E, map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types
+func _[T interface{ type []E, map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use 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() {}
+func (T) m2[ /* ERROR methods cannot have type parameters */ _ any]() {}
+func (T) m3[ /* ERROR methods cannot have type parameters */ 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) _[ /* ERROR methods cannot have type parameters */ T any](x T)
+func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ 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[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T
+func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
+func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ 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 cannot use .* as rune .* \(truncated\) */)
+ 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]
+*/
if t := asInterface(typ); t != nil {
check.completeInterface(pos.Pos(), t) // TODO(gri) is this the correct position?
if t.allTypes != nil {
- check.softErrorf(pos, 0, "interface contains type constraints (%s)", t.allTypes)
+ check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", t.allTypes)
return
}
if t.IsComparable() {
- check.softErrorf(pos, 0, "interface is (or embeds) comparable")
+ check.softErrorf(pos, _Todo, "interface is (or embeds) comparable")
}
}
})
typ := check.typInternal(e, def)
assert(isTyped(typ))
if isGeneric(typ) {
- check.errorf(e, 0, "cannot use generic type %s without instantiation", typ)
+ check.errorf(e, _Todo, "cannot use generic type %s without instantiation", typ)
typ = Typ[Invalid]
}
check.recordTypeAndValue(e, typexpr, typ, nil)
assert(isTyped(typ))
if typ != Typ[Invalid] && !isGeneric(typ) {
if reportErr {
- check.errorf(e, 0, "%s is not a generic type", typ)
+ check.errorf(e, _Todo, "%s is not a generic type", typ)
}
typ = Typ[Invalid]
}
// (A separate check is needed when type-checking interface method signatures because
// they don't have a receiver specification.)
if recvPar != nil {
- check.errorf(ftyp.TParams, 0, "methods cannot have type parameters")
+ check.errorf(ftyp.TParams, _Todo, "methods cannot have type parameters")
}
}
// the author intended to include all types.
types = append(types, f.Type)
if tlist != nil && tlist != name {
- check.errorf(name, 0, "cannot have multiple type lists in an interface")
+ check.errorf(name, _Todo, "cannot have multiple type lists in an interface")
}
tlist = name
continue
// (This extra check is needed here because interface method signatures don't have
// a receiver specification.)
if sig.tparams != nil {
- check.errorf(f.Type.(*ast.FuncType).TParams, 0, "methods cannot have type parameters")
+ check.errorf(f.Type.(*ast.FuncType).TParams, _Todo, "methods cannot have type parameters")
}
// use named receiver type if available (for better error messages)
pos := f.Type.Pos()
name := embeddedFieldIdent(f.Type)
if name == nil {
- check.invalidAST(f.Type, "embedded field type %s has no name", f.Type)
+ // TODO(rFindley): using invalidAST here causes test failures (all
+ // errors should have codes). Clean this up.
+ check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type)
name = ast.NewIdent("_")
name.NamePos = pos
addInvalid(name, pos)
check.completeInterface(types[i].Pos(), t)
}
if includes(list[:i], t) {
- check.softErrorf(types[i], 0, "duplicate type %s in type list", t)
+ check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t)
}
}
})