// Copyright 2021 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. //go:build typeparams // +build typeparams package types_test import ( "fmt" "go/ast" "testing" . "go/types" ) func TestInferredInfo(t *testing.T) { var tests = []struct { src string fun string targs []string sig string }{ {genericPkg + `p0; func f[T any](T); func _() { f(42) }`, `f`, []string{`int`}, `func(int)`, }, {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`, `f`, []string{`rune`}, `func(rune) rune`, }, {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`, `f`, []string{`complex128`}, `func(...complex128) complex128`, }, {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`, `f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`, `f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`}, `func() []int`, }, {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, }, } for _, test := range tests { info := Info{} info.Inferred = make(map[ast.Expr]Inferred) name, err := mayTypecheck(t, "InferredInfo", test.src, &info) if err != nil { t.Errorf("package %s: %v", name, err) continue } // look for inferred type arguments and signature var targs []Type var sig *Signature for call, inf := range info.Inferred { var fun ast.Expr switch x := call.(type) { case *ast.CallExpr: fun = x.Fun case *ast.IndexExpr: fun = x.X default: panic(fmt.Sprintf("unexpected call expression type %T", call)) } if ExprString(fun) == test.fun { targs = inf.Targs sig = inf.Sig break } } if targs == nil { t.Errorf("package %s: no inferred information found for %s", name, test.fun) continue } // check that type arguments are correct if len(targs) != len(test.targs) { t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs)) continue } for i, targ := range targs { if got := targ.String(); got != test.targs[i] { t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) continue } } // check that signature is correct if got := sig.String(); got != test.sig { t.Errorf("package %s: got %s; want %s", name, got, test.sig) } } }