Black Lives Matter. Support the Equal Justice Initiative.

Source file src/go/types/api_typeparams_test.go

Documentation: go/types

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build typeparams
     6  // +build typeparams
     7  
     8  package types_test
     9  
    10  import (
    11  	"fmt"
    12  	"go/ast"
    13  	"testing"
    14  
    15  	. "go/types"
    16  )
    17  
    18  func TestInferredInfo(t *testing.T) {
    19  	var tests = []struct {
    20  		src   string
    21  		fun   string
    22  		targs []string
    23  		sig   string
    24  	}{
    25  		{genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
    26  			`f`,
    27  			[]string{`int`},
    28  			`func(int)`,
    29  		},
    30  		{genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
    31  			`f`,
    32  			[]string{`rune`},
    33  			`func(rune) rune`,
    34  		},
    35  		{genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
    36  			`f`,
    37  			[]string{`complex128`},
    38  			`func(...complex128) complex128`,
    39  		},
    40  		{genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
    41  			`f`,
    42  			[]string{`float64`, `string`, `byte`},
    43  			`func(float64, *string, []byte)`,
    44  		},
    45  		{genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
    46  			`f`,
    47  			[]string{`float64`, `byte`},
    48  			`func(float64, *byte, ...[]byte)`,
    49  		},
    50  
    51  		{genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
    52  			`f`,
    53  			[]string{`string`, `*string`},
    54  			`func(x string)`,
    55  		},
    56  		{genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
    57  			`f`,
    58  			[]string{`int`, `*int`},
    59  			`func(x []int)`,
    60  		},
    61  		{genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
    62  			`f`,
    63  			[]string{`int`, `chan<- int`},
    64  			`func(x []int)`,
    65  		},
    66  		{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) }`,
    67  			`f`,
    68  			[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
    69  			`func(x []int)`,
    70  		},
    71  
    72  		{genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
    73  			`f`,
    74  			[]string{`string`, `*string`},
    75  			`func() string`,
    76  		},
    77  		{genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
    78  			`f`,
    79  			[]string{`int`, `chan<- int`},
    80  			`func() []int`,
    81  		},
    82  		{genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
    83  			`f`,
    84  			[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
    85  			`func() []int`,
    86  		},
    87  	}
    88  
    89  	for _, test := range tests {
    90  		info := Info{}
    91  		info.Inferred = make(map[ast.Expr]Inferred)
    92  		name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
    93  		if err != nil {
    94  			t.Errorf("package %s: %v", name, err)
    95  			continue
    96  		}
    97  
    98  		// look for inferred type arguments and signature
    99  		var targs []Type
   100  		var sig *Signature
   101  		for call, inf := range info.Inferred {
   102  			var fun ast.Expr
   103  			switch x := call.(type) {
   104  			case *ast.CallExpr:
   105  				fun = x.Fun
   106  			case *ast.IndexExpr:
   107  				fun = x.X
   108  			default:
   109  				panic(fmt.Sprintf("unexpected call expression type %T", call))
   110  			}
   111  			if ExprString(fun) == test.fun {
   112  				targs = inf.Targs
   113  				sig = inf.Sig
   114  				break
   115  			}
   116  		}
   117  		if targs == nil {
   118  			t.Errorf("package %s: no inferred information found for %s", name, test.fun)
   119  			continue
   120  		}
   121  
   122  		// check that type arguments are correct
   123  		if len(targs) != len(test.targs) {
   124  			t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs))
   125  			continue
   126  		}
   127  		for i, targ := range targs {
   128  			if got := targ.String(); got != test.targs[i] {
   129  				t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
   130  				continue
   131  			}
   132  		}
   133  
   134  		// check that signature is correct
   135  		if got := sig.String(); got != test.sig {
   136  			t.Errorf("package %s: got %s; want %s", name, got, test.sig)
   137  		}
   138  	}
   139  }
   140  

View as plain text