Source file
src/go/types/api_test.go
1
2
3
4
5 package types_test
6
7 import (
8 "errors"
9 "fmt"
10 "go/ast"
11 "go/importer"
12 "go/parser"
13 "go/token"
14 "internal/goversion"
15 "internal/testenv"
16 "slices"
17 "strings"
18 "sync"
19 "testing"
20
21 . "go/types"
22 "runtime"
23 )
24
25
26 var nopos token.Pos
27
28 func defaultImporter(fset *token.FileSet) Importer {
29 return importer.ForCompiler(fset, runtime.Compiler, nil)
30 }
31
32 func mustParse(fset *token.FileSet, src string) *ast.File {
33 f, err := parser.ParseFile(fset, pkgName(src), src, parser.ParseComments)
34 if err != nil {
35 panic(err)
36 }
37 return f
38 }
39
40 func typecheck(src string, conf *Config, info *Info) (*Package, error) {
41
42 fset := token.NewFileSet()
43 f := mustParse(fset, src)
44 if conf == nil {
45 conf = &Config{
46 Error: func(err error) {},
47 Importer: defaultImporter(fset),
48 }
49 }
50 return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
51 }
52
53 func mustTypecheck(src string, conf *Config, info *Info) *Package {
54 pkg, err := typecheck(src, conf, info)
55 if err != nil {
56 panic(err)
57 }
58 return pkg
59 }
60
61
62 func pkgName(src string) string {
63 const kw = "package "
64 if i := strings.Index(src, kw); i >= 0 {
65 after := src[i+len(kw):]
66 n := len(after)
67 if i := strings.IndexAny(after, "\n\t ;/"); i >= 0 {
68 n = i
69 }
70 return after[:n]
71 }
72 panic("missing package header: " + src)
73 }
74
75 func TestValuesInfo(t *testing.T) {
76 var tests = []struct {
77 src string
78 expr string
79 typ string
80 val string
81 }{
82 {`package a0; const _ = false`, `false`, `untyped bool`, `false`},
83 {`package a1; const _ = 0`, `0`, `untyped int`, `0`},
84 {`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
85 {`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
86 {`package a4; const _ = 0i`, `0i`, `untyped complex`, `(0 + 0i)`},
87 {`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
88
89 {`package b0; var _ = false`, `false`, `bool`, `false`},
90 {`package b1; var _ = 0`, `0`, `int`, `0`},
91 {`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
92 {`package b3; var _ = 0.`, `0.`, `float64`, `0`},
93 {`package b4; var _ = 0i`, `0i`, `complex128`, `(0 + 0i)`},
94 {`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
95
96 {`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
97 {`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
98 {`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
99
100 {`package c1a; var _ = int(0)`, `0`, `int`, `0`},
101 {`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
102 {`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
103
104 {`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
105 {`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
106 {`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
107
108 {`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
109 {`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
110 {`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
111
112 {`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `(0 + 0i)`},
113 {`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `(0 + 0i)`},
114 {`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `(0 + 0i)`},
115
116 {`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
117 {`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
118 {`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
119 {`package c5d; var _ = string(65)`, `65`, `untyped int`, `65`},
120 {`package c5e; var _ = string('A')`, `'A'`, `untyped rune`, `65`},
121 {`package c5f; type T string; var _ = T('A')`, `'A'`, `untyped rune`, `65`},
122
123 {`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
124 {`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
125 {`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
126 {`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
127
128 {`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
129 {`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
130 {`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
131 {`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
132 {`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `(0 + 0i)`},
133 {`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `(0 + 0i)`},
134 {`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `(0 + 0i)`},
135 {`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `(0 + 0i)`},
136
137 {`package f0 ; var _ float32 = 1e-200`, `1e-200`, `float32`, `0`},
138 {`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
139 {`package f2a; var _ float64 = 1e-2000`, `1e-2000`, `float64`, `0`},
140 {`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
141 {`package f2b; var _ = 1e-2000`, `1e-2000`, `float64`, `0`},
142 {`package f3b; var _ = -1e-2000`, `-1e-2000`, `float64`, `0`},
143 {`package f4 ; var _ complex64 = 1e-200 `, `1e-200`, `complex64`, `(0 + 0i)`},
144 {`package f5 ; var _ complex64 = -1e-200 `, `-1e-200`, `complex64`, `(0 + 0i)`},
145 {`package f6a; var _ complex128 = 1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
146 {`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
147 {`package f6b; var _ = 1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
148 {`package f7b; var _ = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
149
150 {`package g0; const (a = len([iota]int{}); b; c); const _ = c`, `c`, `int`, `2`},
151 {`package g1; var(j int32; s int; n = 1.0<<s == j)`, `1.0`, `int32`, `1`},
152 }
153
154 for _, test := range tests {
155 info := Info{
156 Types: make(map[ast.Expr]TypeAndValue),
157 }
158 name := mustTypecheck(test.src, nil, &info).Name()
159
160
161 var expr ast.Expr
162 for e := range info.Types {
163 if ExprString(e) == test.expr {
164 expr = e
165 break
166 }
167 }
168 if expr == nil {
169 t.Errorf("package %s: no expression found for %s", name, test.expr)
170 continue
171 }
172 tv := info.Types[expr]
173
174
175 if got := tv.Type.String(); got != test.typ {
176 t.Errorf("package %s: got type %s; want %s", name, got, test.typ)
177 continue
178 }
179
180
181 if tv.Value != nil {
182 if got := tv.Value.ExactString(); got != test.val {
183 t.Errorf("package %s: got value %s; want %s", name, got, test.val)
184 }
185 } else {
186 if test.val != "" {
187 t.Errorf("package %s: no constant found; want %s", name, test.val)
188 }
189 }
190 }
191 }
192
193 func TestTypesInfo(t *testing.T) {
194
195 const broken = "package broken_"
196
197 var tests = []struct {
198 src string
199 expr string
200 typ string
201 }{
202
203 {`package b0; var x interface{} = false`, `false`, `bool`},
204 {`package b1; var x interface{} = 0`, `0`, `int`},
205 {`package b2; var x interface{} = 0.`, `0.`, `float64`},
206 {`package b3; var x interface{} = 0i`, `0i`, `complex128`},
207 {`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
208
209
210 {`package n0; var _ *int = nil`, `nil`, `untyped nil`},
211 {`package n1; var _ func() = nil`, `nil`, `untyped nil`},
212 {`package n2; var _ []byte = nil`, `nil`, `untyped nil`},
213 {`package n3; var _ map[int]int = nil`, `nil`, `untyped nil`},
214 {`package n4; var _ chan int = nil`, `nil`, `untyped nil`},
215 {`package n5; var _ interface{} = nil`, `nil`, `untyped nil`},
216 {`package n6; import "unsafe"; var _ unsafe.Pointer = nil`, `nil`, `untyped nil`},
217
218 {`package n10; var (x *int; _ = x == nil)`, `nil`, `untyped nil`},
219 {`package n11; var (x func(); _ = x == nil)`, `nil`, `untyped nil`},
220 {`package n12; var (x []byte; _ = x == nil)`, `nil`, `untyped nil`},
221 {`package n13; var (x map[int]int; _ = x == nil)`, `nil`, `untyped nil`},
222 {`package n14; var (x chan int; _ = x == nil)`, `nil`, `untyped nil`},
223 {`package n15; var (x interface{}; _ = x == nil)`, `nil`, `untyped nil`},
224 {`package n15; import "unsafe"; var (x unsafe.Pointer; _ = x == nil)`, `nil`, `untyped nil`},
225
226 {`package n20; var _ = (*int)(nil)`, `nil`, `untyped nil`},
227 {`package n21; var _ = (func())(nil)`, `nil`, `untyped nil`},
228 {`package n22; var _ = ([]byte)(nil)`, `nil`, `untyped nil`},
229 {`package n23; var _ = (map[int]int)(nil)`, `nil`, `untyped nil`},
230 {`package n24; var _ = (chan int)(nil)`, `nil`, `untyped nil`},
231 {`package n25; var _ = (interface{})(nil)`, `nil`, `untyped nil`},
232 {`package n26; import "unsafe"; var _ = unsafe.Pointer(nil)`, `nil`, `untyped nil`},
233
234 {`package n30; func f(*int) { f(nil) }`, `nil`, `untyped nil`},
235 {`package n31; func f(func()) { f(nil) }`, `nil`, `untyped nil`},
236 {`package n32; func f([]byte) { f(nil) }`, `nil`, `untyped nil`},
237 {`package n33; func f(map[int]int) { f(nil) }`, `nil`, `untyped nil`},
238 {`package n34; func f(chan int) { f(nil) }`, `nil`, `untyped nil`},
239 {`package n35; func f(interface{}) { f(nil) }`, `nil`, `untyped nil`},
240 {`package n35; import "unsafe"; func f(unsafe.Pointer) { f(nil) }`, `nil`, `untyped nil`},
241
242
243 {`package p0; var x interface{}; var _, _ = x.(int)`,
244 `x.(int)`,
245 `(int, bool)`,
246 },
247 {`package p1; var x interface{}; func _() { _, _ = x.(int) }`,
248 `x.(int)`,
249 `(int, bool)`,
250 },
251 {`package p2a; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
252 `m["foo"]`,
253 `(complex128, p2a.mybool)`,
254 },
255 {`package p2b; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
256 `m["foo"]`,
257 `(complex128, bool)`,
258 },
259 {`package p3; var c chan string; var _, _ = <-c`,
260 `<-c`,
261 `(string, bool)`,
262 },
263
264
265 {`package issue6796_a; var x interface{}; var _, _ = (x.(int))`,
266 `x.(int)`,
267 `(int, bool)`,
268 },
269 {`package issue6796_b; var c chan string; var _, _ = (<-c)`,
270 `(<-c)`,
271 `(string, bool)`,
272 },
273 {`package issue6796_c; var c chan string; var _, _ = (<-c)`,
274 `<-c`,
275 `(string, bool)`,
276 },
277 {`package issue6796_d; var c chan string; var _, _ = ((<-c))`,
278 `(<-c)`,
279 `(string, bool)`,
280 },
281 {`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`,
282 `(<-c)`,
283 `(string, bool)`,
284 },
285
286
287 {`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`,
288 `m[0]`,
289 `(string, bool)`,
290 },
291 {`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`,
292 `m[0]`,
293 `(string, bool)`,
294 },
295 {`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`,
296 `m[0]`,
297 `(string, bool)`,
298 },
299 {`package issue7060_d; var ( ch chan string; x, ok = <-ch )`,
300 `<-ch`,
301 `(string, bool)`,
302 },
303 {`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`,
304 `<-ch`,
305 `(string, bool)`,
306 },
307 {`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`,
308 `<-ch`,
309 `(string, bool)`,
310 },
311
312
313 {`package issue28277_a; func f(...int)`,
314 `...int`,
315 `[]int`,
316 },
317 {`package issue28277_b; func f(a, b int, c ...[]struct{})`,
318 `...[]struct{}`,
319 `[][]struct{}`,
320 },
321
322
323 {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`},
324 {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `untyped float`},
325 {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`},
326 {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`},
327 {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`},
328 {`package issue47243_f; var x int32; var _ = 1 << 2`, `2`, `untyped int`},
329 {`package issue47243_g; var x int32; var _ = int(1) << 2`, `2`, `untyped int`},
330 {`package issue47243_h; var x int32; var _ = 1 << (2 << x)`, `1`, `int`},
331 {`package issue47243_i; var x int32; var _ = 1 << (2 << x)`, `(2 << x)`, `untyped int`},
332 {`package issue47243_j; var x int32; var _ = 1 << (2 << x)`, `2`, `untyped int`},
333
334
335 {broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
336 {broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
337 {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a, f: b,}}`, `b`, `string`},
338 {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`},
339 {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
340 {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`},
341
342
343 {`package p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T any](T)`},
344 {`package p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`},
345 {`package p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`},
346 {`package p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`},
347 {`package p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T any](T)`},
348 {`package p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`},
349
350
351 {`package t0; type t[] int; var _ t`, `t`, `t0.t`},
352 {`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P any]`},
353 {`package t2; type t[P interface{}] int; var _ t[int]`, `t`, `t2.t[P interface{}]`},
354 {`package t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `t3.t[P, Q interface{}]`},
355 {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P, Q interface{m()}]`},
356
357
358 {`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`},
359
360
361 {`package issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`},
362
363
364 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`},
365
366
367 {`package u0a; func _[_ interface{int}]() {}`, `int`, `int`},
368 {`package u1a; func _[_ interface{~int}]() {}`, `~int`, `~int`},
369 {`package u2a; func _[_ interface{int | string}]() {}`, `int | string`, `int | string`},
370 {`package u3a; func _[_ interface{int | string | ~bool}]() {}`, `int | string | ~bool`, `int | string | ~bool`},
371 {`package u3a; func _[_ interface{int | string | ~bool}]() {}`, `int | string`, `int | string`},
372 {`package u3a; func _[_ interface{int | string | ~bool}]() {}`, `~bool`, `~bool`},
373 {`package u3a; func _[_ interface{int | string | ~float64|~bool}]() {}`, `int | string | ~float64`, `int | string | ~float64`},
374
375 {`package u0b; func _[_ int]() {}`, `int`, `int`},
376 {`package u1b; func _[_ ~int]() {}`, `~int`, `~int`},
377 {`package u2b; func _[_ int | string]() {}`, `int | string`, `int | string`},
378 {`package u3b; func _[_ int | string | ~bool]() {}`, `int | string | ~bool`, `int | string | ~bool`},
379 {`package u3b; func _[_ int | string | ~bool]() {}`, `int | string`, `int | string`},
380 {`package u3b; func _[_ int | string | ~bool]() {}`, `~bool`, `~bool`},
381 {`package u3b; func _[_ int | string | ~float64|~bool]() {}`, `int | string | ~float64`, `int | string | ~float64`},
382
383 {`package u0c; type _ interface{int}`, `int`, `int`},
384 {`package u1c; type _ interface{~int}`, `~int`, `~int`},
385 {`package u2c; type _ interface{int | string}`, `int | string`, `int | string`},
386 {`package u3c; type _ interface{int | string | ~bool}`, `int | string | ~bool`, `int | string | ~bool`},
387 {`package u3c; type _ interface{int | string | ~bool}`, `int | string`, `int | string`},
388 {`package u3c; type _ interface{int | string | ~bool}`, `~bool`, `~bool`},
389 {`package u3c; type _ interface{int | string | ~float64|~bool}`, `int | string | ~float64`, `int | string | ~float64`},
390
391
392 {`package r1; var _ func(int) = g; func g[P any](P) {}`, `g`, `func(int)`},
393 {`package r2; var _ func(int) = g[int]; func g[P any](P) {}`, `g`, `func[P any](P)`},
394 {`package r3; var _ func(int) = g[int]; func g[P any](P) {}`, `g[int]`, `func(int)`},
395 {`package r4; var _ func(int, string) = g; func g[P, Q any](P, Q) {}`, `g`, `func(int, string)`},
396 {`package r5; var _ func(int, string) = g[int]; func g[P, Q any](P, Q) {}`, `g`, `func[P, Q any](P, Q)`},
397 {`package r6; var _ func(int, string) = g[int]; func g[P, Q any](P, Q) {}`, `g[int]`, `func(int, string)`},
398
399 {`package s1; func _() { f(g) }; func f(func(int)) {}; func g[P any](P) {}`, `g`, `func(int)`},
400 {`package s2; func _() { f(g[int]) }; func f(func(int)) {}; func g[P any](P) {}`, `g`, `func[P any](P)`},
401 {`package s3; func _() { f(g[int]) }; func f(func(int)) {}; func g[P any](P) {}`, `g[int]`, `func(int)`},
402 {`package s4; func _() { f(g) }; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}`, `g`, `func(int, string)`},
403 {`package s5; func _() { f(g[int]) }; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}`, `g`, `func[P, Q any](P, Q)`},
404 {`package s6; func _() { f(g[int]) }; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}`, `g[int]`, `func(int, string)`},
405
406 {`package s7; func _() { f(g, h) }; func f[P any](func(int, P), func(P, string)) {}; func g[P any](P, P) {}; func h[P, Q any](P, Q) {}`, `g`, `func(int, int)`},
407 {`package s8; func _() { f(g, h) }; func f[P any](func(int, P), func(P, string)) {}; func g[P any](P, P) {}; func h[P, Q any](P, Q) {}`, `h`, `func(int, string)`},
408 {`package s9; func _() { f(g, h[int]) }; func f[P any](func(int, P), func(P, string)) {}; func g[P any](P, P) {}; func h[P, Q any](P, Q) {}`, `h`, `func[P, Q any](P, Q)`},
409 {`package s10; func _() { f(g, h[int]) }; func f[P any](func(int, P), func(P, string)) {}; func g[P any](P, P) {}; func h[P, Q any](P, Q) {}`, `h[int]`, `func(int, string)`},
410
411
412
413
414 {`package qa1; type T int; var x T`, `T`, `qa1.T`},
415 {`package qa2; type T int; var x (T)`, `T`, `qa2.T`},
416 {`package qa3; type T int; var x (T)`, `(T)`, `qa3.T`},
417 {`package qa4; type T int; var x ((T))`, `T`, `qa4.T`},
418 {`package qa5; type T int; var x ((T))`, `(T)`, `qa5.T`},
419 {`package qa6; type T int; var x ((T))`, `((T))`, `qa6.T`},
420 {`package qa7; type T int; var x *T`, `T`, `qa7.T`},
421 {`package qa8; type T int; var x *T`, `*T`, `*qa8.T`},
422 {`package qa9; type T int; var x (*T)`, `T`, `qa9.T`},
423 {`package qa10; type T int; var x (*T)`, `*T`, `*qa10.T`},
424 {`package qa11; type T int; var x *(T)`, `T`, `qa11.T`},
425 {`package qa12; type T int; var x *(T)`, `(T)`, `qa12.T`},
426 {`package qa13; type T int; var x *(T)`, `*(T)`, `*qa13.T`},
427 {`package qa14; type T int; var x (*(T))`, `(T)`, `qa14.T`},
428 {`package qa15; type T int; var x (*(T))`, `*(T)`, `*qa15.T`},
429 {`package qa16; type T int; var x (*(T))`, `(*(T))`, `*qa16.T`},
430
431
432 {`package qb1; type T int; func _(T)`, `T`, `qb1.T`},
433 {`package qb2; type T int; func _((T))`, `T`, `qb2.T`},
434 {`package qb3; type T int; func _((T))`, `(T)`, `qb3.T`},
435 {`package qb4; type T int; func _(((T)))`, `T`, `qb4.T`},
436 {`package qb5; type T int; func _(((T)))`, `(T)`, `qb5.T`},
437 {`package qb6; type T int; func _(((T)))`, `((T))`, `qb6.T`},
438 {`package qb7; type T int; func _(*T)`, `T`, `qb7.T`},
439 {`package qb8; type T int; func _(*T)`, `*T`, `*qb8.T`},
440 {`package qb9; type T int; func _((*T))`, `T`, `qb9.T`},
441 {`package qb10; type T int; func _((*T))`, `*T`, `*qb10.T`},
442 {`package qb11; type T int; func _(*(T))`, `T`, `qb11.T`},
443 {`package qb12; type T int; func _(*(T))`, `(T)`, `qb12.T`},
444 {`package qb13; type T int; func _(*(T))`, `*(T)`, `*qb13.T`},
445 {`package qb14; type T int; func _((*(T)))`, `(T)`, `qb14.T`},
446 {`package qb15; type T int; func _((*(T)))`, `*(T)`, `*qb15.T`},
447 {`package qb16; type T int; func _((*(T)))`, `(*(T))`, `*qb16.T`},
448
449
450 {`package qc1; type T int; func (T) _() {}`, `T`, `qc1.T`},
451 {`package qc2; type T int; func ((T)) _() {}`, `T`, `qc2.T`},
452 {`package qc3; type T int; func ((T)) _() {}`, `(T)`, `qc3.T`},
453 {`package qc4; type T int; func (((T))) _() {}`, `T`, `qc4.T`},
454 {`package qc5; type T int; func (((T))) _() {}`, `(T)`, `qc5.T`},
455 {`package qc6; type T int; func (((T))) _() {}`, `((T))`, `qc6.T`},
456 {`package qc7; type T int; func (*T) _() {}`, `T`, `qc7.T`},
457 {`package qc8; type T int; func (*T) _() {}`, `*T`, `*qc8.T`},
458 {`package qc9; type T int; func ((*T)) _() {}`, `T`, `qc9.T`},
459 {`package qc10; type T int; func ((*T)) _() {}`, `*T`, `*qc10.T`},
460 {`package qc11; type T int; func (*(T)) _() {}`, `T`, `qc11.T`},
461 {`package qc12; type T int; func (*(T)) _() {}`, `(T)`, `qc12.T`},
462 {`package qc13; type T int; func (*(T)) _() {}`, `*(T)`, `*qc13.T`},
463 {`package qc14; type T int; func ((*(T))) _() {}`, `(T)`, `qc14.T`},
464 {`package qc15; type T int; func ((*(T))) _() {}`, `*(T)`, `*qc15.T`},
465 {`package qc16; type T int; func ((*(T))) _() {}`, `(*(T))`, `*qc16.T`},
466
467
468 {`package qd1; type T[_ any] int; var x T[int]`, `T`, `qd1.T[_ any]`},
469 {`package qd2; type T[_ any] int; var x (T[int])`, `T[int]`, `qd2.T[int]`},
470 {`package qd3; type T[_ any] int; var x (T[int])`, `(T[int])`, `qd3.T[int]`},
471 {`package qd4; type T[_ any] int; var x ((T[int]))`, `T`, `qd4.T[_ any]`},
472 {`package qd5; type T[_ any] int; var x ((T[int]))`, `(T[int])`, `qd5.T[int]`},
473 {`package qd6; type T[_ any] int; var x ((T[int]))`, `((T[int]))`, `qd6.T[int]`},
474 {`package qd7; type T[_ any] int; var x *T[int]`, `T`, `qd7.T[_ any]`},
475 {`package qd8; type T[_ any] int; var x *T[int]`, `*T[int]`, `*qd8.T[int]`},
476 {`package qd9; type T[_ any] int; var x (*T[int])`, `T`, `qd9.T[_ any]`},
477 {`package qd10; type T[_ any] int; var x (*T[int])`, `*T[int]`, `*qd10.T[int]`},
478 {`package qd11; type T[_ any] int; var x *(T[int])`, `T[int]`, `qd11.T[int]`},
479 {`package qd12; type T[_ any] int; var x *(T[int])`, `(T[int])`, `qd12.T[int]`},
480 {`package qd13; type T[_ any] int; var x *(T[int])`, `*(T[int])`, `*qd13.T[int]`},
481 {`package qd14; type T[_ any] int; var x (*(T[int]))`, `(T[int])`, `qd14.T[int]`},
482 {`package qd15; type T[_ any] int; var x (*(T[int]))`, `*(T[int])`, `*qd15.T[int]`},
483 {`package qd16; type T[_ any] int; var x (*(T[int]))`, `(*(T[int]))`, `*qd16.T[int]`},
484
485
486 {`package qe1; type T[_ any] int; func _(T[int])`, `T`, `qe1.T[_ any]`},
487 {`package qe2; type T[_ any] int; func _((T[int]))`, `T[int]`, `qe2.T[int]`},
488 {`package qe3; type T[_ any] int; func _((T[int]))`, `(T[int])`, `qe3.T[int]`},
489 {`package qe4; type T[_ any] int; func _(((T[int])))`, `T`, `qe4.T[_ any]`},
490 {`package qe5; type T[_ any] int; func _(((T[int])))`, `(T[int])`, `qe5.T[int]`},
491 {`package qe6; type T[_ any] int; func _(((T[int])))`, `((T[int]))`, `qe6.T[int]`},
492 {`package qe7; type T[_ any] int; func _(*T[int])`, `T`, `qe7.T[_ any]`},
493 {`package qe8; type T[_ any] int; func _(*T[int])`, `*T[int]`, `*qe8.T[int]`},
494 {`package qe9; type T[_ any] int; func _((*T[int]))`, `T`, `qe9.T[_ any]`},
495 {`package qe10; type T[_ any] int; func _((*T[int]))`, `*T[int]`, `*qe10.T[int]`},
496 {`package qe11; type T[_ any] int; func _(*(T[int]))`, `T[int]`, `qe11.T[int]`},
497 {`package qe12; type T[_ any] int; func _(*(T[int]))`, `(T[int])`, `qe12.T[int]`},
498 {`package qe13; type T[_ any] int; func _(*(T[int]))`, `*(T[int])`, `*qe13.T[int]`},
499 {`package qe14; type T[_ any] int; func _((*(T[int])))`, `(T[int])`, `qe14.T[int]`},
500 {`package qe15; type T[_ any] int; func _((*(T[int])))`, `*(T[int])`, `*qe15.T[int]`},
501 {`package qe16; type T[_ any] int; func _((*(T[int])))`, `(*(T[int]))`, `*qe16.T[int]`},
502
503
504 {`package qf1; type T[_ any] int; func (T[_]) _() {}`, `T`, `qf1.T[_ any]`},
505 {`package qf2; type T[_ any] int; func ((T[_])) _() {}`, `T[_]`, `qf2.T[_]`},
506 {`package qf3; type T[_ any] int; func ((T[_])) _() {}`, `(T[_])`, `qf3.T[_]`},
507 {`package qf4; type T[_ any] int; func (((T[_]))) _() {}`, `T`, `qf4.T[_ any]`},
508 {`package qf5; type T[_ any] int; func (((T[_]))) _() {}`, `(T[_])`, `qf5.T[_]`},
509 {`package qf6; type T[_ any] int; func (((T[_]))) _() {}`, `((T[_]))`, `qf6.T[_]`},
510 {`package qf7; type T[_ any] int; func (*T[_]) _() {}`, `T`, `qf7.T[_ any]`},
511 {`package qf8; type T[_ any] int; func (*T[_]) _() {}`, `*T[_]`, `*qf8.T[_]`},
512 {`package qf9; type T[_ any] int; func ((*T[_])) _() {}`, `T`, `qf9.T[_ any]`},
513 {`package qf10; type T[_ any] int; func ((*T[_])) _() {}`, `*T[_]`, `*qf10.T[_]`},
514 {`package qf11; type T[_ any] int; func (*(T[_])) _() {}`, `T[_]`, `qf11.T[_]`},
515 {`package qf12; type T[_ any] int; func (*(T[_])) _() {}`, `(T[_])`, `qf12.T[_]`},
516 {`package qf13; type T[_ any] int; func (*(T[_])) _() {}`, `*(T[_])`, `*qf13.T[_]`},
517 {`package qf14; type T[_ any] int; func ((*(T[_]))) _() {}`, `(T[_])`, `qf14.T[_]`},
518 {`package qf15; type T[_ any] int; func ((*(T[_]))) _() {}`, `*(T[_])`, `*qf15.T[_]`},
519 {`package qf16; type T[_ any] int; func ((*(T[_]))) _() {}`, `(*(T[_]))`, `*qf16.T[_]`},
520
521
522
523
524 {`package t1; type T[_ any] int; func (T[P]) _() {}`, `P`, `P`},
525 {`package t2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `P`},
526 {`package t3; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `Q`},
527 }
528
529 for _, test := range tests {
530 info := Info{Types: make(map[ast.Expr]TypeAndValue)}
531 var name string
532 if strings.HasPrefix(test.src, broken) {
533 pkg, err := typecheck(test.src, nil, &info)
534 if err == nil {
535 t.Errorf("package %s: expected to fail but passed", pkg.Name())
536 continue
537 }
538 if pkg != nil {
539 name = pkg.Name()
540 }
541 } else {
542 name = mustTypecheck(test.src, nil, &info).Name()
543 }
544
545
546 var typ Type
547 for e, tv := range info.Types {
548 if ExprString(e) == test.expr {
549 typ = tv.Type
550 break
551 }
552 }
553 if typ == nil {
554 t.Errorf("package %s: no type found for %s", name, test.expr)
555 continue
556 }
557
558
559 if got := typ.String(); got != test.typ {
560 t.Errorf("package %s: expr = %s: got %s; want %s", name, test.expr, got, test.typ)
561 }
562 }
563 }
564
565 func TestInstanceInfo(t *testing.T) {
566 const lib = `package lib
567
568 func F[P any](P) {}
569
570 type T[P any] []P
571 `
572
573 type testInst struct {
574 name string
575 targs []string
576 typ string
577 }
578
579 var tests = []struct {
580 src string
581 instances []testInst
582 }{
583 {`package p0; func f[T any](T) {}; func _() { f(42) }`,
584 []testInst{{`f`, []string{`int`}, `func(int)`}},
585 },
586 {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
587 []testInst{{`f`, []string{`rune`}, `func(rune) rune`}},
588 },
589 {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
590 []testInst{{`f`, []string{`complex128`}, `func(...complex128) complex128`}},
591 },
592 {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
593 []testInst{{`f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
594 },
595 {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
596 []testInst{{`f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
597 },
598
599 {`package s1; func f[T any, P interface{*T}](x T) {}; func _(x string) { f(x) }`,
600 []testInst{{`f`, []string{`string`, `*string`}, `func(x string)`}},
601 },
602 {`package s2; func f[T any, P interface{*T}](x []T) {}; func _(x []int) { f(x) }`,
603 []testInst{{`f`, []string{`int`, `*int`}, `func(x []int)`}},
604 },
605 {`package s3; type C[T any] interface{chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
606 []testInst{
607 {`C`, []string{`T`}, `interface{chan<- T}`},
608 {`f`, []string{`int`, `chan<- int`}, `func(x []int)`},
609 },
610 },
611 {`package 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) }`,
612 []testInst{
613 {`C`, []string{`T`}, `interface{chan<- T}`},
614 {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
615 {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`},
616 },
617 },
618
619 {`package t1; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = f[string] }`,
620 []testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
621 },
622 {`package t2; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
623 []testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
624 },
625 {`package t3; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
626 []testInst{
627 {`C`, []string{`T`}, `interface{chan<- T}`},
628 {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
629 {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
630 },
631 },
632 {`package t4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = (f[int]) }`,
633 []testInst{
634 {`C`, []string{`T`}, `interface{chan<- T}`},
635 {`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
636 {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
637 },
638 },
639 {`package i0; import "lib"; func _() { lib.F(42) }`,
640 []testInst{{`F`, []string{`int`}, `func(int)`}},
641 },
642
643 {`package duplfunc0; func f[T any](T) {}; func _() { f(42); f("foo"); f[int](3) }`,
644 []testInst{
645 {`f`, []string{`int`}, `func(int)`},
646 {`f`, []string{`string`}, `func(string)`},
647 {`f`, []string{`int`}, `func(int)`},
648 },
649 },
650 {`package duplfunc1; import "lib"; func _() { lib.F(42); lib.F("foo"); lib.F(3) }`,
651 []testInst{
652 {`F`, []string{`int`}, `func(int)`},
653 {`F`, []string{`string`}, `func(string)`},
654 {`F`, []string{`int`}, `func(int)`},
655 },
656 },
657
658 {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
659 []testInst{{`T`, []string{`int`}, `struct{x int}`}},
660 },
661 {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
662 []testInst{{`T`, []string{`int`}, `struct{x int}`}},
663 },
664 {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
665 []testInst{{`T`, []string{`int`}, `struct{x int}`}},
666 },
667 {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
668 []testInst{{`T`, []string{`[]int`, `int`}, `struct{x []int; y int}`}},
669 },
670 {`package type4; import "lib"; var _ lib.T[int]`,
671 []testInst{{`T`, []string{`int`}, `[]int`}},
672 },
673
674 {`package dupltype0; type T[P interface{~int}] struct{ x P }; var x T[int]; var y T[int]`,
675 []testInst{
676 {`T`, []string{`int`}, `struct{x int}`},
677 {`T`, []string{`int`}, `struct{x int}`},
678 },
679 },
680 {`package dupltype1; type T[P ~int] struct{ x P }; func (r *T[Q]) add(z T[Q]) { r.x += z.x }`,
681 []testInst{
682 {`T`, []string{`Q`}, `struct{x Q}`},
683 {`T`, []string{`Q`}, `struct{x Q}`},
684 },
685 },
686 {`package dupltype1; import "lib"; var x lib.T[int]; var y lib.T[int]; var z lib.T[string]`,
687 []testInst{
688 {`T`, []string{`int`}, `[]int`},
689 {`T`, []string{`int`}, `[]int`},
690 {`T`, []string{`string`}, `[]string`},
691 },
692 },
693 {`package issue51803; func foo[T any](T) {}; func _() { foo[int]( /* leave arg away on purpose */ ) }`,
694 []testInst{{`foo`, []string{`int`}, `func(int)`}},
695 },
696
697
698 {`package reverse1a; var f func(int) = g; func g[P any](P) {}`,
699 []testInst{{`g`, []string{`int`}, `func(int)`}},
700 },
701 {`package reverse1b; func f(func(int)) {}; func g[P any](P) {}; func _() { f(g) }`,
702 []testInst{{`g`, []string{`int`}, `func(int)`}},
703 },
704 {`package reverse2a; var f func(int, string) = g; func g[P, Q any](P, Q) {}`,
705 []testInst{{`g`, []string{`int`, `string`}, `func(int, string)`}},
706 },
707 {`package reverse2b; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}; func _() { f(g) }`,
708 []testInst{{`g`, []string{`int`, `string`}, `func(int, string)`}},
709 },
710 {`package reverse2c; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}; func _() { f(g[int]) }`,
711 []testInst{{`g`, []string{`int`, `string`}, `func(int, string)`}},
712 },
713
714 {`package reverse3b; func f[R any](func(int) R) {}; func g[P any](P) string { return "" }; func _() { f(g) }`,
715 []testInst{
716 {`f`, []string{`string`}, `func(func(int) string)`},
717 {`g`, []string{`int`}, `func(int) string`},
718 },
719 },
720 {`package reverse4a; var _, _ func([]int, *float32) = g, h; func g[P, Q any]([]P, *Q) {}; func h[R any]([]R, *float32) {}`,
721 []testInst{
722 {`g`, []string{`int`, `float32`}, `func([]int, *float32)`},
723 {`h`, []string{`int`}, `func([]int, *float32)`},
724 },
725 },
726 {`package reverse4b; func f(_, _ func([]int, *float32)) {}; func g[P, Q any]([]P, *Q) {}; func h[R any]([]R, *float32) {}; func _() { f(g, h) }`,
727 []testInst{
728 {`g`, []string{`int`, `float32`}, `func([]int, *float32)`},
729 {`h`, []string{`int`}, `func([]int, *float32)`},
730 },
731 },
732 {`package issue59956; func f(func(int), func(string), func(bool)) {}; func g[P any](P) {}; func _() { f(g, g, g) }`,
733 []testInst{
734 {`g`, []string{`int`}, `func(int)`},
735 {`g`, []string{`string`}, `func(string)`},
736 {`g`, []string{`bool`}, `func(bool)`},
737 },
738 },
739 }
740
741 for _, test := range tests {
742 imports := make(testImporter)
743 conf := Config{Importer: imports}
744 instMap := make(map[*ast.Ident]Instance)
745 useMap := make(map[*ast.Ident]Object)
746 makePkg := func(src string) *Package {
747 pkg, err := typecheck(src, &conf, &Info{Instances: instMap, Uses: useMap})
748
749 if err != nil && (pkg == nil || pkg.Name() != "issue51803") {
750 t.Fatal(err)
751 }
752 imports[pkg.Name()] = pkg
753 return pkg
754 }
755 makePkg(lib)
756 pkg := makePkg(test.src)
757
758 t.Run(pkg.Name(), func(t *testing.T) {
759
760 instances := sortedInstances(instMap)
761 if got, want := len(instances), len(test.instances); got != want {
762 t.Fatalf("got %d instances, want %d", got, want)
763 }
764
765
766 for ii, inst := range instances {
767 var targs []Type
768 for i := 0; i < inst.Inst.TypeArgs.Len(); i++ {
769 targs = append(targs, inst.Inst.TypeArgs.At(i))
770 }
771 typ := inst.Inst.Type
772
773 testInst := test.instances[ii]
774 if got := inst.Ident.Name; got != testInst.name {
775 t.Fatalf("got name %s, want %s", got, testInst.name)
776 }
777 if len(targs) != len(testInst.targs) {
778 t.Fatalf("got %d type arguments; want %d", len(targs), len(testInst.targs))
779 }
780 for i, targ := range targs {
781 if got := targ.String(); got != testInst.targs[i] {
782 t.Errorf("type argument %d: got %s; want %s", i, got, testInst.targs[i])
783 }
784 }
785 if got := typ.Underlying().String(); got != testInst.typ {
786 t.Errorf("package %s: got %s; want %s", pkg.Name(), got, testInst.typ)
787 }
788
789
790
791 ptype := useMap[inst.Ident].Type()
792 lister, _ := ptype.(interface{ TypeParams() *TypeParamList })
793 if lister == nil || lister.TypeParams().Len() == 0 {
794 t.Fatalf("info.Types[%v] = %v, want parameterized type", inst.Ident, ptype)
795 }
796 inst2, err := Instantiate(nil, ptype, targs, true)
797 if err != nil {
798 t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err)
799 }
800 if !Identical(inst.Inst.Type, inst2) {
801 t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2)
802 }
803 }
804 })
805 }
806 }
807
808 type recordedInstance struct {
809 Ident *ast.Ident
810 Inst Instance
811 }
812
813 func sortedInstances(m map[*ast.Ident]Instance) (instances []recordedInstance) {
814 for id, inst := range m {
815 instances = append(instances, recordedInstance{id, inst})
816 }
817 slices.SortFunc(instances, func(a, b recordedInstance) int {
818 return CmpPos(a.Ident.Pos(), b.Ident.Pos())
819 })
820 return instances
821 }
822
823 func TestDefsInfo(t *testing.T) {
824 var tests = []struct {
825 src string
826 obj string
827 want string
828 }{
829 {`package p0; const x = 42`, `x`, `const p0.x untyped int`},
830 {`package p1; const x int = 42`, `x`, `const p1.x int`},
831 {`package p2; var x int`, `x`, `var p2.x int`},
832 {`package p3; type x int`, `x`, `type p3.x int`},
833 {`package p4; func f()`, `f`, `func p4.f()`},
834 {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`},
835
836
837 {`package g0; type x[T any] int`, `x`, `type g0.x[T any] int`},
838 {`package g1; func f[T any]() {}`, `f`, `func g1.f[T any]()`},
839 {`package g2; type x[T any] int; func (*x[_]) m() {}`, `m`, `func (*g2.x[_]).m()`},
840
841
842 {`package r0; type T[_ any] int; func (T[P]) _() {}`, `P`, `type parameter P any`},
843 {`package r1; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `type parameter P any`},
844 {`package r2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `type parameter Q any`},
845 }
846
847 for _, test := range tests {
848 info := Info{
849 Defs: make(map[*ast.Ident]Object),
850 }
851 name := mustTypecheck(test.src, nil, &info).Name()
852
853
854 var def Object
855 for id, obj := range info.Defs {
856 if id.Name == test.obj {
857 def = obj
858 break
859 }
860 }
861 if def == nil {
862 t.Errorf("package %s: %s not found", name, test.obj)
863 continue
864 }
865
866 if got := def.String(); got != test.want {
867 t.Errorf("package %s: got %s; want %s", name, got, test.want)
868 }
869 }
870 }
871
872 func TestUsesInfo(t *testing.T) {
873 var tests = []struct {
874 src string
875 obj string
876 want string
877 }{
878 {`package p0; func _() { _ = x }; const x = 42`, `x`, `const p0.x untyped int`},
879 {`package p1; func _() { _ = x }; const x int = 42`, `x`, `const p1.x int`},
880 {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`},
881 {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`},
882 {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`},
883
884
885 {`package g0; func _[T any]() { _ = x }; const x = 42`, `x`, `const g0.x untyped int`},
886 {`package g1; func _[T any](x T) { }`, `T`, `type parameter T any`},
887 {`package g2; type N[A any] int; var _ N[int]`, `N`, `type g2.N[A any] int`},
888 {`package g3; type N[A any] int; func (N[_]) m() {}`, `N`, `type g3.N[A any] int`},
889
890
891 {`package s1; type N[A any] struct{ a A }; var f = N[int]{}.a`, `a`, `field a int`},
892 {`package s2; type N[A any] struct{ a A }; func (r N[B]) m(b B) { r.a = b }`, `a`, `field a B`},
893
894
895 {`package m0; type N[A any] int; func (r N[B]) m() { r.n() }; func (N[C]) n() {}`, `n`, `func (m0.N[B]).n()`},
896 {`package m1; type N[A any] int; func (r N[B]) m() { }; var f = N[int].m`, `m`, `func (m1.N[int]).m()`},
897 {`package m2; func _[A any](v interface{ m() A }) { v.m() }`, `m`, `func (interface).m() A`},
898 {`package m3; func f[A any]() interface{ m() A } { return nil }; var _ = f[int]().m()`, `m`, `func (interface).m() int`},
899 {`package m4; type T[A any] func() interface{ m() A }; var x T[int]; var y = x().m`, `m`, `func (interface).m() int`},
900 {`package m5; type T[A any] interface{ m() A }; func _[B any](t T[B]) { t.m() }`, `m`, `func (m5.T[B]).m() B`},
901 {`package m6; type T[A any] interface{ m() }; func _[B any](t T[B]) { t.m() }`, `m`, `func (m6.T[B]).m()`},
902 {`package m7; type T[A any] interface{ m() A }; func _(t T[int]) { t.m() }`, `m`, `func (m7.T[int]).m() int`},
903 {`package m8; type T[A any] interface{ m() }; func _(t T[int]) { t.m() }`, `m`, `func (m8.T[int]).m()`},
904 {`package m9; type T[A any] interface{ m() }; func _(t T[int]) { _ = t.m }`, `m`, `func (m9.T[int]).m()`},
905 {
906 `package m10; type E[A any] interface{ m() }; type T[B any] interface{ E[B]; n() }; func _(t T[int]) { t.m() }`,
907 `m`,
908 `func (m10.E[int]).m()`,
909 },
910 {`package m11; type T[A any] interface{ m(); n() }; func _(t1 T[int], t2 T[string]) { t1.m(); t2.n() }`, `m`, `func (m11.T[int]).m()`},
911 {`package m12; type T[A any] interface{ m(); n() }; func _(t1 T[int], t2 T[string]) { t1.m(); t2.n() }`, `n`, `func (m12.T[string]).n()`},
912
913
914
915 {`package r0; type T[_ any] int; func (T[P]) _() {}`, `P`, `type parameter P any`},
916 {`package r1; type T[_, _ any] int; func (T[P, Q]) _() {}`, `P`, `type parameter P any`},
917 {`package r2; type T[_, _ any] int; func (T[P, Q]) _() {}`, `Q`, `type parameter Q any`},
918 }
919
920 for _, test := range tests {
921 info := Info{
922 Uses: make(map[*ast.Ident]Object),
923 }
924 name := mustTypecheck(test.src, nil, &info).Name()
925
926
927 var use Object
928 for id, obj := range info.Uses {
929 if id.Name == test.obj {
930 if use != nil {
931 panic(fmt.Sprintf("multiple uses of %q", id.Name))
932 }
933 use = obj
934 }
935 }
936 if use == nil {
937 t.Errorf("package %s: %s not found", name, test.obj)
938 continue
939 }
940
941 if got := use.String(); got != test.want {
942 t.Errorf("package %s: got %s; want %s", name, got, test.want)
943 }
944 }
945 }
946
947 func TestGenericMethodInfo(t *testing.T) {
948 src := `package p
949
950 type N[A any] int
951
952 func (r N[B]) m() { r.m(); r.n() }
953
954 func (r *N[C]) n() { }
955 `
956 fset := token.NewFileSet()
957 f := mustParse(fset, src)
958 info := Info{
959 Defs: make(map[*ast.Ident]Object),
960 Uses: make(map[*ast.Ident]Object),
961 Selections: make(map[*ast.SelectorExpr]*Selection),
962 }
963 var conf Config
964 pkg, err := conf.Check("p", fset, []*ast.File{f}, &info)
965 if err != nil {
966 t.Fatal(err)
967 }
968
969 N := pkg.Scope().Lookup("N").Type().(*Named)
970
971
972 gm, gn := N.Method(0), N.Method(1)
973 if gm.Name() == "n" {
974 gm, gn = gn, gm
975 }
976
977
978 var dm, dn *Func
979 var dmm, dmn *Func
980 for _, decl := range f.Decls {
981 fdecl, ok := decl.(*ast.FuncDecl)
982 if !ok {
983 continue
984 }
985 def := info.Defs[fdecl.Name].(*Func)
986 switch fdecl.Name.Name {
987 case "m":
988 dm = def
989 ast.Inspect(fdecl.Body, func(n ast.Node) bool {
990 if call, ok := n.(*ast.CallExpr); ok {
991 sel := call.Fun.(*ast.SelectorExpr)
992 use := info.Uses[sel.Sel].(*Func)
993 selection := info.Selections[sel]
994 if selection.Kind() != MethodVal {
995 t.Errorf("Selection kind = %v, want %v", selection.Kind(), MethodVal)
996 }
997 if selection.Obj() != use {
998 t.Errorf("info.Selections contains %v, want %v", selection.Obj(), use)
999 }
1000 switch sel.Sel.Name {
1001 case "m":
1002 dmm = use
1003 case "n":
1004 dmn = use
1005 }
1006 }
1007 return true
1008 })
1009 case "n":
1010 dn = def
1011 }
1012 }
1013
1014 if gm != dm {
1015 t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm)
1016 }
1017 if gn != dn {
1018 t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm)
1019 }
1020 if dmm != dm {
1021 t.Errorf(`Inside "m", r.m uses %v, want the defined func %v`, dmm, dm)
1022 }
1023 if dmn == dn {
1024 t.Errorf(`Inside "m", r.n uses %v, want a func distinct from %v`, dmm, dm)
1025 }
1026 }
1027
1028 func TestImplicitsInfo(t *testing.T) {
1029 testenv.MustHaveGoBuild(t)
1030
1031 var tests = []struct {
1032 src string
1033 want string
1034 }{
1035 {`package p2; import . "fmt"; var _ = Println`, ""},
1036 {`package p0; import local "fmt"; var _ = local.Println`, ""},
1037 {`package p1; import "fmt"; var _ = fmt.Println`, "importSpec: package fmt"},
1038
1039 {`package p3; func f(x interface{}) { switch x.(type) { case int: } }`, ""},
1040 {`package p4; func f(x interface{}) { switch t := x.(type) { case int: _ = t } }`, "caseClause: var t int"},
1041 {`package p5; func f(x interface{}) { switch t := x.(type) { case int, uint: _ = t } }`, "caseClause: var t interface{}"},
1042 {`package p6; func f(x interface{}) { switch t := x.(type) { default: _ = t } }`, "caseClause: var t interface{}"},
1043
1044 {`package p7; func f(x int) {}`, ""},
1045 {`package p8; func f(int) {}`, "field: var int"},
1046 {`package p9; func f() (complex64) { return 0 }`, "field: var complex64"},
1047 {`package p10; type T struct{}; func (*T) f() {}`, "field: var *p10.T"},
1048
1049
1050 {`package f0; func f[T any](x int) {}`, ""},
1051 {`package f1; func f[T any](int) {}`, "field: var int"},
1052 {`package f2; func f[T any](T) {}`, "field: var T"},
1053 {`package f3; func f[T any]() (complex64) { return 0 }`, "field: var complex64"},
1054 {`package f4; func f[T any](t T) (T) { return t }`, "field: var T"},
1055 {`package t0; type T[A any] struct{}; func (*T[_]) f() {}`, "field: var *t0.T[_]"},
1056 {`package t1; type T[A any] struct{}; func _(x interface{}) { switch t := x.(type) { case T[int]: _ = t } }`, "caseClause: var t t1.T[int]"},
1057 {`package t2; type T[A any] struct{}; func _[P any](x interface{}) { switch t := x.(type) { case T[P]: _ = t } }`, "caseClause: var t t2.T[P]"},
1058 {`package t3; func _[P any](x interface{}) { switch t := x.(type) { case P: _ = t } }`, "caseClause: var t P"},
1059 }
1060
1061 for _, test := range tests {
1062 info := Info{
1063 Implicits: make(map[ast.Node]Object),
1064 }
1065 name := mustTypecheck(test.src, nil, &info).Name()
1066
1067
1068 if len(info.Implicits) > 1 {
1069 t.Errorf("package %s: %d Implicits entries found", name, len(info.Implicits))
1070 continue
1071 }
1072
1073
1074 var got string
1075 for n, obj := range info.Implicits {
1076 switch x := n.(type) {
1077 case *ast.ImportSpec:
1078 got = "importSpec"
1079 case *ast.CaseClause:
1080 got = "caseClause"
1081 case *ast.Field:
1082 got = "field"
1083 default:
1084 t.Fatalf("package %s: unexpected %T", name, x)
1085 }
1086 got += ": " + obj.String()
1087 }
1088
1089
1090 if got != test.want {
1091 t.Errorf("package %s: got %q; want %q", name, got, test.want)
1092 }
1093 }
1094 }
1095
1096 func TestPkgNameOf(t *testing.T) {
1097 testenv.MustHaveGoBuild(t)
1098
1099 const src = `
1100 package p
1101
1102 import (
1103 . "os"
1104 _ "io"
1105 "math"
1106 "path/filepath"
1107 snort "sort"
1108 )
1109
1110 // avoid imported and not used errors
1111 var (
1112 _ = Open // os.Open
1113 _ = math.Sin
1114 _ = filepath.Abs
1115 _ = snort.Ints
1116 )
1117 `
1118
1119 var tests = []struct {
1120 path string
1121 want string
1122 }{
1123 {`"os"`, "."},
1124 {`"io"`, "_"},
1125 {`"math"`, "math"},
1126 {`"path/filepath"`, "filepath"},
1127 {`"sort"`, "snort"},
1128 }
1129
1130 fset := token.NewFileSet()
1131 f := mustParse(fset, src)
1132 info := Info{
1133 Defs: make(map[*ast.Ident]Object),
1134 Implicits: make(map[ast.Node]Object),
1135 }
1136 var conf Config
1137 conf.Importer = defaultImporter(fset)
1138 _, err := conf.Check("p", fset, []*ast.File{f}, &info)
1139 if err != nil {
1140 t.Fatal(err)
1141 }
1142
1143
1144 imports := make(map[string]*ast.ImportSpec)
1145 for _, s := range f.Decls[0].(*ast.GenDecl).Specs {
1146 if imp, _ := s.(*ast.ImportSpec); imp != nil {
1147 imports[imp.Path.Value] = imp
1148 }
1149 }
1150
1151 for _, test := range tests {
1152 imp := imports[test.path]
1153 if imp == nil {
1154 t.Fatalf("invalid test case: import path %s not found", test.path)
1155 }
1156 got := info.PkgNameOf(imp)
1157 if got == nil {
1158 t.Fatalf("import %s: package name not found", test.path)
1159 }
1160 if got.Name() != test.want {
1161 t.Errorf("import %s: got %s; want %s", test.path, got.Name(), test.want)
1162 }
1163 }
1164
1165
1166 if got := info.PkgNameOf(new(ast.ImportSpec)); got != nil {
1167 t.Errorf("got %s for non-existing import declaration", got.Name())
1168 }
1169 }
1170
1171 func predString(tv TypeAndValue) string {
1172 var buf strings.Builder
1173 pred := func(b bool, s string) {
1174 if b {
1175 if buf.Len() > 0 {
1176 buf.WriteString(", ")
1177 }
1178 buf.WriteString(s)
1179 }
1180 }
1181
1182 pred(tv.IsVoid(), "void")
1183 pred(tv.IsType(), "type")
1184 pred(tv.IsBuiltin(), "builtin")
1185 pred(tv.IsValue() && tv.Value != nil, "const")
1186 pred(tv.IsValue() && tv.Value == nil, "value")
1187 pred(tv.IsNil(), "nil")
1188 pred(tv.Addressable(), "addressable")
1189 pred(tv.Assignable(), "assignable")
1190 pred(tv.HasOk(), "hasOk")
1191
1192 if buf.Len() == 0 {
1193 return "invalid"
1194 }
1195 return buf.String()
1196 }
1197
1198 func TestPredicatesInfo(t *testing.T) {
1199 testenv.MustHaveGoBuild(t)
1200
1201 var tests = []struct {
1202 src string
1203 expr string
1204 pred string
1205 }{
1206
1207 {`package n0; func f() { f() }`, `f()`, `void`},
1208
1209
1210 {`package t0; type _ int`, `int`, `type`},
1211 {`package t1; type _ []int`, `[]int`, `type`},
1212 {`package t2; type _ func()`, `func()`, `type`},
1213 {`package t3; type _ func(int)`, `int`, `type`},
1214 {`package t3; type _ func(...int)`, `...int`, `type`},
1215
1216
1217 {`package b0; var _ = len("")`, `len`, `builtin`},
1218 {`package b1; var _ = (len)("")`, `(len)`, `builtin`},
1219
1220
1221 {`package c0; var _ = 42`, `42`, `const`},
1222 {`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`},
1223 {`package c2; const (i = 1i; _ = i)`, `i`, `const`},
1224
1225
1226 {`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
1227 {`package v1; var _ = &[]int{1}`, `[]int{…}`, `value`},
1228 {`package v2; var _ = func(){}`, `(func() literal)`, `value`},
1229 {`package v4; func f() { _ = f }`, `f`, `value`},
1230 {`package v3; var _ *int = nil`, `nil`, `value, nil`},
1231 {`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
1232
1233
1234 {`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`},
1235 {`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`},
1236 {`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`},
1237 {`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`},
1238 {`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`},
1239 {`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`},
1240 {`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`},
1241 {`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`},
1242
1243
1244
1245 {`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
1246 {`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
1247
1248
1249 {`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`},
1250 {`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`},
1251
1252
1253
1254
1255 {`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`},
1256 {`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`},
1257 {`package m2; const c = 0`, `c`, `<missing>`},
1258 {`package m3; type T int`, `T`, `<missing>`},
1259 {`package m4; var v int`, `v`, `<missing>`},
1260 {`package m5; func f() {}`, `f`, `<missing>`},
1261 {`package m6; func _(x int) {}`, `x`, `<missing>`},
1262 {`package m6; func _()(x int) { return }`, `x`, `<missing>`},
1263 {`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`},
1264 }
1265
1266 for _, test := range tests {
1267 info := Info{Types: make(map[ast.Expr]TypeAndValue)}
1268 name := mustTypecheck(test.src, nil, &info).Name()
1269
1270
1271 got := "<missing>"
1272 for e, tv := range info.Types {
1273
1274 if ExprString(e) == test.expr {
1275 got = predString(tv)
1276 break
1277 }
1278 }
1279
1280 if got != test.pred {
1281 t.Errorf("package %s: got %s; want %s", name, got, test.pred)
1282 }
1283 }
1284 }
1285
1286 func TestScopesInfo(t *testing.T) {
1287 testenv.MustHaveGoBuild(t)
1288
1289 var tests = []struct {
1290 src string
1291 scopes []string
1292 }{
1293 {`package p0`, []string{
1294 "file:",
1295 }},
1296 {`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
1297 "file:fmt m",
1298 }},
1299 {`package p2; func _() {}`, []string{
1300 "file:", "func:",
1301 }},
1302 {`package p3; func _(x, y int) {}`, []string{
1303 "file:", "func:x y",
1304 }},
1305 {`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
1306 "file:", "func:x y z",
1307 }},
1308 {`package p5; func _(x, y int) (u, _ int) { return }`, []string{
1309 "file:", "func:u x y",
1310 }},
1311 {`package p6; func _() { { var x int; _ = x } }`, []string{
1312 "file:", "func:", "block:x",
1313 }},
1314 {`package p7; func _() { if true {} }`, []string{
1315 "file:", "func:", "if:", "block:",
1316 }},
1317 {`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
1318 "file:", "func:", "if:x", "block:y",
1319 }},
1320 {`package p9; func _() { switch x := 0; x {} }`, []string{
1321 "file:", "func:", "switch:x",
1322 }},
1323 {`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
1324 "file:", "func:", "switch:x", "case:y", "case:",
1325 }},
1326 {`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
1327 "file:", "func:t", "type switch:",
1328 }},
1329 {`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
1330 "file:", "func:t", "type switch:t",
1331 }},
1332 {`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
1333 "file:", "func:t", "type switch:", "case:x",
1334 }},
1335 {`package p14; func _() { select{} }`, []string{
1336 "file:", "func:",
1337 }},
1338 {`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
1339 "file:", "func:c", "comm:",
1340 }},
1341 {`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
1342 "file:", "func:c", "comm:i x",
1343 }},
1344 {`package p17; func _() { for{} }`, []string{
1345 "file:", "func:", "for:", "block:",
1346 }},
1347 {`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
1348 "file:", "func:n", "for:i", "block:",
1349 }},
1350 {`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
1351 "file:", "func:a", "range:i", "block:",
1352 }},
1353 {`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
1354 "file:", "func:a", "range:i x", "block:",
1355 }},
1356 }
1357
1358 for _, test := range tests {
1359 info := Info{Scopes: make(map[ast.Node]*Scope)}
1360 name := mustTypecheck(test.src, nil, &info).Name()
1361
1362
1363 if len(info.Scopes) != len(test.scopes) {
1364 t.Errorf("package %s: got %d scopes; want %d", name, len(info.Scopes), len(test.scopes))
1365 }
1366
1367
1368 for node, scope := range info.Scopes {
1369 kind := "<unknown node kind>"
1370 switch node.(type) {
1371 case *ast.File:
1372 kind = "file"
1373 case *ast.FuncType:
1374 kind = "func"
1375 case *ast.BlockStmt:
1376 kind = "block"
1377 case *ast.IfStmt:
1378 kind = "if"
1379 case *ast.SwitchStmt:
1380 kind = "switch"
1381 case *ast.TypeSwitchStmt:
1382 kind = "type switch"
1383 case *ast.CaseClause:
1384 kind = "case"
1385 case *ast.CommClause:
1386 kind = "comm"
1387 case *ast.ForStmt:
1388 kind = "for"
1389 case *ast.RangeStmt:
1390 kind = "range"
1391 }
1392
1393
1394 desc := kind + ":" + strings.Join(scope.Names(), " ")
1395 if !slices.Contains(test.scopes, desc) {
1396 t.Errorf("package %s: no matching scope found for %s", name, desc)
1397 }
1398 }
1399 }
1400 }
1401
1402 func TestInitOrderInfo(t *testing.T) {
1403 var tests = []struct {
1404 src string
1405 inits []string
1406 }{
1407 {`package p0; var (x = 1; y = x)`, []string{
1408 "x = 1", "y = x",
1409 }},
1410 {`package p1; var (a = 1; b = 2; c = 3)`, []string{
1411 "a = 1", "b = 2", "c = 3",
1412 }},
1413 {`package p2; var (a, b, c = 1, 2, 3)`, []string{
1414 "a = 1", "b = 2", "c = 3",
1415 }},
1416 {`package p3; var _ = f(); func f() int { return 1 }`, []string{
1417 "_ = f()",
1418 }},
1419 {`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{
1420 "a = 0", "z = 0", "y = z", "x = y",
1421 }},
1422 {`package p5; var (a, _ = m[0]; m map[int]string)`, []string{
1423 "a, _ = m[0]",
1424 }},
1425 {`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{
1426 "z = 0", "a, b = f()",
1427 }},
1428 {`package p7; var (a = func() int { return b }(); b = 1)`, []string{
1429 "b = 1", "a = (func() int literal)()",
1430 }},
1431 {`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
1432 "c = 1", "a, b = (func() (_, _ int) literal)()",
1433 }},
1434 {`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
1435 "y = 1", "x = T.m",
1436 }},
1437 {`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{
1438 "a = 0", "b = 0", "c = 0", "d = c + b",
1439 }},
1440 {`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{
1441 "c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c",
1442 }},
1443
1444
1445 {`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{
1446 "b = 0", "x, y = m[0]", "a = x",
1447 }},
1448
1449 {`package p12
1450
1451 var (
1452 a = c + b
1453 b = f()
1454 c = f()
1455 d = 3
1456 )
1457
1458 func f() int {
1459 d++
1460 return d
1461 }`, []string{
1462 "d = 3", "b = f()", "c = f()", "a = c + b",
1463 }},
1464
1465 {`package main
1466
1467 var counter int
1468 func next() int { counter++; return counter }
1469
1470 var _ = makeOrder()
1471 func makeOrder() []int { return []int{f, b, d, e, c, a} }
1472
1473 var a = next()
1474 var b, c = next(), next()
1475 var d, e, f = next(), next(), next()
1476 `, []string{
1477 "a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
1478 }},
1479
1480 {`package p13
1481
1482 var (
1483 v = t.m()
1484 t = makeT(0)
1485 )
1486
1487 type T struct{}
1488
1489 func (T) m() int { return 0 }
1490
1491 func makeT(n int) T {
1492 if n > 0 {
1493 return makeT(n-1)
1494 }
1495 return T{}
1496 }`, []string{
1497 "t = makeT(0)", "v = t.m()",
1498 }},
1499
1500 {`package p14
1501
1502 var (
1503 t = makeT(0)
1504 v = t.m()
1505 )
1506
1507 type T struct{}
1508
1509 func (T) m() int { return 0 }
1510
1511 func makeT(n int) T {
1512 if n > 0 {
1513 return makeT(n-1)
1514 }
1515 return T{}
1516 }`, []string{
1517 "t = makeT(0)", "v = t.m()",
1518 }},
1519
1520 {`package p15
1521
1522 var y1 = f1()
1523
1524 func f1() int { return g1() }
1525 func g1() int { f1(); return x1 }
1526
1527 var x1 = 0
1528
1529 var y2 = f2()
1530
1531 func f2() int { return g2() }
1532 func g2() int { return x2 }
1533
1534 var x2 = 0`, []string{
1535 "x1 = 0", "y1 = f1()", "x2 = 0", "y2 = f2()",
1536 }},
1537 }
1538
1539 for _, test := range tests {
1540 info := Info{}
1541 name := mustTypecheck(test.src, nil, &info).Name()
1542
1543
1544 if len(info.InitOrder) != len(test.inits) {
1545 t.Errorf("package %s: got %d initializers; want %d", name, len(info.InitOrder), len(test.inits))
1546 continue
1547 }
1548
1549
1550 for i, want := range test.inits {
1551 got := info.InitOrder[i].String()
1552 if got != want {
1553 t.Errorf("package %s, init %d: got %s; want %s", name, i, got, want)
1554 continue
1555 }
1556 }
1557 }
1558 }
1559
1560 func TestMultiFileInitOrder(t *testing.T) {
1561 fset := token.NewFileSet()
1562 fileA := mustParse(fset, `package main; var a = 1`)
1563 fileB := mustParse(fset, `package main; var b = 2`)
1564
1565
1566
1567
1568 for _, test := range []struct {
1569 files []*ast.File
1570 want string
1571 }{
1572 {[]*ast.File{fileA, fileB}, "[a = 1 b = 2]"},
1573 {[]*ast.File{fileB, fileA}, "[b = 2 a = 1]"},
1574 } {
1575 var info Info
1576 if _, err := new(Config).Check("main", fset, test.files, &info); err != nil {
1577 t.Fatal(err)
1578 }
1579 if got := fmt.Sprint(info.InitOrder); got != test.want {
1580 t.Fatalf("got %s; want %s", got, test.want)
1581 }
1582 }
1583 }
1584
1585 func TestFiles(t *testing.T) {
1586 var sources = []string{
1587 "package p; type T struct{}; func (T) m1() {}",
1588 "package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}",
1589 "package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}",
1590 "package p",
1591 }
1592
1593 var conf Config
1594 fset := token.NewFileSet()
1595 pkg := NewPackage("p", "p")
1596 var info Info
1597 check := NewChecker(&conf, fset, pkg, &info)
1598
1599 for _, src := range sources {
1600 if err := check.Files([]*ast.File{mustParse(fset, src)}); err != nil {
1601 t.Error(err)
1602 }
1603 }
1604
1605
1606 var vars []string
1607 for _, init := range info.InitOrder {
1608 for _, v := range init.Lhs {
1609 vars = append(vars, v.Name())
1610 }
1611 }
1612 if got, want := fmt.Sprint(vars), "[x y]"; got != want {
1613 t.Errorf("InitOrder == %s, want %s", got, want)
1614 }
1615 }
1616
1617 type testImporter map[string]*Package
1618
1619 func (m testImporter) Import(path string) (*Package, error) {
1620 if pkg := m[path]; pkg != nil {
1621 return pkg, nil
1622 }
1623 return nil, fmt.Errorf("package %q not found", path)
1624 }
1625
1626 func TestSelection(t *testing.T) {
1627 selections := make(map[*ast.SelectorExpr]*Selection)
1628
1629
1630
1631 fset := token.NewFileSet()
1632 imports := make(testImporter)
1633 conf := Config{Importer: imports}
1634 makePkg := func(path, src string) {
1635 pkg, err := conf.Check(path, fset, []*ast.File{mustParse(fset, src)}, &Info{Selections: selections})
1636 if err != nil {
1637 t.Fatal(err)
1638 }
1639 imports[path] = pkg
1640 }
1641
1642 const libSrc = `
1643 package lib
1644 type T float64
1645 const C T = 3
1646 var V T
1647 func F() {}
1648 func (T) M() {}
1649 `
1650 const mainSrc = `
1651 package main
1652 import "lib"
1653
1654 type A struct {
1655 *B
1656 C
1657 }
1658
1659 type B struct {
1660 b int
1661 }
1662
1663 func (B) f(int)
1664
1665 type C struct {
1666 c int
1667 }
1668
1669 type G[P any] struct {
1670 p P
1671 }
1672
1673 func (G[P]) m(P) {}
1674
1675 var Inst G[int]
1676
1677 func (C) g()
1678 func (*C) h()
1679
1680 func main() {
1681 // qualified identifiers
1682 var _ lib.T
1683 _ = lib.C
1684 _ = lib.F
1685 _ = lib.V
1686 _ = lib.T.M
1687
1688 // fields
1689 _ = A{}.B
1690 _ = new(A).B
1691
1692 _ = A{}.C
1693 _ = new(A).C
1694
1695 _ = A{}.b
1696 _ = new(A).b
1697
1698 _ = A{}.c
1699 _ = new(A).c
1700
1701 _ = Inst.p
1702 _ = G[string]{}.p
1703
1704 // methods
1705 _ = A{}.f
1706 _ = new(A).f
1707 _ = A{}.g
1708 _ = new(A).g
1709 _ = new(A).h
1710
1711 _ = B{}.f
1712 _ = new(B).f
1713
1714 _ = C{}.g
1715 _ = new(C).g
1716 _ = new(C).h
1717 _ = Inst.m
1718
1719 // method expressions
1720 _ = A.f
1721 _ = (*A).f
1722 _ = B.f
1723 _ = (*B).f
1724 _ = G[string].m
1725 }`
1726
1727 wantOut := map[string][2]string{
1728 "lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"},
1729
1730 "A{}.B": {"field (main.A) B *main.B", ".[0]"},
1731 "new(A).B": {"field (*main.A) B *main.B", "->[0]"},
1732 "A{}.C": {"field (main.A) C main.C", ".[1]"},
1733 "new(A).C": {"field (*main.A) C main.C", "->[1]"},
1734 "A{}.b": {"field (main.A) b int", "->[0 0]"},
1735 "new(A).b": {"field (*main.A) b int", "->[0 0]"},
1736 "A{}.c": {"field (main.A) c int", ".[1 0]"},
1737 "new(A).c": {"field (*main.A) c int", "->[1 0]"},
1738 "Inst.p": {"field (main.G[int]) p int", ".[0]"},
1739
1740 "A{}.f": {"method (main.A) f(int)", "->[0 0]"},
1741 "new(A).f": {"method (*main.A) f(int)", "->[0 0]"},
1742 "A{}.g": {"method (main.A) g()", ".[1 0]"},
1743 "new(A).g": {"method (*main.A) g()", "->[1 0]"},
1744 "new(A).h": {"method (*main.A) h()", "->[1 1]"},
1745 "B{}.f": {"method (main.B) f(int)", ".[0]"},
1746 "new(B).f": {"method (*main.B) f(int)", "->[0]"},
1747 "C{}.g": {"method (main.C) g()", ".[0]"},
1748 "new(C).g": {"method (*main.C) g()", "->[0]"},
1749 "new(C).h": {"method (*main.C) h()", "->[1]"},
1750 "Inst.m": {"method (main.G[int]) m(int)", ".[0]"},
1751
1752 "A.f": {"method expr (main.A) f(main.A, int)", "->[0 0]"},
1753 "(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"},
1754 "B.f": {"method expr (main.B) f(main.B, int)", ".[0]"},
1755 "(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"},
1756 "G[string].m": {"method expr (main.G[string]) m(main.G[string], string)", ".[0]"},
1757 "G[string]{}.p": {"field (main.G[string]) p string", ".[0]"},
1758 }
1759
1760 makePkg("lib", libSrc)
1761 makePkg("main", mainSrc)
1762
1763 for e, sel := range selections {
1764 _ = sel.String()
1765
1766 start := fset.Position(e.Pos()).Offset
1767 end := fset.Position(e.End()).Offset
1768 syntax := mainSrc[start:end]
1769
1770 direct := "."
1771 if sel.Indirect() {
1772 direct = "->"
1773 }
1774 got := [2]string{
1775 sel.String(),
1776 fmt.Sprintf("%s%v", direct, sel.Index()),
1777 }
1778 want := wantOut[syntax]
1779 if want != got {
1780 t.Errorf("%s: got %q; want %q", syntax, got, want)
1781 }
1782 delete(wantOut, syntax)
1783
1784
1785
1786
1787 sig, _ := sel.Type().(*Signature)
1788 if sel.Kind() == MethodVal {
1789 got := sig.Recv().Type()
1790 want := sel.Recv()
1791 if !Identical(got, want) {
1792 t.Errorf("%s: Recv() = %s, want %s", syntax, got, want)
1793 }
1794 } else if sig != nil && sig.Recv() != nil {
1795 t.Errorf("%s: signature has receiver %s", sig, sig.Recv().Type())
1796 }
1797 }
1798
1799 for syntax := range wantOut {
1800 t.Errorf("no ast.Selection found with syntax %q", syntax)
1801 }
1802 }
1803
1804 func TestIssue8518(t *testing.T) {
1805 fset := token.NewFileSet()
1806 imports := make(testImporter)
1807 conf := Config{
1808 Error: func(err error) { t.Log(err) },
1809 Importer: imports,
1810 }
1811 makePkg := func(path, src string) {
1812 imports[path], _ = conf.Check(path, fset, []*ast.File{mustParse(fset, src)}, nil)
1813 }
1814
1815 const libSrc = `
1816 package a
1817 import "missing"
1818 const C1 = foo
1819 const C2 = missing.C
1820 `
1821
1822 const mainSrc = `
1823 package main
1824 import "a"
1825 var _ = a.C1
1826 var _ = a.C2
1827 `
1828
1829 makePkg("a", libSrc)
1830 makePkg("main", mainSrc)
1831 }
1832
1833 func TestIssue59603(t *testing.T) {
1834 fset := token.NewFileSet()
1835 imports := make(testImporter)
1836 conf := Config{
1837 Error: func(err error) { t.Log(err) },
1838 Importer: imports,
1839 }
1840 makePkg := func(path, src string) {
1841 imports[path], _ = conf.Check(path, fset, []*ast.File{mustParse(fset, src)}, nil)
1842 }
1843
1844 const libSrc = `
1845 package a
1846 const C = foo
1847 `
1848
1849 const mainSrc = `
1850 package main
1851 import "a"
1852 const _ = a.C
1853 `
1854
1855 makePkg("a", libSrc)
1856 makePkg("main", mainSrc)
1857 }
1858
1859 func TestLookupFieldOrMethodOnNil(t *testing.T) {
1860
1861 defer func() {
1862 const want = "LookupFieldOrMethod on nil type"
1863 p := recover()
1864 if s, ok := p.(string); !ok || s != want {
1865 t.Fatalf("got %v, want %s", p, want)
1866 }
1867 }()
1868 LookupFieldOrMethod(nil, false, nil, "")
1869 }
1870
1871 func TestLookupFieldOrMethod(t *testing.T) {
1872
1873
1874
1875
1876
1877 var tests = []struct {
1878 src string
1879 found bool
1880 index []int
1881 indirect bool
1882 }{
1883
1884 {"var x T; type T struct{}", false, nil, false},
1885 {"var x T; type T struct{ f int }", true, []int{0}, false},
1886 {"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
1887
1888
1889 {"var x T[int]; type T[P any] struct{}", false, nil, false},
1890 {"var x T[int]; type T[P any] struct{ f P }", true, []int{0}, false},
1891 {"var x T[int]; type T[P any] struct{ a, b, f, c P }", true, []int{2}, false},
1892
1893
1894 {"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
1895 {"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
1896 {"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
1897 {"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true},
1898
1899
1900 {"var a T[int]; type T[P any] struct{}; func (T[P]) f() {}", true, []int{0}, false},
1901 {"var a *T[int]; type T[P any] struct{}; func (T[P]) f() {}", true, []int{0}, true},
1902 {"var a T[int]; type T[P any] struct{}; func (*T[P]) f() {}", true, []int{0}, false},
1903 {"var a *T[int]; type T[P any] struct{}; func (*T[P]) f() {}", true, []int{0}, true},
1904
1905
1906 {"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
1907 {"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
1908
1909
1910 {"type ( E1[P any] struct{ f P }; E2[P any] struct{ f P }; x struct{ E1[int]; *E2[int] })", false, []int{1, 0}, false},
1911 {"type ( E1[P any] struct{ f P }; E2[P any] struct{}; x struct{ E1[int]; *E2[int] }); func (E2[P]) f() {}", false, []int{1, 0}, false},
1912
1913
1914
1915 {"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
1916
1917
1918 {"var x T[int]; type T[P any] struct{}; func (*T[P]) f() {}", false, nil, true},
1919
1920
1921 {"var a T[int]; type ( T[P any] struct { *N[P] }; N[P any] struct { *T[P] } ); func (N[P]) f() {}", true, []int{0, 0}, true},
1922 {"var a T[int]; type ( T[P any] struct { *N[P] }; N[P any] struct { *T[P] } ); func (T[P]) f() {}", true, []int{0}, false},
1923 }
1924
1925 for _, test := range tests {
1926 pkg := mustTypecheck("package p;"+test.src, nil, nil)
1927
1928 obj := pkg.Scope().Lookup("a")
1929 if obj == nil {
1930 if obj = pkg.Scope().Lookup("x"); obj == nil {
1931 t.Errorf("%s: incorrect test case - no object a or x", test.src)
1932 continue
1933 }
1934 }
1935
1936 f, index, indirect := LookupFieldOrMethod(obj.Type(), obj.Name() == "a", pkg, "f")
1937 if (f != nil) != test.found {
1938 if f == nil {
1939 t.Errorf("%s: got no object; want one", test.src)
1940 } else {
1941 t.Errorf("%s: got object = %v; want none", test.src, f)
1942 }
1943 }
1944 if !slices.Equal(index, test.index) {
1945 t.Errorf("%s: got index = %v; want %v", test.src, index, test.index)
1946 }
1947 if indirect != test.indirect {
1948 t.Errorf("%s: got indirect = %v; want %v", test.src, indirect, test.indirect)
1949 }
1950 }
1951 }
1952
1953
1954 func TestLookupFieldOrMethod_RecursiveGeneric(t *testing.T) {
1955 const src = `
1956 package pkg
1957
1958 type Tree[T any] struct {
1959 *Node[T]
1960 }
1961
1962 func (*Tree[R]) N(r R) R { return r }
1963
1964 type Node[T any] struct {
1965 *Tree[T]
1966 }
1967
1968 type Instance = *Tree[int]
1969 `
1970
1971 fset := token.NewFileSet()
1972 f := mustParse(fset, src)
1973 pkg := NewPackage("pkg", f.Name.Name)
1974 if err := NewChecker(nil, fset, pkg, nil).Files([]*ast.File{f}); err != nil {
1975 panic(err)
1976 }
1977
1978 T := pkg.Scope().Lookup("Instance").Type()
1979 _, _, _ = LookupFieldOrMethod(T, false, pkg, "M")
1980 }
1981
1982
1983
1984 func newDefined(underlying Type) *Named {
1985 tname := NewTypeName(nopos, nil, "T", nil)
1986 return NewNamed(tname, underlying, nil)
1987 }
1988
1989 func TestConvertibleTo(t *testing.T) {
1990 for _, test := range []struct {
1991 v, t Type
1992 want bool
1993 }{
1994 {Typ[Int], Typ[Int], true},
1995 {Typ[Int], Typ[Float32], true},
1996 {Typ[Int], Typ[String], true},
1997 {newDefined(Typ[Int]), Typ[Int], true},
1998 {newDefined(new(Struct)), new(Struct), true},
1999 {newDefined(Typ[Int]), new(Struct), false},
2000 {Typ[UntypedInt], Typ[Int], true},
2001 {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), true},
2002 {NewSlice(Typ[Int]), NewArray(Typ[Uint], 10), false},
2003 {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true},
2004 {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false},
2005
2006 {Typ[UntypedString], Typ[String], true},
2007 } {
2008 if got := ConvertibleTo(test.v, test.t); got != test.want {
2009 t.Errorf("ConvertibleTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want)
2010 }
2011 }
2012 }
2013
2014 func TestAssignableTo(t *testing.T) {
2015 for _, test := range []struct {
2016 v, t Type
2017 want bool
2018 }{
2019 {Typ[Int], Typ[Int], true},
2020 {Typ[Int], Typ[Float32], false},
2021 {newDefined(Typ[Int]), Typ[Int], false},
2022 {newDefined(new(Struct)), new(Struct), true},
2023 {Typ[UntypedBool], Typ[Bool], true},
2024 {Typ[UntypedString], Typ[Bool], false},
2025
2026
2027
2028 {Typ[UntypedString], Typ[String], true},
2029 {Typ[UntypedInt], Typ[Int], true},
2030 } {
2031 if got := AssignableTo(test.v, test.t); got != test.want {
2032 t.Errorf("AssignableTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want)
2033 }
2034 }
2035 }
2036
2037 func TestIdentical(t *testing.T) {
2038
2039 tests := []struct {
2040 src string
2041 want bool
2042 }{
2043
2044 {"var X int; var Y int", true},
2045 {"var X int; var Y string", false},
2046
2047
2048
2049
2050 {"type X int; type Y int", false},
2051
2052
2053 {"type X = int; type Y = int", true},
2054
2055
2056 {`func X(int) string { return "" }; func Y(int) string { return "" }`, true},
2057 {`func X() string { return "" }; func Y(int) string { return "" }`, false},
2058 {`func X(int) string { return "" }; func Y(int) {}`, false},
2059
2060
2061
2062 {`func X[P ~int](){}; func Y[Q ~int]() {}`, true},
2063 {`func X[P1 any, P2 ~*P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, true},
2064 {`func X[P1 any, P2 ~[]P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, false},
2065 {`func X[P ~int](P){}; func Y[Q ~int](Q) {}`, true},
2066 {`func X[P ~string](P){}; func Y[Q ~int](Q) {}`, false},
2067 {`func X[P ~int]([]P){}; func Y[Q ~int]([]Q) {}`, true},
2068 }
2069
2070 for _, test := range tests {
2071 pkg := mustTypecheck("package p;"+test.src, nil, nil)
2072 X := pkg.Scope().Lookup("X")
2073 Y := pkg.Scope().Lookup("Y")
2074 if X == nil || Y == nil {
2075 t.Fatal("test must declare both X and Y")
2076 }
2077 if got := Identical(X.Type(), Y.Type()); got != test.want {
2078 t.Errorf("Identical(%s, %s) = %t, want %t", X.Type(), Y.Type(), got, test.want)
2079 }
2080 }
2081 }
2082
2083 func TestIdentical_issue15173(t *testing.T) {
2084
2085 for _, test := range []struct {
2086 x, y Type
2087 want bool
2088 }{
2089 {Typ[Int], Typ[Int], true},
2090 {Typ[Int], nil, false},
2091 {nil, Typ[Int], false},
2092 {nil, nil, true},
2093 } {
2094 if got := Identical(test.x, test.y); got != test.want {
2095 t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got)
2096 }
2097 }
2098 }
2099
2100 func TestIdenticalUnions(t *testing.T) {
2101 tname := NewTypeName(nopos, nil, "myInt", nil)
2102 myInt := NewNamed(tname, Typ[Int], nil)
2103 tmap := map[string]*Term{
2104 "int": NewTerm(false, Typ[Int]),
2105 "~int": NewTerm(true, Typ[Int]),
2106 "string": NewTerm(false, Typ[String]),
2107 "~string": NewTerm(true, Typ[String]),
2108 "myInt": NewTerm(false, myInt),
2109 }
2110 makeUnion := func(s string) *Union {
2111 parts := strings.Split(s, "|")
2112 var terms []*Term
2113 for _, p := range parts {
2114 term := tmap[p]
2115 if term == nil {
2116 t.Fatalf("missing term %q", p)
2117 }
2118 terms = append(terms, term)
2119 }
2120 return NewUnion(terms)
2121 }
2122 for _, test := range []struct {
2123 x, y string
2124 want bool
2125 }{
2126
2127
2128 {"int|~int", "~int", true},
2129 {"myInt|~int", "~int", true},
2130 {"int|string", "string|int", true},
2131 {"int|int|string", "string|int", true},
2132 {"myInt|string", "int|string", false},
2133 } {
2134 x := makeUnion(test.x)
2135 y := makeUnion(test.y)
2136 if got := Identical(x, y); got != test.want {
2137 t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got)
2138 }
2139 }
2140 }
2141
2142 func TestIssue61737(t *testing.T) {
2143
2144
2145
2146
2147
2148
2149 sig1 := NewSignatureType(nil, nil, nil, NewTuple(NewParam(nopos, nil, "", Typ[Int])), nil, false)
2150 sig2 := NewSignatureType(nil, nil, nil, NewTuple(NewParam(nopos, nil, "", Typ[String])), nil, false)
2151
2152 methods := []*Func{
2153 NewFunc(nopos, nil, "M", sig1),
2154 NewFunc(nopos, nil, "M", sig2),
2155 }
2156
2157 embeddedMethods := []*Func{
2158 NewFunc(nopos, nil, "M", sig2),
2159 }
2160 embedded := NewInterfaceType(embeddedMethods, nil)
2161 iface := NewInterfaceType(methods, []Type{embedded})
2162 iface.Complete()
2163 }
2164
2165 func TestNewAlias_Issue65455(t *testing.T) {
2166 obj := NewTypeName(nopos, nil, "A", nil)
2167 alias := NewAlias(obj, Typ[Int])
2168 alias.Underlying()
2169 }
2170
2171 func TestIssue15305(t *testing.T) {
2172 const src = "package p; func f() int16; var _ = f(undef)"
2173 fset := token.NewFileSet()
2174 f := mustParse(fset, src)
2175 conf := Config{
2176 Error: func(err error) {},
2177 }
2178 info := &Info{
2179 Types: make(map[ast.Expr]TypeAndValue),
2180 }
2181 conf.Check("p", fset, []*ast.File{f}, info)
2182 for e, tv := range info.Types {
2183 if _, ok := e.(*ast.CallExpr); ok {
2184 if tv.Type != Typ[Int16] {
2185 t.Errorf("CallExpr has type %v, want int16", tv.Type)
2186 }
2187 return
2188 }
2189 }
2190 t.Errorf("CallExpr has no type")
2191 }
2192
2193
2194
2195
2196 func TestCompositeLitTypes(t *testing.T) {
2197 for i, test := range []struct {
2198 lit, typ string
2199 }{
2200 {`[16]byte{}`, `[16]byte`},
2201 {`[...]byte{}`, `[0]byte`},
2202 {`[...]int{1, 2, 3}`, `[3]int`},
2203 {`[...]int{90: 0, 98: 1, 2}`, `[100]int`},
2204 {`[]int{}`, `[]int`},
2205 {`map[string]bool{"foo": true}`, `map[string]bool`},
2206 {`struct{}{}`, `struct{}`},
2207 {`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
2208 } {
2209 fset := token.NewFileSet()
2210 f := mustParse(fset, fmt.Sprintf("package p%d; var _ = %s", i, test.lit))
2211 types := make(map[ast.Expr]TypeAndValue)
2212 if _, err := new(Config).Check("p", fset, []*ast.File{f}, &Info{Types: types}); err != nil {
2213 t.Fatalf("%s: %v", test.lit, err)
2214 }
2215
2216 cmptype := func(x ast.Expr, want string) {
2217 tv, ok := types[x]
2218 if !ok {
2219 t.Errorf("%s: no Types entry found", test.lit)
2220 return
2221 }
2222 if tv.Type == nil {
2223 t.Errorf("%s: type is nil", test.lit)
2224 return
2225 }
2226 if got := tv.Type.String(); got != want {
2227 t.Errorf("%s: got %v, want %s", test.lit, got, want)
2228 }
2229 }
2230
2231
2232 rhs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0]
2233 cmptype(rhs, test.typ)
2234
2235
2236 cmptype(rhs.(*ast.CompositeLit).Type, test.typ)
2237 }
2238 }
2239
2240
2241
2242 func TestObjectParents(t *testing.T) {
2243 const src = `
2244 package p
2245
2246 const C = 0
2247
2248 type T1 struct {
2249 a, b int
2250 T2
2251 }
2252
2253 type T2 interface {
2254 im1()
2255 im2()
2256 }
2257
2258 func (T1) m1() {}
2259 func (*T1) m2() {}
2260
2261 func f(x int) { y := x; print(y) }
2262 `
2263
2264 fset := token.NewFileSet()
2265 f := mustParse(fset, src)
2266
2267 info := &Info{
2268 Defs: make(map[*ast.Ident]Object),
2269 }
2270 if _, err := new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
2271 t.Fatal(err)
2272 }
2273
2274 for ident, obj := range info.Defs {
2275 if obj == nil {
2276
2277
2278 if ident.Name != "p" {
2279 t.Errorf("%v has nil object", ident)
2280 }
2281 continue
2282 }
2283
2284
2285
2286 wantParent := true
2287 switch obj := obj.(type) {
2288 case *Var:
2289 if obj.IsField() {
2290 wantParent = false
2291 }
2292 case *Func:
2293 if obj.Signature().Recv() != nil {
2294 wantParent = false
2295 }
2296 }
2297
2298 gotParent := obj.Parent() != nil
2299 switch {
2300 case gotParent && !wantParent:
2301 t.Errorf("%v: want no parent, got %s", ident, obj.Parent())
2302 case !gotParent && wantParent:
2303 t.Errorf("%v: no parent found", ident)
2304 }
2305 }
2306 }
2307
2308
2309
2310 func TestFailedImport(t *testing.T) {
2311 testenv.MustHaveGoBuild(t)
2312
2313 const src = `
2314 package p
2315
2316 import foo "go/types/thisdirectorymustnotexistotherwisethistestmayfail/foo" // should only see an error here
2317
2318 const c = foo.C
2319 type T = foo.T
2320 var v T = c
2321 func f(x T) T { return foo.F(x) }
2322 `
2323 fset := token.NewFileSet()
2324 f := mustParse(fset, src)
2325 files := []*ast.File{f}
2326
2327
2328 for _, compiler := range []string{"gc", "gccgo", "source"} {
2329 errcount := 0
2330 conf := Config{
2331 Error: func(err error) {
2332
2333 if errcount > 0 || !strings.Contains(err.Error(), "could not import") {
2334 t.Errorf("for %s importer, got unexpected error: %v", compiler, err)
2335 }
2336 errcount++
2337 },
2338 Importer: importer.For(compiler, nil),
2339 }
2340
2341 info := &Info{
2342 Uses: make(map[*ast.Ident]Object),
2343 }
2344 pkg, _ := conf.Check("p", fset, files, info)
2345 if pkg == nil {
2346 t.Errorf("for %s importer, type-checking failed to return a package", compiler)
2347 continue
2348 }
2349
2350 imports := pkg.Imports()
2351 if len(imports) != 1 {
2352 t.Errorf("for %s importer, got %d imports, want 1", compiler, len(imports))
2353 continue
2354 }
2355 imp := imports[0]
2356 if imp.Name() != "foo" {
2357 t.Errorf(`for %s importer, got %q, want "foo"`, compiler, imp.Name())
2358 continue
2359 }
2360
2361
2362 for ident, obj := range info.Uses {
2363 if ident.Name == "foo" {
2364 if obj, ok := obj.(*PkgName); ok {
2365 if obj.Imported() != imp {
2366 t.Errorf("%s resolved to %v; want %v", ident, obj.Imported(), imp)
2367 }
2368 } else {
2369 t.Errorf("%s resolved to %v; want package name", ident, obj)
2370 }
2371 }
2372 }
2373 }
2374 }
2375
2376 func TestInstantiate(t *testing.T) {
2377
2378 const src = "package p; type T[P any] *T[P]"
2379 pkg := mustTypecheck(src, nil, nil)
2380
2381
2382 T := pkg.Scope().Lookup("T").Type().(*Named)
2383 if n := T.TypeParams().Len(); n != 1 {
2384 t.Fatalf("expected 1 type parameter; found %d", n)
2385 }
2386
2387
2388
2389 res, err := Instantiate(nil, T, []Type{Typ[Int]}, false)
2390 if err != nil {
2391 t.Fatal(err)
2392 }
2393
2394
2395 if p := res.Underlying().(*Pointer).Elem(); p != res {
2396 t.Fatalf("unexpected result type: %s points to %s", res, p)
2397 }
2398 }
2399
2400 func TestInstantiateConcurrent(t *testing.T) {
2401 const src = `package p
2402
2403 type I[P any] interface {
2404 m(P)
2405 n() P
2406 }
2407
2408 type J = I[int]
2409
2410 type Nested[P any] *interface{b(P)}
2411
2412 type K = Nested[string]
2413 `
2414 pkg := mustTypecheck(src, nil, nil)
2415
2416 insts := []*Interface{
2417 pkg.Scope().Lookup("J").Type().Underlying().(*Interface),
2418 pkg.Scope().Lookup("K").Type().Underlying().(*Pointer).Elem().(*Interface),
2419 }
2420
2421
2422 for _, inst := range insts {
2423 var (
2424 counts [2]int
2425 methods [2][]string
2426 )
2427 var wg sync.WaitGroup
2428 for i := 0; i < 2; i++ {
2429 i := i
2430 wg.Add(1)
2431 go func() {
2432 defer wg.Done()
2433
2434 counts[i] = inst.NumMethods()
2435 for mi := 0; mi < counts[i]; mi++ {
2436 methods[i] = append(methods[i], inst.Method(mi).String())
2437 }
2438 }()
2439 }
2440 wg.Wait()
2441
2442 if counts[0] != counts[1] {
2443 t.Errorf("mismatching method counts for %s: %d vs %d", inst, counts[0], counts[1])
2444 continue
2445 }
2446 for i := 0; i < counts[0]; i++ {
2447 if m0, m1 := methods[0][i], methods[1][i]; m0 != m1 {
2448 t.Errorf("mismatching methods for %s: %s vs %s", inst, m0, m1)
2449 }
2450 }
2451 }
2452 }
2453
2454 func TestInstantiateErrors(t *testing.T) {
2455 tests := []struct {
2456 src string
2457 targs []Type
2458 wantAt int
2459 }{
2460 {"type T[P interface{~string}] int", []Type{Typ[Int]}, 0},
2461 {"type T[P1 interface{int}, P2 interface{~string}] int", []Type{Typ[Int], Typ[Int]}, 1},
2462 {"type T[P1 any, P2 interface{~[]P1}] int", []Type{Typ[Int], NewSlice(Typ[String])}, 1},
2463 {"type T[P1 interface{~[]P2}, P2 any] int", []Type{NewSlice(Typ[String]), Typ[Int]}, 0},
2464 }
2465
2466 for _, test := range tests {
2467 src := "package p; " + test.src
2468 pkg := mustTypecheck(src, nil, nil)
2469
2470 T := pkg.Scope().Lookup("T").Type().(*Named)
2471
2472 _, err := Instantiate(nil, T, test.targs, true)
2473 if err == nil {
2474 t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs)
2475 }
2476
2477 var argErr *ArgumentError
2478 if !errors.As(err, &argErr) {
2479 t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs)
2480 }
2481
2482 if argErr.Index != test.wantAt {
2483 t.Errorf("Instantiate(%v, %v): error at index %d, want index %d", T, test.targs, argErr.Index, test.wantAt)
2484 }
2485 }
2486 }
2487
2488 func TestArgumentErrorUnwrapping(t *testing.T) {
2489 var err error = &ArgumentError{
2490 Index: 1,
2491 Err: Error{Msg: "test"},
2492 }
2493 var e Error
2494 if !errors.As(err, &e) {
2495 t.Fatalf("error %v does not wrap types.Error", err)
2496 }
2497 if e.Msg != "test" {
2498 t.Errorf("e.Msg = %q, want %q", e.Msg, "test")
2499 }
2500 }
2501
2502 func TestInstanceIdentity(t *testing.T) {
2503 imports := make(testImporter)
2504 conf := Config{Importer: imports}
2505 makePkg := func(src string) {
2506 fset := token.NewFileSet()
2507 f := mustParse(fset, src)
2508 name := f.Name.Name
2509 pkg, err := conf.Check(name, fset, []*ast.File{f}, nil)
2510 if err != nil {
2511 t.Fatal(err)
2512 }
2513 imports[name] = pkg
2514 }
2515 makePkg(`package lib; type T[P any] struct{}`)
2516 makePkg(`package a; import "lib"; var A lib.T[int]`)
2517 makePkg(`package b; import "lib"; var B lib.T[int]`)
2518 a := imports["a"].Scope().Lookup("A")
2519 b := imports["b"].Scope().Lookup("B")
2520 if !Identical(a.Type(), b.Type()) {
2521 t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type())
2522 }
2523 }
2524
2525
2526 func TestInstantiatedObjects(t *testing.T) {
2527 const src = `
2528 package p
2529
2530 type T[P any] struct {
2531 field P
2532 }
2533
2534 func (recv *T[Q]) concreteMethod(mParam Q) (mResult Q) { return }
2535
2536 type FT[P any] func(ftParam P) (ftResult P)
2537
2538 func F[P any](fParam P) (fResult P){ return }
2539
2540 type I[P any] interface {
2541 interfaceMethod(P)
2542 }
2543
2544 type R[P any] T[P]
2545
2546 func (R[P]) m() {} // having a method triggers expansion of R
2547
2548 var (
2549 t T[int]
2550 ft FT[int]
2551 f = F[int]
2552 i I[int]
2553 )
2554
2555 func fn() {
2556 var r R[int]
2557 _ = r
2558 }
2559 `
2560 info := &Info{
2561 Defs: make(map[*ast.Ident]Object),
2562 }
2563 fset := token.NewFileSet()
2564 f := mustParse(fset, src)
2565 conf := Config{}
2566 pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
2567 if err != nil {
2568 t.Fatal(err)
2569 }
2570
2571 lookup := func(name string) Type { return pkg.Scope().Lookup(name).Type() }
2572 fnScope := pkg.Scope().Lookup("fn").(*Func).Scope()
2573
2574 tests := []struct {
2575 name string
2576 obj Object
2577 }{
2578
2579 {"field", lookup("t").Underlying().(*Struct).Field(0)},
2580 {"field", fnScope.Lookup("r").Type().Underlying().(*Struct).Field(0)},
2581
2582
2583 {"concreteMethod", lookup("t").(*Named).Method(0)},
2584 {"recv", lookup("t").(*Named).Method(0).Signature().Recv()},
2585 {"mParam", lookup("t").(*Named).Method(0).Signature().Params().At(0)},
2586 {"mResult", lookup("t").(*Named).Method(0).Signature().Results().At(0)},
2587
2588
2589 {"interfaceMethod", lookup("i").Underlying().(*Interface).Method(0)},
2590
2591
2592 {"ftParam", lookup("ft").Underlying().(*Signature).Params().At(0)},
2593 {"ftResult", lookup("ft").Underlying().(*Signature).Results().At(0)},
2594
2595
2596 {"fParam", lookup("f").(*Signature).Params().At(0)},
2597 {"fResult", lookup("f").(*Signature).Results().At(0)},
2598 }
2599
2600
2601 idents := make(map[string][]*ast.Ident)
2602 ast.Inspect(f, func(n ast.Node) bool {
2603 if id, ok := n.(*ast.Ident); ok {
2604 idents[id.Name] = append(idents[id.Name], id)
2605 }
2606 return true
2607 })
2608
2609 for _, test := range tests {
2610 test := test
2611 t.Run(test.name, func(t *testing.T) {
2612 if got := len(idents[test.name]); got != 1 {
2613 t.Fatalf("found %d identifiers named %s, want 1", got, test.name)
2614 }
2615 ident := idents[test.name][0]
2616 def := info.Defs[ident]
2617 if def == test.obj {
2618 t.Fatalf("info.Defs[%s] contains the test object", test.name)
2619 }
2620 if orig := originObject(test.obj); def != orig {
2621 t.Errorf("info.Defs[%s] does not match obj.Origin()", test.name)
2622 }
2623 if def.Pkg() != test.obj.Pkg() {
2624 t.Errorf("Pkg() = %v, want %v", def.Pkg(), test.obj.Pkg())
2625 }
2626 if def.Name() != test.obj.Name() {
2627 t.Errorf("Name() = %v, want %v", def.Name(), test.obj.Name())
2628 }
2629 if def.Pos() != test.obj.Pos() {
2630 t.Errorf("Pos() = %v, want %v", def.Pos(), test.obj.Pos())
2631 }
2632 if def.Parent() != test.obj.Parent() {
2633 t.Fatalf("Parent() = %v, want %v", def.Parent(), test.obj.Parent())
2634 }
2635 if def.Exported() != test.obj.Exported() {
2636 t.Fatalf("Exported() = %v, want %v", def.Exported(), test.obj.Exported())
2637 }
2638 if def.Id() != test.obj.Id() {
2639 t.Fatalf("Id() = %v, want %v", def.Id(), test.obj.Id())
2640 }
2641
2642 })
2643 }
2644 }
2645
2646 func originObject(obj Object) Object {
2647 switch obj := obj.(type) {
2648 case *Var:
2649 return obj.Origin()
2650 case *Func:
2651 return obj.Origin()
2652 }
2653 return obj
2654 }
2655
2656 func TestImplements(t *testing.T) {
2657 const src = `
2658 package p
2659
2660 type EmptyIface interface{}
2661
2662 type I interface {
2663 m()
2664 }
2665
2666 type C interface {
2667 m()
2668 ~int
2669 }
2670
2671 type Integer interface{
2672 int8 | int16 | int32 | int64
2673 }
2674
2675 type EmptyTypeSet interface{
2676 Integer
2677 ~string
2678 }
2679
2680 type N1 int
2681 func (N1) m() {}
2682
2683 type N2 int
2684 func (*N2) m() {}
2685
2686 type N3 int
2687 func (N3) m(int) {}
2688
2689 type N4 string
2690 func (N4) m()
2691
2692 type Bad Bad // invalid type
2693 `
2694
2695 fset := token.NewFileSet()
2696 f := mustParse(fset, src)
2697 conf := Config{Error: func(error) {}}
2698 pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
2699
2700 lookup := func(tname string) Type { return pkg.Scope().Lookup(tname).Type() }
2701 var (
2702 EmptyIface = lookup("EmptyIface").Underlying().(*Interface)
2703 I = lookup("I").(*Named)
2704 II = I.Underlying().(*Interface)
2705 C = lookup("C").(*Named)
2706 CI = C.Underlying().(*Interface)
2707 Integer = lookup("Integer").Underlying().(*Interface)
2708 EmptyTypeSet = lookup("EmptyTypeSet").Underlying().(*Interface)
2709 N1 = lookup("N1")
2710 N1p = NewPointer(N1)
2711 N2 = lookup("N2")
2712 N2p = NewPointer(N2)
2713 N3 = lookup("N3")
2714 N4 = lookup("N4")
2715 Bad = lookup("Bad")
2716 )
2717
2718 tests := []struct {
2719 V Type
2720 T *Interface
2721 want bool
2722 }{
2723 {I, II, true},
2724 {I, CI, false},
2725 {C, II, true},
2726 {C, CI, true},
2727 {Typ[Int8], Integer, true},
2728 {Typ[Int64], Integer, true},
2729 {Typ[String], Integer, false},
2730 {EmptyTypeSet, II, true},
2731 {EmptyTypeSet, EmptyTypeSet, true},
2732 {Typ[Int], EmptyTypeSet, false},
2733 {N1, II, true},
2734 {N1, CI, true},
2735 {N1p, II, true},
2736 {N1p, CI, false},
2737 {N2, II, false},
2738 {N2, CI, false},
2739 {N2p, II, true},
2740 {N2p, CI, false},
2741 {N3, II, false},
2742 {N3, CI, false},
2743 {N4, II, true},
2744 {N4, CI, false},
2745 {Bad, II, false},
2746 {Bad, CI, false},
2747 {Bad, EmptyIface, true},
2748 }
2749
2750 for _, test := range tests {
2751 if got := Implements(test.V, test.T); got != test.want {
2752 t.Errorf("Implements(%s, %s) = %t, want %t", test.V, test.T, got, test.want)
2753 }
2754
2755
2756
2757 V := test.T
2758 T := test.V
2759 want := false
2760 if _, ok := T.Underlying().(*Interface); (ok || Implements(T, V)) && T != Bad {
2761 want = true
2762 }
2763 if got := AssertableTo(V, T); got != want {
2764 t.Errorf("AssertableTo(%s, %s) = %t, want %t", V, T, got, want)
2765 }
2766 }
2767 }
2768
2769 func TestMissingMethodAlternative(t *testing.T) {
2770 const src = `
2771 package p
2772 type T interface {
2773 m()
2774 }
2775
2776 type V0 struct{}
2777 func (V0) m() {}
2778
2779 type V1 struct{}
2780
2781 type V2 struct{}
2782 func (V2) m() int
2783
2784 type V3 struct{}
2785 func (*V3) m()
2786
2787 type V4 struct{}
2788 func (V4) M()
2789 `
2790
2791 pkg := mustTypecheck(src, nil, nil)
2792
2793 T := pkg.Scope().Lookup("T").Type().Underlying().(*Interface)
2794 lookup := func(name string) (*Func, bool) {
2795 return MissingMethod(pkg.Scope().Lookup(name).Type(), T, true)
2796 }
2797
2798
2799 method, wrongType := lookup("V0")
2800 if method != nil || wrongType {
2801 t.Fatalf("V0: got method = %v, wrongType = %v", method, wrongType)
2802 }
2803
2804 checkMissingMethod := func(tname string, reportWrongType bool) {
2805 method, wrongType := lookup(tname)
2806 if method == nil || method.Name() != "m" || wrongType != reportWrongType {
2807 t.Fatalf("%s: got method = %v, wrongType = %v", tname, method, wrongType)
2808 }
2809 }
2810
2811
2812 checkMissingMethod("V1", false)
2813
2814
2815 checkMissingMethod("V2", true)
2816
2817
2818 checkMissingMethod("V3", true)
2819
2820
2821 checkMissingMethod("V4", false)
2822 }
2823
2824 func TestErrorURL(t *testing.T) {
2825 var conf Config
2826 *stringFieldAddr(&conf, "_ErrorURL") = " [go.dev/e/%s]"
2827
2828
2829 const src1 = `
2830 package p
2831 var _ T
2832 `
2833 _, err := typecheck(src1, &conf, nil)
2834 if err == nil || !strings.HasSuffix(err.Error(), " [go.dev/e/UndeclaredName]") {
2835 t.Errorf("src1: unexpected error: got %v", err)
2836 }
2837
2838
2839 const src2 = `
2840 package p
2841 func f() int { return 0 }
2842 var _ = f(1, 2)
2843 `
2844 _, err = typecheck(src2, &conf, nil)
2845 if err == nil || !strings.Contains(err.Error(), " [go.dev/e/WrongArgCount]\n") {
2846 t.Errorf("src1: unexpected error: got %v", err)
2847 }
2848 }
2849
2850 func TestModuleVersion(t *testing.T) {
2851
2852 goversion := fmt.Sprintf("go1.%d", goversion.Version)
2853 for _, v := range []string{
2854 goversion,
2855 goversion + ".0",
2856 goversion + ".1",
2857 goversion + ".rc",
2858 } {
2859 conf := Config{GoVersion: v}
2860 pkg := mustTypecheck("package p", &conf, nil)
2861 if pkg.GoVersion() != conf.GoVersion {
2862 t.Errorf("got %s; want %s", pkg.GoVersion(), conf.GoVersion)
2863 }
2864 }
2865 }
2866
2867 func TestFileVersions(t *testing.T) {
2868 for _, test := range []struct {
2869 goVersion string
2870 fileVersion string
2871 wantVersion string
2872 }{
2873 {"", "", ""},
2874 {"go1.19", "", "go1.19"},
2875 {"", "go1.20", "go1.21"},
2876 {"go1", "", "go1"},
2877 {"go1", "goo1.22", "go1"},
2878 {"go1", "go1.19", "go1.21"},
2879 {"go1", "go1.20", "go1.21"},
2880 {"go1", "go1.21", "go1.21"},
2881 {"go1", "go1.22", "go1.22"},
2882 {"go1.19", "", "go1.19"},
2883 {"go1.19", "goo1.22", "go1.19"},
2884 {"go1.19", "go1.20", "go1.21"},
2885 {"go1.19", "go1.21", "go1.21"},
2886 {"go1.19", "go1.22", "go1.22"},
2887 {"go1.20", "", "go1.20"},
2888 {"go1.20", "goo1.22", "go1.20"},
2889 {"go1.20", "go1.19", "go1.21"},
2890 {"go1.20", "go1.20", "go1.21"},
2891 {"go1.20", "go1.21", "go1.21"},
2892 {"go1.20", "go1.22", "go1.22"},
2893 {"go1.21", "", "go1.21"},
2894 {"go1.21", "goo1.22", "go1.21"},
2895 {"go1.21", "go1.19", "go1.21"},
2896 {"go1.21", "go1.20", "go1.21"},
2897 {"go1.21", "go1.21", "go1.21"},
2898 {"go1.21", "go1.22", "go1.22"},
2899 {"go1.22", "", "go1.22"},
2900 {"go1.22", "goo1.22", "go1.22"},
2901 {"go1.22", "go1.19", "go1.21"},
2902 {"go1.22", "go1.20", "go1.21"},
2903 {"go1.22", "go1.21", "go1.21"},
2904 {"go1.22", "go1.22", "go1.22"},
2905
2906
2907
2908 {"go1.19.0", "", "go1.19.0"},
2909 {"go1.20.1", "go1.19.1", "go1.20.1"},
2910 {"go1.20.1", "go1.21.1", "go1.20.1"},
2911 {"go1.21.1", "go1.19.1", "go1.21.1"},
2912 {"go1.21.1", "go1.21.1", "go1.21.1"},
2913 {"go1.22.1", "go1.19.1", "go1.22.1"},
2914 {"go1.22.1", "go1.21.1", "go1.22.1"},
2915 } {
2916 var src string
2917 if test.fileVersion != "" {
2918 src = "//go:build " + test.fileVersion + "\n"
2919 }
2920 src += "package p"
2921
2922 conf := Config{GoVersion: test.goVersion}
2923 versions := make(map[*ast.File]string)
2924 var info Info
2925 info.FileVersions = versions
2926 mustTypecheck(src, &conf, &info)
2927
2928 n := 0
2929 for _, v := range versions {
2930 want := test.wantVersion
2931 if v != want {
2932 t.Errorf("%q: unexpected file version: got %q, want %q", src, v, want)
2933 }
2934 n++
2935 }
2936 if n != 1 {
2937 t.Errorf("%q: incorrect number of map entries: got %d", src, n)
2938 }
2939 }
2940 }
2941
2942
2943
2944 func TestTooNew(t *testing.T) {
2945 for _, test := range []struct {
2946 goVersion string
2947 fileVersion string
2948 wantErr string
2949 }{
2950 {"go1.98", "", "package requires newer Go version go1.98"},
2951 {"", "go1.99", "p:2:9: file requires newer Go version go1.99"},
2952 {"go1.98", "go1.99", "package requires newer Go version go1.98"},
2953 {"go1.98", "go1.99", "file requires newer Go version go1.99"},
2954 } {
2955 var src string
2956 if test.fileVersion != "" {
2957 src = "//go:build " + test.fileVersion + "\n"
2958 }
2959 src += "package p; func f()"
2960
2961 var errs []error
2962 conf := Config{
2963 GoVersion: test.goVersion,
2964 Error: func(err error) { errs = append(errs, err) },
2965 }
2966 info := &Info{Defs: make(map[*ast.Ident]Object)}
2967 typecheck(src, &conf, info)
2968 got := fmt.Sprint(errs)
2969 if !strings.Contains(got, test.wantErr) {
2970 t.Errorf("%q: unexpected error: got %q, want substring %q",
2971 src, got, test.wantErr)
2972 }
2973
2974
2975 var gotObjs []string
2976 for id, obj := range info.Defs {
2977 if obj != nil {
2978 objStr := strings.ReplaceAll(fmt.Sprintf("%s:%T", id.Name, obj), "types2", "types")
2979 gotObjs = append(gotObjs, objStr)
2980 }
2981 }
2982 wantObjs := "f:*types.Func"
2983 if !strings.Contains(fmt.Sprint(gotObjs), wantObjs) {
2984 t.Errorf("%q: got %s, want substring %q",
2985 src, gotObjs, wantObjs)
2986 }
2987 }
2988 }
2989
2990
2991 func TestUnaliasTooSoonInCycle(t *testing.T) {
2992 setGotypesalias(t, true)
2993 const src = `package a
2994
2995 var x T[B] // this appears to cause Unalias to be called on B while still Invalid
2996
2997 type T[_ any] struct{}
2998 type A T[B]
2999 type B = T[A]
3000 `
3001 pkg := mustTypecheck(src, nil, nil)
3002 B := pkg.Scope().Lookup("B")
3003
3004 got, want := Unalias(B.Type()).String(), "a.T[a.A]"
3005 if got != want {
3006 t.Errorf("Unalias(type B = T[A]) = %q, want %q", got, want)
3007 }
3008 }
3009
3010 func TestAlias_Rhs(t *testing.T) {
3011 setGotypesalias(t, true)
3012 const src = `package p
3013
3014 type A = B
3015 type B = C
3016 type C = int
3017 `
3018
3019 pkg := mustTypecheck(src, nil, nil)
3020 A := pkg.Scope().Lookup("A")
3021
3022 got, want := A.Type().(*Alias).Rhs().String(), "p.B"
3023 if got != want {
3024 t.Errorf("A.Rhs = %s, want %s", got, want)
3025 }
3026 }
3027
3028
3029
3030 func TestAnyHijacking_Check(t *testing.T) {
3031 for _, enableAlias := range []bool{false, true} {
3032 t.Run(fmt.Sprintf("EnableAlias=%t", enableAlias), func(t *testing.T) {
3033 setGotypesalias(t, enableAlias)
3034 var wg sync.WaitGroup
3035 for i := 0; i < 10; i++ {
3036 wg.Add(1)
3037 go func() {
3038 defer wg.Done()
3039 pkg := mustTypecheck("package p; var x any", nil, nil)
3040 x := pkg.Scope().Lookup("x")
3041 if _, gotAlias := x.Type().(*Alias); gotAlias != enableAlias {
3042 t.Errorf(`Lookup("x").Type() is %T: got Alias: %t, want %t`, x.Type(), gotAlias, enableAlias)
3043 }
3044 }()
3045 }
3046 wg.Wait()
3047 })
3048 }
3049 }
3050
3051
3052
3053 func TestAnyHijacking_Lookup(t *testing.T) {
3054 for _, enableAlias := range []bool{false, true} {
3055 t.Run(fmt.Sprintf("EnableAlias=%t", enableAlias), func(t *testing.T) {
3056 setGotypesalias(t, enableAlias)
3057 a := Universe.Lookup("any")
3058 if _, gotAlias := a.Type().(*Alias); gotAlias != enableAlias {
3059 t.Errorf(`Lookup("x").Type() is %T: got Alias: %t, want %t`, a.Type(), gotAlias, enableAlias)
3060 }
3061 })
3062 }
3063 }
3064
3065 func setGotypesalias(t *testing.T, enable bool) {
3066 if enable {
3067 t.Setenv("GODEBUG", "gotypesalias=1")
3068 } else {
3069 t.Setenv("GODEBUG", "gotypesalias=0")
3070 }
3071 }
3072
3073
3074
3075
3076 func TestVersionIssue69477(t *testing.T) {
3077 fset := token.NewFileSet()
3078 f, _ := parser.ParseFile(fset, "a.go", "package p; const k = 123", 0)
3079
3080
3081 ast.Inspect(f, func(n ast.Node) bool {
3082 if lit, ok := n.(*ast.BasicLit); ok {
3083 lit.ValuePos = 99999
3084 }
3085 return true
3086 })
3087
3088
3089
3090 pkg := NewPackage("p", "p")
3091 check := NewChecker(&Config{}, fset, pkg, nil)
3092 if err := check.Files([]*ast.File{f}); err != nil {
3093 t.Fatal(err)
3094 }
3095 }
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106 func TestVersionWithoutPos(t *testing.T) {
3107 fset := token.NewFileSet()
3108 f, _ := parser.ParseFile(fset, "a.go", "//go:build go1.22\n\npackage p; var _ int", 0)
3109
3110
3111 f2, _ := parser.ParseFile(fset, "a.go", "package q; func _(s func(func() bool)) { for range s {} }", 0)
3112 f.Decls[0] = f2.Decls[0]
3113
3114
3115
3116
3117
3118 pkg := NewPackage("p", "p")
3119 check := NewChecker(&Config{}, fset, pkg, nil)
3120 err := check.Files([]*ast.File{f})
3121 got := fmt.Sprint(err)
3122 want := "range over s (variable of type func(func() bool)): requires go1.23"
3123 if !strings.Contains(got, want) {
3124 t.Errorf("check error was %q, want substring %q", got, want)
3125 }
3126 }
3127
View as plain text