]> Cypherpunks.ru repositories - gostls13.git/blob - src/go/types/api_test.go
go/types, types2: add an additional shift test case
[gostls13.git] / src / go / types / api_test.go
1 // Copyright 2013 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 package types_test
6
7 import (
8         "bytes"
9         "fmt"
10         "go/ast"
11         "go/importer"
12         "go/internal/typeparams"
13         "go/parser"
14         "go/token"
15         "internal/testenv"
16         "reflect"
17         "regexp"
18         "strings"
19         "testing"
20
21         . "go/types"
22 )
23
24 // pkgFor parses and type checks the package specified by path and source,
25 // populating info if provided.
26 //
27 // If source begins with "package generic_" and type parameters are enabled,
28 // generic code is permitted.
29 func pkgFor(path, source string, info *Info) (*Package, error) {
30         fset := token.NewFileSet()
31         mode := modeForSource(source)
32         f, err := parser.ParseFile(fset, path, source, mode)
33         if err != nil {
34                 return nil, err
35         }
36         conf := Config{Importer: importer.Default()}
37         return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
38 }
39
40 func mustTypecheck(t *testing.T, path, source string, info *Info) string {
41         pkg, err := pkgFor(path, source, info)
42         if err != nil {
43                 name := path
44                 if pkg != nil {
45                         name = "package " + pkg.Name()
46                 }
47                 t.Fatalf("%s: didn't type-check (%s)", name, err)
48         }
49         return pkg.Name()
50 }
51
52 // genericPkg is a prefix for packages that should be type checked with
53 // generics.
54 const genericPkg = "package generic_"
55
56 func modeForSource(src string) parser.Mode {
57         if !strings.HasPrefix(src, genericPkg) {
58                 return typeparams.DisallowParsing
59         }
60         return 0
61 }
62
63 func mayTypecheck(t *testing.T, path, source string, info *Info) (string, error) {
64         fset := token.NewFileSet()
65         mode := modeForSource(source)
66         f, err := parser.ParseFile(fset, path, source, mode)
67         if f == nil { // ignore errors unless f is nil
68                 t.Fatalf("%s: unable to parse: %s", path, err)
69         }
70         conf := Config{
71                 Error:    func(err error) {},
72                 Importer: importer.Default(),
73         }
74         pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
75         return pkg.Name(), err
76 }
77
78 func TestValuesInfo(t *testing.T) {
79         var tests = []struct {
80                 src  string
81                 expr string // constant expression
82                 typ  string // constant type
83                 val  string // constant value
84         }{
85                 {`package a0; const _ = false`, `false`, `untyped bool`, `false`},
86                 {`package a1; const _ = 0`, `0`, `untyped int`, `0`},
87                 {`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
88                 {`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
89                 {`package a4; const _ = 0i`, `0i`, `untyped complex`, `(0 + 0i)`},
90                 {`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
91
92                 {`package b0; var _ = false`, `false`, `bool`, `false`},
93                 {`package b1; var _ = 0`, `0`, `int`, `0`},
94                 {`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
95                 {`package b3; var _ = 0.`, `0.`, `float64`, `0`},
96                 {`package b4; var _ = 0i`, `0i`, `complex128`, `(0 + 0i)`},
97                 {`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
98
99                 {`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
100                 {`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
101                 {`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
102
103                 {`package c1a; var _ = int(0)`, `0`, `int`, `0`},
104                 {`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
105                 {`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
106
107                 {`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
108                 {`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
109                 {`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
110
111                 {`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
112                 {`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
113                 {`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
114
115                 {`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `(0 + 0i)`},
116                 {`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `(0 + 0i)`},
117                 {`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `(0 + 0i)`},
118
119                 {`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
120                 {`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
121                 {`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
122                 {`package c5d; var _ = string(65)`, `65`, `untyped int`, `65`},
123                 {`package c5e; var _ = string('A')`, `'A'`, `untyped rune`, `65`},
124                 {`package c5f; type T string; var _ = T('A')`, `'A'`, `untyped rune`, `65`},
125                 {`package c5g; var s uint; var _ = string(1 << s)`, `1 << s`, `untyped int`, ``},
126
127                 {`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
128                 {`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
129                 {`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
130                 {`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
131
132                 {`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
133                 {`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
134                 {`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
135                 {`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
136                 {`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `(0 + 0i)`},
137                 {`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `(0 + 0i)`},
138                 {`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `(0 + 0i)`},
139                 {`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `(0 + 0i)`},
140
141                 {`package f0 ; var _ float32 =  1e-200`, `1e-200`, `float32`, `0`},
142                 {`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
143                 {`package f2a; var _ float64 =  1e-2000`, `1e-2000`, `float64`, `0`},
144                 {`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
145                 {`package f2b; var _         =  1e-2000`, `1e-2000`, `float64`, `0`},
146                 {`package f3b; var _         = -1e-2000`, `-1e-2000`, `float64`, `0`},
147                 {`package f4 ; var _ complex64  =  1e-200 `, `1e-200`, `complex64`, `(0 + 0i)`},
148                 {`package f5 ; var _ complex64  = -1e-200 `, `-1e-200`, `complex64`, `(0 + 0i)`},
149                 {`package f6a; var _ complex128 =  1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
150                 {`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
151                 {`package f6b; var _            =  1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
152                 {`package f7b; var _            = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
153
154                 {`package g0; const (a = len([iota]int{}); b; c); const _ = c`, `c`, `int`, `2`}, // issue #22341
155                 {`package g1; var(j int32; s int; n = 1.0<<s == j)`, `1.0`, `int32`, `1`},        // issue #48422
156         }
157
158         for _, test := range tests {
159                 info := Info{
160                         Types: make(map[ast.Expr]TypeAndValue),
161                 }
162                 name := mustTypecheck(t, "ValuesInfo", test.src, &info)
163
164                 // look for expression
165                 var expr ast.Expr
166                 for e := range info.Types {
167                         if ExprString(e) == test.expr {
168                                 expr = e
169                                 break
170                         }
171                 }
172                 if expr == nil {
173                         t.Errorf("package %s: no expression found for %s", name, test.expr)
174                         continue
175                 }
176                 tv := info.Types[expr]
177
178                 // check that type is correct
179                 if got := tv.Type.String(); got != test.typ {
180                         t.Errorf("package %s: got type %s; want %s", name, got, test.typ)
181                         continue
182                 }
183
184                 // if we have a constant, check that value is correct
185                 if tv.Value != nil {
186                         if got := tv.Value.ExactString(); got != test.val {
187                                 t.Errorf("package %s: got value %s; want %s", name, got, test.val)
188                         }
189                 } else {
190                         if test.val != "" {
191                                 t.Errorf("package %s: no constant found; want %s", name, test.val)
192                         }
193                 }
194         }
195 }
196
197 func TestTypesInfo(t *testing.T) {
198         // Test sources that are not expected to typecheck must start with the broken prefix.
199         const broken = "package broken_"
200
201         var tests = []struct {
202                 src  string
203                 expr string // expression
204                 typ  string // value type
205         }{
206                 // single-valued expressions of untyped constants
207                 {`package b0; var x interface{} = false`, `false`, `bool`},
208                 {`package b1; var x interface{} = 0`, `0`, `int`},
209                 {`package b2; var x interface{} = 0.`, `0.`, `float64`},
210                 {`package b3; var x interface{} = 0i`, `0i`, `complex128`},
211                 {`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
212
213                 // uses of nil
214                 {`package n0; var _ *int = nil`, `nil`, `untyped nil`},
215                 {`package n1; var _ func() = nil`, `nil`, `untyped nil`},
216                 {`package n2; var _ []byte = nil`, `nil`, `untyped nil`},
217                 {`package n3; var _ map[int]int = nil`, `nil`, `untyped nil`},
218                 {`package n4; var _ chan int = nil`, `nil`, `untyped nil`},
219                 {`package n5; var _ interface{} = nil`, `nil`, `untyped nil`},
220                 {`package n6; import "unsafe"; var _ unsafe.Pointer = nil`, `nil`, `untyped nil`},
221
222                 {`package n10; var (x *int; _ = x == nil)`, `nil`, `untyped nil`},
223                 {`package n11; var (x func(); _ = x == nil)`, `nil`, `untyped nil`},
224                 {`package n12; var (x []byte; _ = x == nil)`, `nil`, `untyped nil`},
225                 {`package n13; var (x map[int]int; _ = x == nil)`, `nil`, `untyped nil`},
226                 {`package n14; var (x chan int; _ = x == nil)`, `nil`, `untyped nil`},
227                 {`package n15; var (x interface{}; _ = x == nil)`, `nil`, `untyped nil`},
228                 {`package n15; import "unsafe"; var (x unsafe.Pointer; _ = x == nil)`, `nil`, `untyped nil`},
229
230                 {`package n20; var _ = (*int)(nil)`, `nil`, `untyped nil`},
231                 {`package n21; var _ = (func())(nil)`, `nil`, `untyped nil`},
232                 {`package n22; var _ = ([]byte)(nil)`, `nil`, `untyped nil`},
233                 {`package n23; var _ = (map[int]int)(nil)`, `nil`, `untyped nil`},
234                 {`package n24; var _ = (chan int)(nil)`, `nil`, `untyped nil`},
235                 {`package n25; var _ = (interface{})(nil)`, `nil`, `untyped nil`},
236                 {`package n26; import "unsafe"; var _ = unsafe.Pointer(nil)`, `nil`, `untyped nil`},
237
238                 {`package n30; func f(*int) { f(nil) }`, `nil`, `untyped nil`},
239                 {`package n31; func f(func()) { f(nil) }`, `nil`, `untyped nil`},
240                 {`package n32; func f([]byte) { f(nil) }`, `nil`, `untyped nil`},
241                 {`package n33; func f(map[int]int) { f(nil) }`, `nil`, `untyped nil`},
242                 {`package n34; func f(chan int) { f(nil) }`, `nil`, `untyped nil`},
243                 {`package n35; func f(interface{}) { f(nil) }`, `nil`, `untyped nil`},
244                 {`package n35; import "unsafe"; func f(unsafe.Pointer) { f(nil) }`, `nil`, `untyped nil`},
245
246                 // comma-ok expressions
247                 {`package p0; var x interface{}; var _, _ = x.(int)`,
248                         `x.(int)`,
249                         `(int, bool)`,
250                 },
251                 {`package p1; var x interface{}; func _() { _, _ = x.(int) }`,
252                         `x.(int)`,
253                         `(int, bool)`,
254                 },
255                 {`package p2a; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
256                         `m["foo"]`,
257                         `(complex128, p2a.mybool)`,
258                 },
259                 {`package p2b; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
260                         `m["foo"]`,
261                         `(complex128, bool)`,
262                 },
263                 {`package p3; var c chan string; var _, _ = <-c`,
264                         `<-c`,
265                         `(string, bool)`,
266                 },
267
268                 // issue 6796
269                 {`package issue6796_a; var x interface{}; var _, _ = (x.(int))`,
270                         `x.(int)`,
271                         `(int, bool)`,
272                 },
273                 {`package issue6796_b; var c chan string; var _, _ = (<-c)`,
274                         `(<-c)`,
275                         `(string, bool)`,
276                 },
277                 {`package issue6796_c; var c chan string; var _, _ = (<-c)`,
278                         `<-c`,
279                         `(string, bool)`,
280                 },
281                 {`package issue6796_d; var c chan string; var _, _ = ((<-c))`,
282                         `(<-c)`,
283                         `(string, bool)`,
284                 },
285                 {`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`,
286                         `(<-c)`,
287                         `(string, bool)`,
288                 },
289
290                 // issue 7060
291                 {`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`,
292                         `m[0]`,
293                         `(string, bool)`,
294                 },
295                 {`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`,
296                         `m[0]`,
297                         `(string, bool)`,
298                 },
299                 {`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`,
300                         `m[0]`,
301                         `(string, bool)`,
302                 },
303                 {`package issue7060_d; var ( ch chan string; x, ok = <-ch )`,
304                         `<-ch`,
305                         `(string, bool)`,
306                 },
307                 {`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`,
308                         `<-ch`,
309                         `(string, bool)`,
310                 },
311                 {`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`,
312                         `<-ch`,
313                         `(string, bool)`,
314                 },
315
316                 // issue 28277
317                 {`package issue28277_a; func f(...int)`,
318                         `...int`,
319                         `[]int`,
320                 },
321                 {`package issue28277_b; func f(a, b int, c ...[]struct{})`,
322                         `...[]struct{}`,
323                         `[][]struct{}`,
324                 },
325
326                 // issue 47243
327                 {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`},
328                 {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `uint`}, // issue 47410: should be untyped float
329                 {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`},
330                 {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`},
331                 {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`},
332                 {`package issue47243_f; var x int32; var _ = 1 << 2`, `2`, `untyped int`},
333                 {`package issue47243_g; var x int32; var _ = int(1) << 2`, `2`, `untyped int`},
334                 {`package issue47243_h; var x int32; var _ = 1 << (2 << x)`, `1`, `int`},
335                 {`package issue47243_i; var x int32; var _ = 1 << (2 << x)`, `(2 << x)`, `untyped int`},
336                 {`package issue47243_j; var x int32; var _ = 1 << (2 << x)`, `2`, `untyped int`},
337
338                 // tests for broken code that doesn't parse or type-check
339                 {broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
340                 {broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
341                 {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
342                 {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`},
343                 {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
344                 {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
345
346                 // parameterized functions
347                 {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`},
348                 {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`},
349                 {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`},
350                 {genericPkg + `p3; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`},
351
352                 // type parameters
353                 {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t
354                 {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P₁ interface{}]`},
355                 {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P₁ interface{}]`},
356                 {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P₁, generic_t3.Q₂ interface{}]`},
357
358                 // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here
359                 {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`},
360
361                 // instantiated types must be sanitized
362                 {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`},
363
364                 // issue 45096
365                 {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32  }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`},
366
367                 // issue 47895
368                 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`},
369         }
370
371         for _, test := range tests {
372                 info := Info{Types: make(map[ast.Expr]TypeAndValue)}
373                 var name string
374                 if strings.HasPrefix(test.src, broken) {
375                         var err error
376                         name, err = mayTypecheck(t, "TypesInfo", test.src, &info)
377                         if err == nil {
378                                 t.Errorf("package %s: expected to fail but passed", name)
379                                 continue
380                         }
381                 } else {
382                         name = mustTypecheck(t, "TypesInfo", test.src, &info)
383                 }
384
385                 // look for expression type
386                 var typ Type
387                 for e, tv := range info.Types {
388                         if ExprString(e) == test.expr {
389                                 typ = tv.Type
390                                 break
391                         }
392                 }
393                 if typ == nil {
394                         t.Errorf("package %s: no type found for %s", name, test.expr)
395                         continue
396                 }
397
398                 // check that type is correct
399                 if got := typ.String(); got != test.typ {
400                         t.Errorf("package %s: got %s; want %s", name, got, test.typ)
401                 }
402         }
403 }
404
405 func TestInferredInfo(t *testing.T) {
406         var tests = []struct {
407                 src   string
408                 fun   string
409                 targs []string
410                 sig   string
411         }{
412                 {genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`,
413                         `f`,
414                         []string{`int`},
415                         `func(int)`,
416                 },
417                 {genericPkg + `p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
418                         `f`,
419                         []string{`rune`},
420                         `func(rune) rune`,
421                 },
422                 {genericPkg + `p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
423                         `f`,
424                         []string{`complex128`},
425                         `func(...complex128) complex128`,
426                 },
427                 {genericPkg + `p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
428                         `f`,
429                         []string{`float64`, `string`, `byte`},
430                         `func(float64, *string, []byte)`,
431                 },
432                 {genericPkg + `p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
433                         `f`,
434                         []string{`float64`, `byte`},
435                         `func(float64, *byte, ...[]byte)`,
436                 },
437
438                 {genericPkg + `s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`,
439                         `f`,
440                         []string{`string`, `*string`},
441                         `func(x string)`,
442                 },
443                 {genericPkg + `s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`,
444                         `f`,
445                         []string{`int`, `*int`},
446                         `func(x []int)`,
447                 },
448                 {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
449                         `f`,
450                         []string{`int`, `chan<- int`},
451                         `func(x []int)`,
452                 },
453                 {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
454                         `f`,
455                         []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
456                         `func(x []int)`,
457                 },
458
459                 {genericPkg + `t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`,
460                         `f`,
461                         []string{`string`, `*string`},
462                         `func() string`,
463                 },
464                 {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`,
465                         `f`,
466                         []string{`int`, `chan<- int`},
467                         `func() []int`,
468                 },
469                 {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
470                         `f`,
471                         []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
472                         `func() []int`,
473                 },
474         }
475
476         for _, test := range tests {
477                 info := Info{}
478                 info.Inferred = make(map[ast.Expr]Inferred)
479                 name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
480                 if err != nil {
481                         t.Errorf("package %s: %v", name, err)
482                         continue
483                 }
484
485                 // look for inferred type arguments and signature
486                 var targs *TypeList
487                 var sig *Signature
488                 for call, inf := range info.Inferred {
489                         var fun ast.Expr
490                         switch x := call.(type) {
491                         case *ast.CallExpr:
492                                 fun = x.Fun
493                         case *ast.IndexExpr:
494                                 fun = x.X
495                         default:
496                                 panic(fmt.Sprintf("unexpected call expression type %T", call))
497                         }
498                         if ExprString(fun) == test.fun {
499                                 targs = inf.TArgs
500                                 sig = inf.Sig
501                                 break
502                         }
503                 }
504                 if targs == nil {
505                         t.Errorf("package %s: no inferred information found for %s", name, test.fun)
506                         continue
507                 }
508
509                 // check that type arguments are correct
510                 if targs.Len() != len(test.targs) {
511                         t.Errorf("package %s: got %d type arguments; want %d", name, targs.Len(), len(test.targs))
512                         continue
513                 }
514                 for i := 0; i < targs.Len(); i++ {
515                         targ := targs.At(i)
516                         if got := targ.String(); got != test.targs[i] {
517                                 t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
518                                 continue
519                         }
520                 }
521
522                 // check that signature is correct
523                 if got := sig.String(); got != test.sig {
524                         t.Errorf("package %s: got %s; want %s", name, got, test.sig)
525                 }
526         }
527 }
528
529 func TestDefsInfo(t *testing.T) {
530         var tests = []struct {
531                 src  string
532                 obj  string
533                 want string
534         }{
535                 {`package p0; const x = 42`, `x`, `const p0.x untyped int`},
536                 {`package p1; const x int = 42`, `x`, `const p1.x int`},
537                 {`package p2; var x int`, `x`, `var p2.x int`},
538                 {`package p3; type x int`, `x`, `type p3.x int`},
539                 {`package p4; func f()`, `f`, `func p4.f()`},
540                 {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`},
541
542                 // generic types must be sanitized
543                 // (need to use sufficiently nested types to provoke unexpanded types)
544                 {genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`},
545                 {genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`},
546                 {genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`},
547                 {genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`},
548         }
549
550         for _, test := range tests {
551                 info := Info{
552                         Defs: make(map[*ast.Ident]Object),
553                 }
554                 name := mustTypecheck(t, "DefsInfo", test.src, &info)
555
556                 // find object
557                 var def Object
558                 for id, obj := range info.Defs {
559                         if id.Name == test.obj {
560                                 def = obj
561                                 break
562                         }
563                 }
564                 if def == nil {
565                         t.Errorf("package %s: %s not found", name, test.obj)
566                         continue
567                 }
568
569                 if got := def.String(); got != test.want {
570                         t.Errorf("package %s: got %s; want %s", name, got, test.want)
571                 }
572         }
573 }
574
575 func TestUsesInfo(t *testing.T) {
576         var tests = []struct {
577                 src  string
578                 obj  string
579                 want string
580         }{
581                 {`package p0; func _() { _ = x }; const x = 42`, `x`, `const p0.x untyped int`},
582                 {`package p1; func _() { _ = x }; const x int = 42`, `x`, `const p1.x int`},
583                 {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`},
584                 {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`},
585                 {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`},
586
587                 // generic types must be sanitized
588                 // (need to use sufficiently nested types to provoke unexpanded types)
589                 {genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`},
590                 {genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`},
591                 {genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`},
592                 {genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`},
593         }
594
595         for _, test := range tests {
596                 info := Info{
597                         Uses: make(map[*ast.Ident]Object),
598                 }
599                 name := mustTypecheck(t, "UsesInfo", test.src, &info)
600
601                 // find object
602                 var use Object
603                 for id, obj := range info.Uses {
604                         if id.Name == test.obj {
605                                 use = obj
606                                 break
607                         }
608                 }
609                 if use == nil {
610                         t.Errorf("package %s: %s not found", name, test.obj)
611                         continue
612                 }
613
614                 if got := use.String(); got != test.want {
615                         t.Errorf("package %s: got %s; want %s", name, got, test.want)
616                 }
617         }
618 }
619
620 func TestImplicitsInfo(t *testing.T) {
621         testenv.MustHaveGoBuild(t)
622
623         var tests = []struct {
624                 src  string
625                 want string
626         }{
627                 {`package p2; import . "fmt"; var _ = Println`, ""},           // no Implicits entry
628                 {`package p0; import local "fmt"; var _ = local.Println`, ""}, // no Implicits entry
629                 {`package p1; import "fmt"; var _ = fmt.Println`, "importSpec: package fmt"},
630
631                 {`package p3; func f(x interface{}) { switch x.(type) { case int: } }`, ""}, // no Implicits entry
632                 {`package p4; func f(x interface{}) { switch t := x.(type) { case int: _ = t } }`, "caseClause: var t int"},
633                 {`package p5; func f(x interface{}) { switch t := x.(type) { case int, uint: _ = t } }`, "caseClause: var t interface{}"},
634                 {`package p6; func f(x interface{}) { switch t := x.(type) { default: _ = t } }`, "caseClause: var t interface{}"},
635
636                 {`package p7; func f(x int) {}`, ""}, // no Implicits entry
637                 {`package p8; func f(int) {}`, "field: var  int"},
638                 {`package p9; func f() (complex64) { return 0 }`, "field: var  complex64"},
639                 {`package p10; type T struct{}; func (*T) f() {}`, "field: var  *p10.T"},
640         }
641
642         for _, test := range tests {
643                 info := Info{
644                         Implicits: make(map[ast.Node]Object),
645                 }
646                 name := mustTypecheck(t, "ImplicitsInfo", test.src, &info)
647
648                 // the test cases expect at most one Implicits entry
649                 if len(info.Implicits) > 1 {
650                         t.Errorf("package %s: %d Implicits entries found", name, len(info.Implicits))
651                         continue
652                 }
653
654                 // extract Implicits entry, if any
655                 var got string
656                 for n, obj := range info.Implicits {
657                         switch x := n.(type) {
658                         case *ast.ImportSpec:
659                                 got = "importSpec"
660                         case *ast.CaseClause:
661                                 got = "caseClause"
662                         case *ast.Field:
663                                 got = "field"
664                         default:
665                                 t.Fatalf("package %s: unexpected %T", name, x)
666                         }
667                         got += ": " + obj.String()
668                 }
669
670                 // verify entry
671                 if got != test.want {
672                         t.Errorf("package %s: got %q; want %q", name, got, test.want)
673                 }
674         }
675 }
676
677 func predString(tv TypeAndValue) string {
678         var buf bytes.Buffer
679         pred := func(b bool, s string) {
680                 if b {
681                         if buf.Len() > 0 {
682                                 buf.WriteString(", ")
683                         }
684                         buf.WriteString(s)
685                 }
686         }
687
688         pred(tv.IsVoid(), "void")
689         pred(tv.IsType(), "type")
690         pred(tv.IsBuiltin(), "builtin")
691         pred(tv.IsValue() && tv.Value != nil, "const")
692         pred(tv.IsValue() && tv.Value == nil, "value")
693         pred(tv.IsNil(), "nil")
694         pred(tv.Addressable(), "addressable")
695         pred(tv.Assignable(), "assignable")
696         pred(tv.HasOk(), "hasOk")
697
698         if buf.Len() == 0 {
699                 return "invalid"
700         }
701         return buf.String()
702 }
703
704 func TestPredicatesInfo(t *testing.T) {
705         testenv.MustHaveGoBuild(t)
706
707         var tests = []struct {
708                 src  string
709                 expr string
710                 pred string
711         }{
712                 // void
713                 {`package n0; func f() { f() }`, `f()`, `void`},
714
715                 // types
716                 {`package t0; type _ int`, `int`, `type`},
717                 {`package t1; type _ []int`, `[]int`, `type`},
718                 {`package t2; type _ func()`, `func()`, `type`},
719                 {`package t3; type _ func(int)`, `int`, `type`},
720                 {`package t3; type _ func(...int)`, `...int`, `type`},
721
722                 // built-ins
723                 {`package b0; var _ = len("")`, `len`, `builtin`},
724                 {`package b1; var _ = (len)("")`, `(len)`, `builtin`},
725
726                 // constants
727                 {`package c0; var _ = 42`, `42`, `const`},
728                 {`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`},
729                 {`package c2; const (i = 1i; _ = i)`, `i`, `const`},
730
731                 // values
732                 {`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
733                 {`package v1; var _ = &[]int{1}`, `([]int literal)`, `value`},
734                 {`package v2; var _ = func(){}`, `(func() literal)`, `value`},
735                 {`package v4; func f() { _ = f }`, `f`, `value`},
736                 {`package v3; var _ *int = nil`, `nil`, `value, nil`},
737                 {`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
738
739                 // addressable (and thus assignable) operands
740                 {`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`},
741                 {`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`},
742                 {`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`},
743                 {`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`},
744                 {`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`},
745                 {`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`},
746                 {`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`},
747                 {`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`},
748                 // composite literals are not addressable
749
750                 // assignable but not addressable values
751                 {`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
752                 {`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
753
754                 // hasOk expressions
755                 {`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`},
756                 {`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`},
757
758                 // missing entries
759                 // - package names are collected in the Uses map
760                 // - identifiers being declared are collected in the Defs map
761                 {`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`},
762                 {`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`},
763                 {`package m2; const c = 0`, `c`, `<missing>`},
764                 {`package m3; type T int`, `T`, `<missing>`},
765                 {`package m4; var v int`, `v`, `<missing>`},
766                 {`package m5; func f() {}`, `f`, `<missing>`},
767                 {`package m6; func _(x int) {}`, `x`, `<missing>`},
768                 {`package m6; func _()(x int) { return }`, `x`, `<missing>`},
769                 {`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`},
770         }
771
772         for _, test := range tests {
773                 info := Info{Types: make(map[ast.Expr]TypeAndValue)}
774                 name := mustTypecheck(t, "PredicatesInfo", test.src, &info)
775
776                 // look for expression predicates
777                 got := "<missing>"
778                 for e, tv := range info.Types {
779                         //println(name, ExprString(e))
780                         if ExprString(e) == test.expr {
781                                 got = predString(tv)
782                                 break
783                         }
784                 }
785
786                 if got != test.pred {
787                         t.Errorf("package %s: got %s; want %s", name, got, test.pred)
788                 }
789         }
790 }
791
792 func TestScopesInfo(t *testing.T) {
793         testenv.MustHaveGoBuild(t)
794
795         var tests = []struct {
796                 src    string
797                 scopes []string // list of scope descriptors of the form kind:varlist
798         }{
799                 {`package p0`, []string{
800                         "file:",
801                 }},
802                 {`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
803                         "file:fmt m",
804                 }},
805                 {`package p2; func _() {}`, []string{
806                         "file:", "func:",
807                 }},
808                 {`package p3; func _(x, y int) {}`, []string{
809                         "file:", "func:x y",
810                 }},
811                 {`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
812                         "file:", "func:x y z", // redeclaration of x
813                 }},
814                 {`package p5; func _(x, y int) (u, _ int) { return }`, []string{
815                         "file:", "func:u x y",
816                 }},
817                 {`package p6; func _() { { var x int; _ = x } }`, []string{
818                         "file:", "func:", "block:x",
819                 }},
820                 {`package p7; func _() { if true {} }`, []string{
821                         "file:", "func:", "if:", "block:",
822                 }},
823                 {`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
824                         "file:", "func:", "if:x", "block:y",
825                 }},
826                 {`package p9; func _() { switch x := 0; x {} }`, []string{
827                         "file:", "func:", "switch:x",
828                 }},
829                 {`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
830                         "file:", "func:", "switch:x", "case:y", "case:",
831                 }},
832                 {`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
833                         "file:", "func:t", "type switch:",
834                 }},
835                 {`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
836                         "file:", "func:t", "type switch:t",
837                 }},
838                 {`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
839                         "file:", "func:t", "type switch:", "case:x", // x implicitly declared
840                 }},
841                 {`package p14; func _() { select{} }`, []string{
842                         "file:", "func:",
843                 }},
844                 {`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
845                         "file:", "func:c", "comm:",
846                 }},
847                 {`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
848                         "file:", "func:c", "comm:i x",
849                 }},
850                 {`package p17; func _() { for{} }`, []string{
851                         "file:", "func:", "for:", "block:",
852                 }},
853                 {`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
854                         "file:", "func:n", "for:i", "block:",
855                 }},
856                 {`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
857                         "file:", "func:a", "range:i", "block:",
858                 }},
859                 {`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
860                         "file:", "func:a", "range:i x", "block:",
861                 }},
862         }
863
864         for _, test := range tests {
865                 info := Info{Scopes: make(map[ast.Node]*Scope)}
866                 name := mustTypecheck(t, "ScopesInfo", test.src, &info)
867
868                 // number of scopes must match
869                 if len(info.Scopes) != len(test.scopes) {
870                         t.Errorf("package %s: got %d scopes; want %d", name, len(info.Scopes), len(test.scopes))
871                 }
872
873                 // scope descriptions must match
874                 for node, scope := range info.Scopes {
875                         kind := "<unknown node kind>"
876                         switch node.(type) {
877                         case *ast.File:
878                                 kind = "file"
879                         case *ast.FuncType:
880                                 kind = "func"
881                         case *ast.BlockStmt:
882                                 kind = "block"
883                         case *ast.IfStmt:
884                                 kind = "if"
885                         case *ast.SwitchStmt:
886                                 kind = "switch"
887                         case *ast.TypeSwitchStmt:
888                                 kind = "type switch"
889                         case *ast.CaseClause:
890                                 kind = "case"
891                         case *ast.CommClause:
892                                 kind = "comm"
893                         case *ast.ForStmt:
894                                 kind = "for"
895                         case *ast.RangeStmt:
896                                 kind = "range"
897                         }
898
899                         // look for matching scope description
900                         desc := kind + ":" + strings.Join(scope.Names(), " ")
901                         found := false
902                         for _, d := range test.scopes {
903                                 if desc == d {
904                                         found = true
905                                         break
906                                 }
907                         }
908                         if !found {
909                                 t.Errorf("package %s: no matching scope found for %s", name, desc)
910                         }
911                 }
912         }
913 }
914
915 func TestInitOrderInfo(t *testing.T) {
916         var tests = []struct {
917                 src   string
918                 inits []string
919         }{
920                 {`package p0; var (x = 1; y = x)`, []string{
921                         "x = 1", "y = x",
922                 }},
923                 {`package p1; var (a = 1; b = 2; c = 3)`, []string{
924                         "a = 1", "b = 2", "c = 3",
925                 }},
926                 {`package p2; var (a, b, c = 1, 2, 3)`, []string{
927                         "a = 1", "b = 2", "c = 3",
928                 }},
929                 {`package p3; var _ = f(); func f() int { return 1 }`, []string{
930                         "_ = f()", // blank var
931                 }},
932                 {`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{
933                         "a = 0", "z = 0", "y = z", "x = y",
934                 }},
935                 {`package p5; var (a, _ = m[0]; m map[int]string)`, []string{
936                         "a, _ = m[0]", // blank var
937                 }},
938                 {`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{
939                         "z = 0", "a, b = f()",
940                 }},
941                 {`package p7; var (a = func() int { return b }(); b = 1)`, []string{
942                         "b = 1", "a = (func() int literal)()",
943                 }},
944                 {`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
945                         "c = 1", "a, b = (func() (_, _ int) literal)()",
946                 }},
947                 {`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
948                         "y = 1", "x = T.m",
949                 }},
950                 {`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{
951                         "a = 0", "b = 0", "c = 0", "d = c + b",
952                 }},
953                 {`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{
954                         "c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c",
955                 }},
956                 // emit an initializer for n:1 initializations only once (not for each node
957                 // on the lhs which may appear in different order in the dependency graph)
958                 {`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{
959                         "b = 0", "x, y = m[0]", "a = x",
960                 }},
961                 // test case from spec section on package initialization
962                 {`package p12
963
964                 var (
965                         a = c + b
966                         b = f()
967                         c = f()
968                         d = 3
969                 )
970
971                 func f() int {
972                         d++
973                         return d
974                 }`, []string{
975                         "d = 3", "b = f()", "c = f()", "a = c + b",
976                 }},
977                 // test case for issue 7131
978                 {`package main
979
980                 var counter int
981                 func next() int { counter++; return counter }
982
983                 var _ = makeOrder()
984                 func makeOrder() []int { return []int{f, b, d, e, c, a} }
985
986                 var a       = next()
987                 var b, c    = next(), next()
988                 var d, e, f = next(), next(), next()
989                 `, []string{
990                         "a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
991                 }},
992                 // test case for issue 10709
993                 {`package p13
994
995                 var (
996                     v = t.m()
997                     t = makeT(0)
998                 )
999
1000                 type T struct{}
1001
1002                 func (T) m() int { return 0 }
1003
1004                 func makeT(n int) T {
1005                     if n > 0 {
1006                         return makeT(n-1)
1007                     }
1008                     return T{}
1009                 }`, []string{
1010                         "t = makeT(0)", "v = t.m()",
1011                 }},
1012                 // test case for issue 10709: same as test before, but variable decls swapped
1013                 {`package p14
1014
1015                 var (
1016                     t = makeT(0)
1017                     v = t.m()
1018                 )
1019
1020                 type T struct{}
1021
1022                 func (T) m() int { return 0 }
1023
1024                 func makeT(n int) T {
1025                     if n > 0 {
1026                         return makeT(n-1)
1027                     }
1028                     return T{}
1029                 }`, []string{
1030                         "t = makeT(0)", "v = t.m()",
1031                 }},
1032                 // another candidate possibly causing problems with issue 10709
1033                 {`package p15
1034
1035                 var y1 = f1()
1036
1037                 func f1() int { return g1() }
1038                 func g1() int { f1(); return x1 }
1039
1040                 var x1 = 0
1041
1042                 var y2 = f2()
1043
1044                 func f2() int { return g2() }
1045                 func g2() int { return x2 }
1046
1047                 var x2 = 0`, []string{
1048                         "x1 = 0", "y1 = f1()", "x2 = 0", "y2 = f2()",
1049                 }},
1050         }
1051
1052         for _, test := range tests {
1053                 info := Info{}
1054                 name := mustTypecheck(t, "InitOrderInfo", test.src, &info)
1055
1056                 // number of initializers must match
1057                 if len(info.InitOrder) != len(test.inits) {
1058                         t.Errorf("package %s: got %d initializers; want %d", name, len(info.InitOrder), len(test.inits))
1059                         continue
1060                 }
1061
1062                 // initializers must match
1063                 for i, want := range test.inits {
1064                         got := info.InitOrder[i].String()
1065                         if got != want {
1066                                 t.Errorf("package %s, init %d: got %s; want %s", name, i, got, want)
1067                                 continue
1068                         }
1069                 }
1070         }
1071 }
1072
1073 func TestMultiFileInitOrder(t *testing.T) {
1074         fset := token.NewFileSet()
1075         mustParse := func(src string) *ast.File {
1076                 f, err := parser.ParseFile(fset, "main", src, 0)
1077                 if err != nil {
1078                         t.Fatal(err)
1079                 }
1080                 return f
1081         }
1082
1083         fileA := mustParse(`package main; var a = 1`)
1084         fileB := mustParse(`package main; var b = 2`)
1085
1086         // The initialization order must not depend on the parse
1087         // order of the files, only on the presentation order to
1088         // the type-checker.
1089         for _, test := range []struct {
1090                 files []*ast.File
1091                 want  string
1092         }{
1093                 {[]*ast.File{fileA, fileB}, "[a = 1 b = 2]"},
1094                 {[]*ast.File{fileB, fileA}, "[b = 2 a = 1]"},
1095         } {
1096                 var info Info
1097                 if _, err := new(Config).Check("main", fset, test.files, &info); err != nil {
1098                         t.Fatal(err)
1099                 }
1100                 if got := fmt.Sprint(info.InitOrder); got != test.want {
1101                         t.Fatalf("got %s; want %s", got, test.want)
1102                 }
1103         }
1104 }
1105
1106 func TestFiles(t *testing.T) {
1107         var sources = []string{
1108                 "package p; type T struct{}; func (T) m1() {}",
1109                 "package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}",
1110                 "package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}",
1111                 "package p",
1112         }
1113
1114         var conf Config
1115         fset := token.NewFileSet()
1116         pkg := NewPackage("p", "p")
1117         var info Info
1118         check := NewChecker(&conf, fset, pkg, &info)
1119
1120         for i, src := range sources {
1121                 filename := fmt.Sprintf("sources%d", i)
1122                 f, err := parser.ParseFile(fset, filename, src, 0)
1123                 if err != nil {
1124                         t.Fatal(err)
1125                 }
1126                 if err := check.Files([]*ast.File{f}); err != nil {
1127                         t.Error(err)
1128                 }
1129         }
1130
1131         // check InitOrder is [x y]
1132         var vars []string
1133         for _, init := range info.InitOrder {
1134                 for _, v := range init.Lhs {
1135                         vars = append(vars, v.Name())
1136                 }
1137         }
1138         if got, want := fmt.Sprint(vars), "[x y]"; got != want {
1139                 t.Errorf("InitOrder == %s, want %s", got, want)
1140         }
1141 }
1142
1143 type testImporter map[string]*Package
1144
1145 func (m testImporter) Import(path string) (*Package, error) {
1146         if pkg := m[path]; pkg != nil {
1147                 return pkg, nil
1148         }
1149         return nil, fmt.Errorf("package %q not found", path)
1150 }
1151
1152 func TestSelection(t *testing.T) {
1153         selections := make(map[*ast.SelectorExpr]*Selection)
1154
1155         fset := token.NewFileSet()
1156         imports := make(testImporter)
1157         conf := Config{Importer: imports}
1158         makePkg := func(path, src string) {
1159                 f, err := parser.ParseFile(fset, path+".go", src, 0)
1160                 if err != nil {
1161                         t.Fatal(err)
1162                 }
1163                 pkg, err := conf.Check(path, fset, []*ast.File{f}, &Info{Selections: selections})
1164                 if err != nil {
1165                         t.Fatal(err)
1166                 }
1167                 imports[path] = pkg
1168         }
1169
1170         const libSrc = `
1171 package lib
1172 type T float64
1173 const C T = 3
1174 var V T
1175 func F() {}
1176 func (T) M() {}
1177 `
1178         const mainSrc = `
1179 package main
1180 import "lib"
1181
1182 type A struct {
1183         *B
1184         C
1185 }
1186
1187 type B struct {
1188         b int
1189 }
1190
1191 func (B) f(int)
1192
1193 type C struct {
1194         c int
1195 }
1196
1197 func (C) g()
1198 func (*C) h()
1199
1200 func main() {
1201         // qualified identifiers
1202         var _ lib.T
1203         _ = lib.C
1204         _ = lib.F
1205         _ = lib.V
1206         _ = lib.T.M
1207
1208         // fields
1209         _ = A{}.B
1210         _ = new(A).B
1211
1212         _ = A{}.C
1213         _ = new(A).C
1214
1215         _ = A{}.b
1216         _ = new(A).b
1217
1218         _ = A{}.c
1219         _ = new(A).c
1220
1221         // methods
1222         _ = A{}.f
1223         _ = new(A).f
1224         _ = A{}.g
1225         _ = new(A).g
1226         _ = new(A).h
1227
1228         _ = B{}.f
1229         _ = new(B).f
1230
1231         _ = C{}.g
1232         _ = new(C).g
1233         _ = new(C).h
1234
1235         // method expressions
1236         _ = A.f
1237         _ = (*A).f
1238         _ = B.f
1239         _ = (*B).f
1240 }`
1241
1242         wantOut := map[string][2]string{
1243                 "lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"},
1244
1245                 "A{}.B":    {"field (main.A) B *main.B", ".[0]"},
1246                 "new(A).B": {"field (*main.A) B *main.B", "->[0]"},
1247                 "A{}.C":    {"field (main.A) C main.C", ".[1]"},
1248                 "new(A).C": {"field (*main.A) C main.C", "->[1]"},
1249                 "A{}.b":    {"field (main.A) b int", "->[0 0]"},
1250                 "new(A).b": {"field (*main.A) b int", "->[0 0]"},
1251                 "A{}.c":    {"field (main.A) c int", ".[1 0]"},
1252                 "new(A).c": {"field (*main.A) c int", "->[1 0]"},
1253
1254                 "A{}.f":    {"method (main.A) f(int)", "->[0 0]"},
1255                 "new(A).f": {"method (*main.A) f(int)", "->[0 0]"},
1256                 "A{}.g":    {"method (main.A) g()", ".[1 0]"},
1257                 "new(A).g": {"method (*main.A) g()", "->[1 0]"},
1258                 "new(A).h": {"method (*main.A) h()", "->[1 1]"}, // TODO(gri) should this report .[1 1] ?
1259                 "B{}.f":    {"method (main.B) f(int)", ".[0]"},
1260                 "new(B).f": {"method (*main.B) f(int)", "->[0]"},
1261                 "C{}.g":    {"method (main.C) g()", ".[0]"},
1262                 "new(C).g": {"method (*main.C) g()", "->[0]"},
1263                 "new(C).h": {"method (*main.C) h()", "->[1]"}, // TODO(gri) should this report .[1] ?
1264
1265                 "A.f":    {"method expr (main.A) f(main.A, int)", "->[0 0]"},
1266                 "(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"},
1267                 "B.f":    {"method expr (main.B) f(main.B, int)", ".[0]"},
1268                 "(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"},
1269         }
1270
1271         makePkg("lib", libSrc)
1272         makePkg("main", mainSrc)
1273
1274         for e, sel := range selections {
1275                 _ = sel.String() // assertion: must not panic
1276
1277                 start := fset.Position(e.Pos()).Offset
1278                 end := fset.Position(e.End()).Offset
1279                 syntax := mainSrc[start:end] // (all SelectorExprs are in main, not lib)
1280
1281                 direct := "."
1282                 if sel.Indirect() {
1283                         direct = "->"
1284                 }
1285                 got := [2]string{
1286                         sel.String(),
1287                         fmt.Sprintf("%s%v", direct, sel.Index()),
1288                 }
1289                 want := wantOut[syntax]
1290                 if want != got {
1291                         t.Errorf("%s: got %q; want %q", syntax, got, want)
1292                 }
1293                 delete(wantOut, syntax)
1294
1295                 // We must explicitly assert properties of the
1296                 // Signature's receiver since it doesn't participate
1297                 // in Identical() or String().
1298                 sig, _ := sel.Type().(*Signature)
1299                 if sel.Kind() == MethodVal {
1300                         got := sig.Recv().Type()
1301                         want := sel.Recv()
1302                         if !Identical(got, want) {
1303                                 t.Errorf("%s: Recv() = %s, want %s", syntax, got, want)
1304                         }
1305                 } else if sig != nil && sig.Recv() != nil {
1306                         t.Errorf("%s: signature has receiver %s", sig, sig.Recv().Type())
1307                 }
1308         }
1309         // Assert that all wantOut entries were used exactly once.
1310         for syntax := range wantOut {
1311                 t.Errorf("no ast.Selection found with syntax %q", syntax)
1312         }
1313 }
1314
1315 func TestIssue8518(t *testing.T) {
1316         fset := token.NewFileSet()
1317         imports := make(testImporter)
1318         conf := Config{
1319                 Error:    func(err error) { t.Log(err) }, // don't exit after first error
1320                 Importer: imports,
1321         }
1322         makePkg := func(path, src string) {
1323                 f, err := parser.ParseFile(fset, path, src, 0)
1324                 if err != nil {
1325                         t.Fatal(err)
1326                 }
1327                 pkg, _ := conf.Check(path, fset, []*ast.File{f}, nil) // errors logged via conf.Error
1328                 imports[path] = pkg
1329         }
1330
1331         const libSrc = `
1332 package a
1333 import "missing"
1334 const C1 = foo
1335 const C2 = missing.C
1336 `
1337
1338         const mainSrc = `
1339 package main
1340 import "a"
1341 var _ = a.C1
1342 var _ = a.C2
1343 `
1344
1345         makePkg("a", libSrc)
1346         makePkg("main", mainSrc) // don't crash when type-checking this package
1347 }
1348
1349 func TestLookupFieldOrMethod(t *testing.T) {
1350         // Test cases assume a lookup of the form a.f or x.f, where a stands for an
1351         // addressable value, and x for a non-addressable value (even though a variable
1352         // for ease of test case writing).
1353         //
1354         // Should be kept in sync with TestMethodSet.
1355         var tests = []struct {
1356                 src      string
1357                 found    bool
1358                 index    []int
1359                 indirect bool
1360         }{
1361                 // field lookups
1362                 {"var x T; type T struct{}", false, nil, false},
1363                 {"var x T; type T struct{ f int }", true, []int{0}, false},
1364                 {"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
1365
1366                 // method lookups
1367                 {"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
1368                 {"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
1369                 {"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
1370                 {"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
1371
1372                 // collisions
1373                 {"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
1374                 {"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
1375
1376                 // outside methodset
1377                 // (*T).f method exists, but value of type T is not addressable
1378                 {"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
1379         }
1380
1381         for _, test := range tests {
1382                 pkg, err := pkgFor("test", "package p;"+test.src, nil)
1383                 if err != nil {
1384                         t.Errorf("%s: incorrect test case: %s", test.src, err)
1385                         continue
1386                 }
1387
1388                 obj := pkg.Scope().Lookup("a")
1389                 if obj == nil {
1390                         if obj = pkg.Scope().Lookup("x"); obj == nil {
1391                                 t.Errorf("%s: incorrect test case - no object a or x", test.src)
1392                                 continue
1393                         }
1394                 }
1395
1396                 f, index, indirect := LookupFieldOrMethod(obj.Type(), obj.Name() == "a", pkg, "f")
1397                 if (f != nil) != test.found {
1398                         if f == nil {
1399                                 t.Errorf("%s: got no object; want one", test.src)
1400                         } else {
1401                                 t.Errorf("%s: got object = %v; want none", test.src, f)
1402                         }
1403                 }
1404                 if !sameSlice(index, test.index) {
1405                         t.Errorf("%s: got index = %v; want %v", test.src, index, test.index)
1406                 }
1407                 if indirect != test.indirect {
1408                         t.Errorf("%s: got indirect = %v; want %v", test.src, indirect, test.indirect)
1409                 }
1410         }
1411 }
1412
1413 func sameSlice(a, b []int) bool {
1414         if len(a) != len(b) {
1415                 return false
1416         }
1417         for i, x := range a {
1418                 if x != b[i] {
1419                         return false
1420                 }
1421         }
1422         return true
1423 }
1424
1425 // TestScopeLookupParent ensures that (*Scope).LookupParent returns
1426 // the correct result at various positions with the source.
1427 func TestScopeLookupParent(t *testing.T) {
1428         fset := token.NewFileSet()
1429         imports := make(testImporter)
1430         conf := Config{Importer: imports}
1431         mustParse := func(src string) *ast.File {
1432                 f, err := parser.ParseFile(fset, "dummy.go", src, parser.ParseComments)
1433                 if err != nil {
1434                         t.Fatal(err)
1435                 }
1436                 return f
1437         }
1438         var info Info
1439         makePkg := func(path string, files ...*ast.File) {
1440                 var err error
1441                 imports[path], err = conf.Check(path, fset, files, &info)
1442                 if err != nil {
1443                         t.Fatal(err)
1444                 }
1445         }
1446
1447         makePkg("lib", mustParse("package lib; var X int"))
1448         // Each /*name=kind:line*/ comment makes the test look up the
1449         // name at that point and checks that it resolves to a decl of
1450         // the specified kind and line number.  "undef" means undefined.
1451         mainSrc := `
1452 /*lib=pkgname:5*/ /*X=var:1*/ /*Pi=const:8*/ /*T=typename:9*/ /*Y=var:10*/ /*F=func:12*/
1453 package main
1454
1455 import "lib"
1456 import . "lib"
1457
1458 const Pi = 3.1415
1459 type T struct{}
1460 var Y, _ = lib.X, X
1461
1462 func F(){
1463         const pi, e = 3.1415, /*pi=undef*/ 2.71828 /*pi=const:13*/ /*e=const:13*/
1464         type /*t=undef*/ t /*t=typename:14*/ *t
1465         print(Y) /*Y=var:10*/
1466         x, Y := Y, /*x=undef*/ /*Y=var:10*/ Pi /*x=var:16*/ /*Y=var:16*/ ; _ = x; _ = Y
1467         var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
1468
1469         var a []int
1470         for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
1471
1472         var i interface{}
1473         switch y := i.(type) { /*y=undef*/
1474         case /*y=undef*/ int /*y=var:23*/ :
1475         case float32, /*y=undef*/ float64 /*y=var:23*/ :
1476         default /*y=var:23*/:
1477                 println(y)
1478         }
1479         /*y=undef*/
1480
1481         switch int := i.(type) {
1482         case /*int=typename:0*/ int /*int=var:31*/ :
1483                 println(int)
1484         default /*int=var:31*/ :
1485         }
1486 }
1487 /*main=undef*/
1488 `
1489
1490         info.Uses = make(map[*ast.Ident]Object)
1491         f := mustParse(mainSrc)
1492         makePkg("main", f)
1493         mainScope := imports["main"].Scope()
1494         rx := regexp.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`)
1495         for _, group := range f.Comments {
1496                 for _, comment := range group.List {
1497                         // Parse the assertion in the comment.
1498                         m := rx.FindStringSubmatch(comment.Text)
1499                         if m == nil {
1500                                 t.Errorf("%s: bad comment: %s",
1501                                         fset.Position(comment.Pos()), comment.Text)
1502                                 continue
1503                         }
1504                         name, want := m[1], m[2]
1505
1506                         // Look up the name in the innermost enclosing scope.
1507                         inner := mainScope.Innermost(comment.Pos())
1508                         if inner == nil {
1509                                 t.Errorf("%s: at %s: can't find innermost scope",
1510                                         fset.Position(comment.Pos()), comment.Text)
1511                                 continue
1512                         }
1513                         got := "undef"
1514                         if _, obj := inner.LookupParent(name, comment.Pos()); obj != nil {
1515                                 kind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
1516                                 got = fmt.Sprintf("%s:%d", kind, fset.Position(obj.Pos()).Line)
1517                         }
1518                         if got != want {
1519                                 t.Errorf("%s: at %s: %s resolved to %s, want %s",
1520                                         fset.Position(comment.Pos()), comment.Text, name, got, want)
1521                         }
1522                 }
1523         }
1524
1525         // Check that for each referring identifier,
1526         // a lookup of its name on the innermost
1527         // enclosing scope returns the correct object.
1528
1529         for id, wantObj := range info.Uses {
1530                 inner := mainScope.Innermost(id.Pos())
1531                 if inner == nil {
1532                         t.Errorf("%s: can't find innermost scope enclosing %q",
1533                                 fset.Position(id.Pos()), id.Name)
1534                         continue
1535                 }
1536
1537                 // Exclude selectors and qualified identifiers---lexical
1538                 // refs only.  (Ideally, we'd see if the AST parent is a
1539                 // SelectorExpr, but that requires PathEnclosingInterval
1540                 // from golang.org/x/tools/go/ast/astutil.)
1541                 if id.Name == "X" {
1542                         continue
1543                 }
1544
1545                 _, gotObj := inner.LookupParent(id.Name, id.Pos())
1546                 if gotObj != wantObj {
1547                         t.Errorf("%s: got %v, want %v",
1548                                 fset.Position(id.Pos()), gotObj, wantObj)
1549                         continue
1550                 }
1551         }
1552 }
1553
1554 // newDefined creates a new defined type named T with the given underlying type.
1555 // Helper function for use with TestIncompleteInterfaces only.
1556 func newDefined(underlying Type) *Named {
1557         tname := NewTypeName(token.NoPos, nil, "T", nil)
1558         return NewNamed(tname, underlying, nil)
1559 }
1560
1561 func TestConvertibleTo(t *testing.T) {
1562         for _, test := range []struct {
1563                 v, t Type
1564                 want bool
1565         }{
1566                 {Typ[Int], Typ[Int], true},
1567                 {Typ[Int], Typ[Float32], true},
1568                 {newDefined(Typ[Int]), Typ[Int], true},
1569                 {newDefined(new(Struct)), new(Struct), true},
1570                 {newDefined(Typ[Int]), new(Struct), false},
1571                 {Typ[UntypedInt], Typ[Int], true},
1572                 {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true},
1573                 {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false},
1574                 {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false},
1575                 // Untyped string values are not permitted by the spec, so the below
1576                 // behavior is undefined.
1577                 {Typ[UntypedString], Typ[String], true},
1578         } {
1579                 if got := ConvertibleTo(test.v, test.t); got != test.want {
1580                         t.Errorf("ConvertibleTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want)
1581                 }
1582         }
1583 }
1584
1585 func TestAssignableTo(t *testing.T) {
1586         for _, test := range []struct {
1587                 v, t Type
1588                 want bool
1589         }{
1590                 {Typ[Int], Typ[Int], true},
1591                 {Typ[Int], Typ[Float32], false},
1592                 {newDefined(Typ[Int]), Typ[Int], false},
1593                 {newDefined(new(Struct)), new(Struct), true},
1594                 {Typ[UntypedBool], Typ[Bool], true},
1595                 {Typ[UntypedString], Typ[Bool], false},
1596                 // Neither untyped string nor untyped numeric assignments arise during
1597                 // normal type checking, so the below behavior is technically undefined by
1598                 // the spec.
1599                 {Typ[UntypedString], Typ[String], true},
1600                 {Typ[UntypedInt], Typ[Int], true},
1601         } {
1602                 if got := AssignableTo(test.v, test.t); got != test.want {
1603                         t.Errorf("AssignableTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want)
1604                 }
1605         }
1606 }
1607
1608 func TestIdentical_issue15173(t *testing.T) {
1609         // Identical should allow nil arguments and be symmetric.
1610         for _, test := range []struct {
1611                 x, y Type
1612                 want bool
1613         }{
1614                 {Typ[Int], Typ[Int], true},
1615                 {Typ[Int], nil, false},
1616                 {nil, Typ[Int], false},
1617                 {nil, nil, true},
1618         } {
1619                 if got := Identical(test.x, test.y); got != test.want {
1620                         t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got)
1621                 }
1622         }
1623 }
1624
1625 func TestIdenticalUnions(t *testing.T) {
1626         tname := NewTypeName(token.NoPos, nil, "myInt", nil)
1627         myInt := NewNamed(tname, Typ[Int], nil)
1628         tmap := map[string]*Term{
1629                 "int":     NewTerm(false, Typ[Int]),
1630                 "~int":    NewTerm(true, Typ[Int]),
1631                 "string":  NewTerm(false, Typ[String]),
1632                 "~string": NewTerm(true, Typ[String]),
1633                 "myInt":   NewTerm(false, myInt),
1634         }
1635         makeUnion := func(s string) *Union {
1636                 parts := strings.Split(s, "|")
1637                 var terms []*Term
1638                 for _, p := range parts {
1639                         term := tmap[p]
1640                         if term == nil {
1641                                 t.Fatalf("missing term %q", p)
1642                         }
1643                         terms = append(terms, term)
1644                 }
1645                 return NewUnion(terms)
1646         }
1647         for _, test := range []struct {
1648                 x, y string
1649                 want bool
1650         }{
1651                 // These tests are just sanity checks. The tests for type sets and
1652                 // interfaces provide much more test coverage.
1653                 {"int|~int", "~int", true},
1654                 {"myInt|~int", "~int", true},
1655                 {"int|string", "string|int", true},
1656                 {"int|int|string", "string|int", true},
1657                 {"myInt|string", "int|string", false},
1658         } {
1659                 x := makeUnion(test.x)
1660                 y := makeUnion(test.y)
1661                 if got := Identical(x, y); got != test.want {
1662                         t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got)
1663                 }
1664         }
1665 }
1666
1667 func TestIssue15305(t *testing.T) {
1668         const src = "package p; func f() int16; var _ = f(undef)"
1669         fset := token.NewFileSet()
1670         f, err := parser.ParseFile(fset, "issue15305.go", src, 0)
1671         if err != nil {
1672                 t.Fatal(err)
1673         }
1674         conf := Config{
1675                 Error: func(err error) {}, // allow errors
1676         }
1677         info := &Info{
1678                 Types: make(map[ast.Expr]TypeAndValue),
1679         }
1680         conf.Check("p", fset, []*ast.File{f}, info) // ignore result
1681         for e, tv := range info.Types {
1682                 if _, ok := e.(*ast.CallExpr); ok {
1683                         if tv.Type != Typ[Int16] {
1684                                 t.Errorf("CallExpr has type %v, want int16", tv.Type)
1685                         }
1686                         return
1687                 }
1688         }
1689         t.Errorf("CallExpr has no type")
1690 }
1691
1692 // TestCompositeLitTypes verifies that Info.Types registers the correct
1693 // types for composite literal expressions and composite literal type
1694 // expressions.
1695 func TestCompositeLitTypes(t *testing.T) {
1696         for _, test := range []struct {
1697                 lit, typ string
1698         }{
1699                 {`[16]byte{}`, `[16]byte`},
1700                 {`[...]byte{}`, `[0]byte`},                // test for issue #14092
1701                 {`[...]int{1, 2, 3}`, `[3]int`},           // test for issue #14092
1702                 {`[...]int{90: 0, 98: 1, 2}`, `[100]int`}, // test for issue #14092
1703                 {`[]int{}`, `[]int`},
1704                 {`map[string]bool{"foo": true}`, `map[string]bool`},
1705                 {`struct{}{}`, `struct{}`},
1706                 {`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
1707         } {
1708                 fset := token.NewFileSet()
1709                 f, err := parser.ParseFile(fset, test.lit, "package p; var _ = "+test.lit, 0)
1710                 if err != nil {
1711                         t.Fatalf("%s: %v", test.lit, err)
1712                 }
1713
1714                 info := &Info{
1715                         Types: make(map[ast.Expr]TypeAndValue),
1716                 }
1717                 if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
1718                         t.Fatalf("%s: %v", test.lit, err)
1719                 }
1720
1721                 cmptype := func(x ast.Expr, want string) {
1722                         tv, ok := info.Types[x]
1723                         if !ok {
1724                                 t.Errorf("%s: no Types entry found", test.lit)
1725                                 return
1726                         }
1727                         if tv.Type == nil {
1728                                 t.Errorf("%s: type is nil", test.lit)
1729                                 return
1730                         }
1731                         if got := tv.Type.String(); got != want {
1732                                 t.Errorf("%s: got %v, want %s", test.lit, got, want)
1733                         }
1734                 }
1735
1736                 // test type of composite literal expression
1737                 rhs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0]
1738                 cmptype(rhs, test.typ)
1739
1740                 // test type of composite literal type expression
1741                 cmptype(rhs.(*ast.CompositeLit).Type, test.typ)
1742         }
1743 }
1744
1745 // TestObjectParents verifies that objects have parent scopes or not
1746 // as specified by the Object interface.
1747 func TestObjectParents(t *testing.T) {
1748         const src = `
1749 package p
1750
1751 const C = 0
1752
1753 type T1 struct {
1754         a, b int
1755         T2
1756 }
1757
1758 type T2 interface {
1759         im1()
1760         im2()
1761 }
1762
1763 func (T1) m1() {}
1764 func (*T1) m2() {}
1765
1766 func f(x int) { y := x; print(y) }
1767 `
1768
1769         fset := token.NewFileSet()
1770         f, err := parser.ParseFile(fset, "src", src, 0)
1771         if err != nil {
1772                 t.Fatal(err)
1773         }
1774
1775         info := &Info{
1776                 Defs: make(map[*ast.Ident]Object),
1777         }
1778         if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
1779                 t.Fatal(err)
1780         }
1781
1782         for ident, obj := range info.Defs {
1783                 if obj == nil {
1784                         // only package names and implicit vars have a nil object
1785                         // (in this test we only need to handle the package name)
1786                         if ident.Name != "p" {
1787                                 t.Errorf("%v has nil object", ident)
1788                         }
1789                         continue
1790                 }
1791
1792                 // struct fields, type-associated and interface methods
1793                 // have no parent scope
1794                 wantParent := true
1795                 switch obj := obj.(type) {
1796                 case *Var:
1797                         if obj.IsField() {
1798                                 wantParent = false
1799                         }
1800                 case *Func:
1801                         if obj.Type().(*Signature).Recv() != nil { // method
1802                                 wantParent = false
1803                         }
1804                 }
1805
1806                 gotParent := obj.Parent() != nil
1807                 switch {
1808                 case gotParent && !wantParent:
1809                         t.Errorf("%v: want no parent, got %s", ident, obj.Parent())
1810                 case !gotParent && wantParent:
1811                         t.Errorf("%v: no parent found", ident)
1812                 }
1813         }
1814 }
1815
1816 // TestFailedImport tests that we don't get follow-on errors
1817 // elsewhere in a package due to failing to import a package.
1818 func TestFailedImport(t *testing.T) {
1819         testenv.MustHaveGoBuild(t)
1820
1821         const src = `
1822 package p
1823
1824 import foo "go/types/thisdirectorymustnotexistotherwisethistestmayfail/foo" // should only see an error here
1825
1826 const c = foo.C
1827 type T = foo.T
1828 var v T = c
1829 func f(x T) T { return foo.F(x) }
1830 `
1831         fset := token.NewFileSet()
1832         f, err := parser.ParseFile(fset, "src", src, 0)
1833         if err != nil {
1834                 t.Fatal(err)
1835         }
1836         files := []*ast.File{f}
1837
1838         // type-check using all possible importers
1839         for _, compiler := range []string{"gc", "gccgo", "source"} {
1840                 errcount := 0
1841                 conf := Config{
1842                         Error: func(err error) {
1843                                 // we should only see the import error
1844                                 if errcount > 0 || !strings.Contains(err.Error(), "could not import") {
1845                                         t.Errorf("for %s importer, got unexpected error: %v", compiler, err)
1846                                 }
1847                                 errcount++
1848                         },
1849                         Importer: importer.For(compiler, nil),
1850                 }
1851
1852                 info := &Info{
1853                         Uses: make(map[*ast.Ident]Object),
1854                 }
1855                 pkg, _ := conf.Check("p", fset, files, info)
1856                 if pkg == nil {
1857                         t.Errorf("for %s importer, type-checking failed to return a package", compiler)
1858                         continue
1859                 }
1860
1861                 imports := pkg.Imports()
1862                 if len(imports) != 1 {
1863                         t.Errorf("for %s importer, got %d imports, want 1", compiler, len(imports))
1864                         continue
1865                 }
1866                 imp := imports[0]
1867                 if imp.Name() != "foo" {
1868                         t.Errorf(`for %s importer, got %q, want "foo"`, compiler, imp.Name())
1869                         continue
1870                 }
1871
1872                 // verify that all uses of foo refer to the imported package foo (imp)
1873                 for ident, obj := range info.Uses {
1874                         if ident.Name == "foo" {
1875                                 if obj, ok := obj.(*PkgName); ok {
1876                                         if obj.Imported() != imp {
1877                                                 t.Errorf("%s resolved to %v; want %v", ident, obj.Imported(), imp)
1878                                         }
1879                                 } else {
1880                                         t.Errorf("%s resolved to %v; want package name", ident, obj)
1881                                 }
1882                         }
1883                 }
1884         }
1885 }
1886
1887 func TestInstantiate(t *testing.T) {
1888         // eventually we like more tests but this is a start
1889         const src = genericPkg + "p; type T[P any] *T[P]"
1890         pkg, err := pkgFor(".", src, nil)
1891         if err != nil {
1892                 t.Fatal(err)
1893         }
1894
1895         // type T should have one type parameter
1896         T := pkg.Scope().Lookup("T").Type().(*Named)
1897         if n := T.TypeParams().Len(); n != 1 {
1898                 t.Fatalf("expected 1 type parameter; found %d", n)
1899         }
1900
1901         // instantiation should succeed (no endless recursion)
1902         // even with a nil *Checker
1903         res, err := Instantiate(nil, T, []Type{Typ[Int]}, false)
1904         if err != nil {
1905                 t.Fatal(err)
1906         }
1907
1908         // instantiated type should point to itself
1909         if p := res.Underlying().(*Pointer).Elem(); p != res {
1910                 t.Fatalf("unexpected result type: %s points to %s", res, p)
1911         }
1912 }
1913
1914 func TestInstantiateErrors(t *testing.T) {
1915         tests := []struct {
1916                 src    string // by convention, T must be the type being instantiated
1917                 targs  []Type
1918                 wantAt int // -1 indicates no error
1919         }{
1920                 {"type T[P interface{~string}] int", []Type{Typ[Int]}, 0},
1921                 {"type T[P1 interface{int}, P2 interface{~string}] int", []Type{Typ[Int], Typ[Int]}, 1},
1922                 {"type T[P1 any, P2 interface{~[]P1}] int", []Type{Typ[Int], NewSlice(Typ[String])}, 1},
1923                 {"type T[P1 interface{~[]P2}, P2 any] int", []Type{NewSlice(Typ[String]), Typ[Int]}, 0},
1924         }
1925
1926         for _, test := range tests {
1927                 src := genericPkg + "p; " + test.src
1928                 pkg, err := pkgFor(".", src, nil)
1929                 if err != nil {
1930                         t.Fatal(err)
1931                 }
1932
1933                 T := pkg.Scope().Lookup("T").Type().(*Named)
1934
1935                 _, err = Instantiate(nil, T, test.targs, true)
1936                 if err == nil {
1937                         t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs)
1938                 }
1939
1940                 gotAt := err.(ArgumentError).Index()
1941                 if gotAt != test.wantAt {
1942                         t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, gotAt, test.wantAt)
1943                 }
1944         }
1945 }
1946
1947 func TestInstanceIdentity(t *testing.T) {
1948         imports := make(testImporter)
1949         conf := Config{Importer: imports}
1950         makePkg := func(src string) {
1951                 fset := token.NewFileSet()
1952                 f, err := parser.ParseFile(fset, "", src, 0)
1953                 if err != nil {
1954                         t.Fatal(err)
1955                 }
1956                 name := f.Name.Name
1957                 pkg, err := conf.Check(name, fset, []*ast.File{f}, nil)
1958                 if err != nil {
1959                         t.Fatal(err)
1960                 }
1961                 imports[name] = pkg
1962         }
1963         makePkg(genericPkg + `lib; type T[P any] struct{}`)
1964         makePkg(genericPkg + `a; import "generic_lib"; var A generic_lib.T[int]`)
1965         makePkg(genericPkg + `b; import "generic_lib"; var B generic_lib.T[int]`)
1966         a := imports["generic_a"].Scope().Lookup("A")
1967         b := imports["generic_b"].Scope().Lookup("B")
1968         if !Identical(a.Type(), b.Type()) {
1969                 t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type())
1970         }
1971 }