github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/go/types/api_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package types_test 6 7 import ( 8 "errors" 9 "fmt" 10 "go/ast" 11 "go/importer" 12 "go/parser" 13 "go/token" 14 "internal/testenv" 15 "reflect" 16 "regexp" 17 "sort" 18 "strings" 19 "testing" 20 21 . "go/types" 22 ) 23 24 // nopos indicates an unknown position 25 var nopos token.Pos 26 27 func mustParse(fset *token.FileSet, src string) *ast.File { 28 f, err := parser.ParseFile(fset, pkgName(src), src, 0) 29 if err != nil { 30 panic(err) // so we don't need to pass *testing.T 31 } 32 return f 33 } 34 35 func typecheck(src string, conf *Config, info *Info) (*Package, error) { 36 fset := token.NewFileSet() 37 f := mustParse(fset, src) 38 if conf == nil { 39 conf = &Config{ 40 Error: func(err error) {}, // collect all errors 41 Importer: importer.Default(), 42 } 43 } 44 return conf.Check(f.Name.Name, fset, []*ast.File{f}, info) 45 } 46 47 func mustTypecheck(src string, conf *Config, info *Info) *Package { 48 pkg, err := typecheck(src, conf, info) 49 if err != nil { 50 panic(err) // so we don't need to pass *testing.T 51 } 52 return pkg 53 } 54 55 // pkgName extracts the package name from src, which must contain a package header. 56 func pkgName(src string) string { 57 const kw = "package " 58 if i := strings.Index(src, kw); i >= 0 { 59 after := src[i+len(kw):] 60 n := len(after) 61 if i := strings.IndexAny(after, "\n\t ;/"); i >= 0 { 62 n = i 63 } 64 return after[:n] 65 } 66 panic("missing package header: " + src) 67 } 68 69 func TestValuesInfo(t *testing.T) { 70 var tests = []struct { 71 src string 72 expr string // constant expression 73 typ string // constant type 74 val string // constant value 75 }{ 76 {`package a0; const _ = false`, `false`, `untyped bool`, `false`}, 77 {`package a1; const _ = 0`, `0`, `untyped int`, `0`}, 78 {`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`}, 79 {`package a3; const _ = 0.`, `0.`, `untyped float`, `0`}, 80 {`package a4; const _ = 0i`, `0i`, `untyped complex`, `(0 + 0i)`}, 81 {`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`}, 82 83 {`package b0; var _ = false`, `false`, `bool`, `false`}, 84 {`package b1; var _ = 0`, `0`, `int`, `0`}, 85 {`package b2; var _ = 'A'`, `'A'`, `rune`, `65`}, 86 {`package b3; var _ = 0.`, `0.`, `float64`, `0`}, 87 {`package b4; var _ = 0i`, `0i`, `complex128`, `(0 + 0i)`}, 88 {`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`}, 89 90 {`package c0a; var _ = bool(false)`, `false`, `bool`, `false`}, 91 {`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`}, 92 {`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`}, 93 94 {`package c1a; var _ = int(0)`, `0`, `int`, `0`}, 95 {`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`}, 96 {`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`}, 97 98 {`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`}, 99 {`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`}, 100 {`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`}, 101 102 {`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`}, 103 {`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`}, 104 {`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`}, 105 106 {`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `(0 + 0i)`}, 107 {`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `(0 + 0i)`}, 108 {`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `(0 + 0i)`}, 109 110 {`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`}, 111 {`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`}, 112 {`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`}, 113 {`package c5d; var _ = string(65)`, `65`, `untyped int`, `65`}, 114 {`package c5e; var _ = string('A')`, `'A'`, `untyped rune`, `65`}, 115 {`package c5f; type T string; var _ = T('A')`, `'A'`, `untyped rune`, `65`}, 116 117 {`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`}, 118 {`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`}, 119 {`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`}, 120 {`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`}, 121 122 {`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`}, 123 {`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`}, 124 {`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`}, 125 {`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`}, 126 {`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `(0 + 0i)`}, 127 {`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `(0 + 0i)`}, 128 {`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `(0 + 0i)`}, 129 {`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `(0 + 0i)`}, 130 131 {`package f0 ; var _ float32 = 1e-200`, `1e-200`, `float32`, `0`}, 132 {`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`}, 133 {`package f2a; var _ float64 = 1e-2000`, `1e-2000`, `float64`, `0`}, 134 {`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`}, 135 {`package f2b; var _ = 1e-2000`, `1e-2000`, `float64`, `0`}, 136 {`package f3b; var _ = -1e-2000`, `-1e-2000`, `float64`, `0`}, 137 {`package f4 ; var _ complex64 = 1e-200 `, `1e-200`, `complex64`, `(0 + 0i)`}, 138 {`package f5 ; var _ complex64 = -1e-200 `, `-1e-200`, `complex64`, `(0 + 0i)`}, 139 {`package f6a; var _ complex128 = 1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`}, 140 {`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`}, 141 {`package f6b; var _ = 1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`}, 142 {`package f7b; var _ = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`}, 143 144 {`package g0; const (a = len([iota]int{}); b; c); const _ = c`, `c`, `int`, `2`}, // go.dev/issue/22341 145 {`package g1; var(j int32; s int; n = 1.0<<s == j)`, `1.0`, `int32`, `1`}, // go.dev/issue/48422 146 } 147 148 for _, test := range tests { 149 info := Info{ 150 Types: make(map[ast.Expr]TypeAndValue), 151 } 152 name := mustTypecheck(test.src, nil, &info).Name() 153 154 // look for expression 155 var expr ast.Expr 156 for e := range info.Types { 157 if ExprString(e) == test.expr { 158 expr = e 159 break 160 } 161 } 162 if expr == nil { 163 t.Errorf("package %s: no expression found for %s", name, test.expr) 164 continue 165 } 166 tv := info.Types[expr] 167 168 // check that type is correct 169 if got := tv.Type.String(); got != test.typ { 170 t.Errorf("package %s: got type %s; want %s", name, got, test.typ) 171 continue 172 } 173 174 // if we have a constant, check that value is correct 175 if tv.Value != nil { 176 if got := tv.Value.ExactString(); got != test.val { 177 t.Errorf("package %s: got value %s; want %s", name, got, test.val) 178 } 179 } else { 180 if test.val != "" { 181 t.Errorf("package %s: no constant found; want %s", name, test.val) 182 } 183 } 184 } 185 } 186 187 func TestTypesInfo(t *testing.T) { 188 // Test sources that are not expected to typecheck must start with the broken prefix. 189 const broken = "package broken_" 190 191 var tests = []struct { 192 src string 193 expr string // expression 194 typ string // value type 195 }{ 196 // single-valued expressions of untyped constants 197 {`package b0; var x interface{} = false`, `false`, `bool`}, 198 {`package b1; var x interface{} = 0`, `0`, `int`}, 199 {`package b2; var x interface{} = 0.`, `0.`, `float64`}, 200 {`package b3; var x interface{} = 0i`, `0i`, `complex128`}, 201 {`package b4; var x interface{} = "foo"`, `"foo"`, `string`}, 202 203 // uses of nil 204 {`package n0; var _ *int = nil`, `nil`, `untyped nil`}, 205 {`package n1; var _ func() = nil`, `nil`, `untyped nil`}, 206 {`package n2; var _ []byte = nil`, `nil`, `untyped nil`}, 207 {`package n3; var _ map[int]int = nil`, `nil`, `untyped nil`}, 208 {`package n4; var _ chan int = nil`, `nil`, `untyped nil`}, 209 {`package n5; var _ interface{} = nil`, `nil`, `untyped nil`}, 210 {`package n6; import "unsafe"; var _ unsafe.Pointer = nil`, `nil`, `untyped nil`}, 211 212 {`package n10; var (x *int; _ = x == nil)`, `nil`, `untyped nil`}, 213 {`package n11; var (x func(); _ = x == nil)`, `nil`, `untyped nil`}, 214 {`package n12; var (x []byte; _ = x == nil)`, `nil`, `untyped nil`}, 215 {`package n13; var (x map[int]int; _ = x == nil)`, `nil`, `untyped nil`}, 216 {`package n14; var (x chan int; _ = x == nil)`, `nil`, `untyped nil`}, 217 {`package n15; var (x interface{}; _ = x == nil)`, `nil`, `untyped nil`}, 218 {`package n15; import "unsafe"; var (x unsafe.Pointer; _ = x == nil)`, `nil`, `untyped nil`}, 219 220 {`package n20; var _ = (*int)(nil)`, `nil`, `untyped nil`}, 221 {`package n21; var _ = (func())(nil)`, `nil`, `untyped nil`}, 222 {`package n22; var _ = ([]byte)(nil)`, `nil`, `untyped nil`}, 223 {`package n23; var _ = (map[int]int)(nil)`, `nil`, `untyped nil`}, 224 {`package n24; var _ = (chan int)(nil)`, `nil`, `untyped nil`}, 225 {`package n25; var _ = (interface{})(nil)`, `nil`, `untyped nil`}, 226 {`package n26; import "unsafe"; var _ = unsafe.Pointer(nil)`, `nil`, `untyped nil`}, 227 228 {`package n30; func f(*int) { f(nil) }`, `nil`, `untyped nil`}, 229 {`package n31; func f(func()) { f(nil) }`, `nil`, `untyped nil`}, 230 {`package n32; func f([]byte) { f(nil) }`, `nil`, `untyped nil`}, 231 {`package n33; func f(map[int]int) { f(nil) }`, `nil`, `untyped nil`}, 232 {`package n34; func f(chan int) { f(nil) }`, `nil`, `untyped nil`}, 233 {`package n35; func f(interface{}) { f(nil) }`, `nil`, `untyped nil`}, 234 {`package n35; import "unsafe"; func f(unsafe.Pointer) { f(nil) }`, `nil`, `untyped nil`}, 235 236 // comma-ok expressions 237 {`package p0; var x interface{}; var _, _ = x.(int)`, 238 `x.(int)`, 239 `(int, bool)`, 240 }, 241 {`package p1; var x interface{}; func _() { _, _ = x.(int) }`, 242 `x.(int)`, 243 `(int, bool)`, 244 }, 245 {`package p2a; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`, 246 `m["foo"]`, 247 `(complex128, p2a.mybool)`, 248 }, 249 {`package p2b; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`, 250 `m["foo"]`, 251 `(complex128, bool)`, 252 }, 253 {`package p3; var c chan string; var _, _ = <-c`, 254 `<-c`, 255 `(string, bool)`, 256 }, 257 258 // go.dev/issue/6796 259 {`package issue6796_a; var x interface{}; var _, _ = (x.(int))`, 260 `x.(int)`, 261 `(int, bool)`, 262 }, 263 {`package issue6796_b; var c chan string; var _, _ = (<-c)`, 264 `(<-c)`, 265 `(string, bool)`, 266 }, 267 {`package issue6796_c; var c chan string; var _, _ = (<-c)`, 268 `<-c`, 269 `(string, bool)`, 270 }, 271 {`package issue6796_d; var c chan string; var _, _ = ((<-c))`, 272 `(<-c)`, 273 `(string, bool)`, 274 }, 275 {`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`, 276 `(<-c)`, 277 `(string, bool)`, 278 }, 279 280 // go.dev/issue/7060 281 {`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`, 282 `m[0]`, 283 `(string, bool)`, 284 }, 285 {`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`, 286 `m[0]`, 287 `(string, bool)`, 288 }, 289 {`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`, 290 `m[0]`, 291 `(string, bool)`, 292 }, 293 {`package issue7060_d; var ( ch chan string; x, ok = <-ch )`, 294 `<-ch`, 295 `(string, bool)`, 296 }, 297 {`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`, 298 `<-ch`, 299 `(string, bool)`, 300 }, 301 {`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`, 302 `<-ch`, 303 `(string, bool)`, 304 }, 305 306 // go.dev/issue/28277 307 {`package issue28277_a; func f(...int)`, 308 `...int`, 309 `[]int`, 310 }, 311 {`package issue28277_b; func f(a, b int, c ...[]struct{})`, 312 `...[]struct{}`, 313 `[][]struct{}`, 314 }, 315 316 // go.dev/issue/47243 317 {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`}, 318 {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `untyped float`}, 319 {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`}, 320 {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`}, 321 {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`}, 322 {`package issue47243_f; var x int32; var _ = 1 << 2`, `2`, `untyped int`}, 323 {`package issue47243_g; var x int32; var _ = int(1) << 2`, `2`, `untyped int`}, 324 {`package issue47243_h; var x int32; var _ = 1 << (2 << x)`, `1`, `int`}, 325 {`package issue47243_i; var x int32; var _ = 1 << (2 << x)`, `(2 << x)`, `untyped int`}, 326 {`package issue47243_j; var x int32; var _ = 1 << (2 << x)`, `2`, `untyped int`}, 327 328 // tests for broken code that doesn't type-check 329 {broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`}, 330 {broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`}, 331 {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a, f: b,}}`, `b`, `string`}, 332 {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`}, 333 {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`}, 334 {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, 335 336 // parameterized functions 337 {`package p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T any](T)`}, 338 {`package p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, 339 {`package p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, 340 {`package p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, 341 {`package p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T any](T)`}, 342 {`package p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, 343 344 // type parameters 345 {`package t0; type t[] int; var _ t`, `t`, `t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t 346 {`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P any]`}, 347 {`package t2; type t[P interface{}] int; var _ t[int]`, `t`, `t2.t[P interface{}]`}, 348 {`package t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `t3.t[P, Q interface{}]`}, 349 {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P, Q interface{m()}]`}, 350 351 // instantiated types must be sanitized 352 {`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`}, 353 354 // go.dev/issue/45096 355 {`package issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, 356 357 // go.dev/issue/47895 358 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, 359 360 // go.dev/issue/50093 361 {`package u0a; func _[_ interface{int}]() {}`, `int`, `int`}, 362 {`package u1a; func _[_ interface{~int}]() {}`, `~int`, `~int`}, 363 {`package u2a; func _[_ interface{int | string}]() {}`, `int | string`, `int | string`}, 364 {`package u3a; func _[_ interface{int | string | ~bool}]() {}`, `int | string | ~bool`, `int | string | ~bool`}, 365 {`package u3a; func _[_ interface{int | string | ~bool}]() {}`, `int | string`, `int | string`}, 366 {`package u3a; func _[_ interface{int | string | ~bool}]() {}`, `~bool`, `~bool`}, 367 {`package u3a; func _[_ interface{int | string | ~float64|~bool}]() {}`, `int | string | ~float64`, `int | string | ~float64`}, 368 369 {`package u0b; func _[_ int]() {}`, `int`, `int`}, 370 {`package u1b; func _[_ ~int]() {}`, `~int`, `~int`}, 371 {`package u2b; func _[_ int | string]() {}`, `int | string`, `int | string`}, 372 {`package u3b; func _[_ int | string | ~bool]() {}`, `int | string | ~bool`, `int | string | ~bool`}, 373 {`package u3b; func _[_ int | string | ~bool]() {}`, `int | string`, `int | string`}, 374 {`package u3b; func _[_ int | string | ~bool]() {}`, `~bool`, `~bool`}, 375 {`package u3b; func _[_ int | string | ~float64|~bool]() {}`, `int | string | ~float64`, `int | string | ~float64`}, 376 377 {`package u0c; type _ interface{int}`, `int`, `int`}, 378 {`package u1c; type _ interface{~int}`, `~int`, `~int`}, 379 {`package u2c; type _ interface{int | string}`, `int | string`, `int | string`}, 380 {`package u3c; type _ interface{int | string | ~bool}`, `int | string | ~bool`, `int | string | ~bool`}, 381 {`package u3c; type _ interface{int | string | ~bool}`, `int | string`, `int | string`}, 382 {`package u3c; type _ interface{int | string | ~bool}`, `~bool`, `~bool`}, 383 {`package u3c; type _ interface{int | string | ~float64|~bool}`, `int | string | ~float64`, `int | string | ~float64`}, 384 385 // reverse type inference 386 {`package r1; var _ func(int) = g; func g[P any](P) {}`, `g`, `func(int)`}, 387 {`package r2; var _ func(int) = g[int]; func g[P any](P) {}`, `g`, `func[P any](P)`}, // go.dev/issues/60212 388 {`package r3; var _ func(int) = g[int]; func g[P any](P) {}`, `g[int]`, `func(int)`}, 389 {`package r4; var _ func(int, string) = g; func g[P, Q any](P, Q) {}`, `g`, `func(int, string)`}, 390 {`package r5; var _ func(int, string) = g[int]; func g[P, Q any](P, Q) {}`, `g`, `func[P, Q any](P, Q)`}, // go.dev/issues/60212 391 {`package r6; var _ func(int, string) = g[int]; func g[P, Q any](P, Q) {}`, `g[int]`, `func(int, string)`}, 392 393 {`package s1; func _() { f(g) }; func f(func(int)) {}; func g[P any](P) {}`, `g`, `func(int)`}, 394 {`package s2; func _() { f(g[int]) }; func f(func(int)) {}; func g[P any](P) {}`, `g`, `func[P any](P)`}, // go.dev/issues/60212 395 {`package s3; func _() { f(g[int]) }; func f(func(int)) {}; func g[P any](P) {}`, `g[int]`, `func(int)`}, 396 {`package s4; func _() { f(g) }; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}`, `g`, `func(int, string)`}, 397 {`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)`}, // go.dev/issues/60212 398 {`package s6; func _() { f(g[int]) }; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}`, `g[int]`, `func(int, string)`}, 399 400 {`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)`}, 401 {`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)`}, 402 {`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)`}, // go.dev/issues/60212 403 {`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)`}, 404 } 405 406 for _, test := range tests { 407 info := Info{Types: make(map[ast.Expr]TypeAndValue)} 408 var name string 409 if strings.HasPrefix(test.src, broken) { 410 pkg, err := typecheck(test.src, nil, &info) 411 if err == nil { 412 t.Errorf("package %s: expected to fail but passed", pkg.Name()) 413 continue 414 } 415 if pkg != nil { 416 name = pkg.Name() 417 } 418 } else { 419 name = mustTypecheck(test.src, nil, &info).Name() 420 } 421 422 // look for expression type 423 var typ Type 424 for e, tv := range info.Types { 425 if ExprString(e) == test.expr { 426 typ = tv.Type 427 break 428 } 429 } 430 if typ == nil { 431 t.Errorf("package %s: no type found for %s", name, test.expr) 432 continue 433 } 434 435 // check that type is correct 436 if got := typ.String(); got != test.typ { 437 t.Errorf("package %s: expr = %s: got %s; want %s", name, test.expr, got, test.typ) 438 } 439 } 440 } 441 442 func TestInstanceInfo(t *testing.T) { 443 const lib = `package lib 444 445 func F[P any](P) {} 446 447 type T[P any] []P 448 ` 449 450 type testInst struct { 451 name string 452 targs []string 453 typ string 454 } 455 456 var tests = []struct { 457 src string 458 instances []testInst // recorded instances in source order 459 }{ 460 {`package p0; func f[T any](T) {}; func _() { f(42) }`, 461 []testInst{{`f`, []string{`int`}, `func(int)`}}, 462 }, 463 {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, 464 []testInst{{`f`, []string{`rune`}, `func(rune) rune`}}, 465 }, 466 {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, 467 []testInst{{`f`, []string{`complex128`}, `func(...complex128) complex128`}}, 468 }, 469 {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, 470 []testInst{{`f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}}, 471 }, 472 {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, 473 []testInst{{`f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}}, 474 }, 475 476 {`package s1; func f[T any, P interface{*T}](x T) {}; func _(x string) { f(x) }`, 477 []testInst{{`f`, []string{`string`, `*string`}, `func(x string)`}}, 478 }, 479 {`package s2; func f[T any, P interface{*T}](x []T) {}; func _(x []int) { f(x) }`, 480 []testInst{{`f`, []string{`int`, `*int`}, `func(x []int)`}}, 481 }, 482 {`package s3; type C[T any] interface{chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, 483 []testInst{ 484 {`C`, []string{`T`}, `interface{chan<- T}`}, 485 {`f`, []string{`int`, `chan<- int`}, `func(x []int)`}, 486 }, 487 }, 488 {`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) }`, 489 []testInst{ 490 {`C`, []string{`T`}, `interface{chan<- T}`}, 491 {`C`, []string{`[]*P`}, `interface{chan<- []*P}`}, 492 {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`}, 493 }, 494 }, 495 496 {`package t1; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = f[string] }`, 497 []testInst{{`f`, []string{`string`, `*string`}, `func() string`}}, 498 }, 499 {`package t2; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = (f[string]) }`, 500 []testInst{{`f`, []string{`string`, `*string`}, `func() string`}}, 501 }, 502 {`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] }`, 503 []testInst{ 504 {`C`, []string{`T`}, `interface{chan<- T}`}, 505 {`C`, []string{`[]*P`}, `interface{chan<- []*P}`}, 506 {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`}, 507 }, 508 }, 509 {`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]) }`, 510 []testInst{ 511 {`C`, []string{`T`}, `interface{chan<- T}`}, 512 {`C`, []string{`[]*P`}, `interface{chan<- []*P}`}, 513 {`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`}, 514 }, 515 }, 516 {`package i0; import "lib"; func _() { lib.F(42) }`, 517 []testInst{{`F`, []string{`int`}, `func(int)`}}, 518 }, 519 520 {`package duplfunc0; func f[T any](T) {}; func _() { f(42); f("foo"); f[int](3) }`, 521 []testInst{ 522 {`f`, []string{`int`}, `func(int)`}, 523 {`f`, []string{`string`}, `func(string)`}, 524 {`f`, []string{`int`}, `func(int)`}, 525 }, 526 }, 527 {`package duplfunc1; import "lib"; func _() { lib.F(42); lib.F("foo"); lib.F(3) }`, 528 []testInst{ 529 {`F`, []string{`int`}, `func(int)`}, 530 {`F`, []string{`string`}, `func(string)`}, 531 {`F`, []string{`int`}, `func(int)`}, 532 }, 533 }, 534 535 {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`, 536 []testInst{{`T`, []string{`int`}, `struct{x int}`}}, 537 }, 538 {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`, 539 []testInst{{`T`, []string{`int`}, `struct{x int}`}}, 540 }, 541 {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`, 542 []testInst{{`T`, []string{`int`}, `struct{x int}`}}, 543 }, 544 {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`, 545 []testInst{{`T`, []string{`[]int`, `int`}, `struct{x []int; y int}`}}, 546 }, 547 {`package type4; import "lib"; var _ lib.T[int]`, 548 []testInst{{`T`, []string{`int`}, `[]int`}}, 549 }, 550 551 {`package dupltype0; type T[P interface{~int}] struct{ x P }; var x T[int]; var y T[int]`, 552 []testInst{ 553 {`T`, []string{`int`}, `struct{x int}`}, 554 {`T`, []string{`int`}, `struct{x int}`}, 555 }, 556 }, 557 {`package dupltype1; type T[P ~int] struct{ x P }; func (r *T[Q]) add(z T[Q]) { r.x += z.x }`, 558 []testInst{ 559 {`T`, []string{`Q`}, `struct{x Q}`}, 560 {`T`, []string{`Q`}, `struct{x Q}`}, 561 }, 562 }, 563 {`package dupltype1; import "lib"; var x lib.T[int]; var y lib.T[int]; var z lib.T[string]`, 564 []testInst{ 565 {`T`, []string{`int`}, `[]int`}, 566 {`T`, []string{`int`}, `[]int`}, 567 {`T`, []string{`string`}, `[]string`}, 568 }, 569 }, 570 {`package issue51803; func foo[T any](T) {}; func _() { foo[int]( /* leave arg away on purpose */ ) }`, 571 []testInst{{`foo`, []string{`int`}, `func(int)`}}, 572 }, 573 574 // reverse type inference 575 {`package reverse1a; var f func(int) = g; func g[P any](P) {}`, 576 []testInst{{`g`, []string{`int`}, `func(int)`}}, 577 }, 578 {`package reverse1b; func f(func(int)) {}; func g[P any](P) {}; func _() { f(g) }`, 579 []testInst{{`g`, []string{`int`}, `func(int)`}}, 580 }, 581 {`package reverse2a; var f func(int, string) = g; func g[P, Q any](P, Q) {}`, 582 []testInst{{`g`, []string{`int`, `string`}, `func(int, string)`}}, 583 }, 584 {`package reverse2b; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}; func _() { f(g) }`, 585 []testInst{{`g`, []string{`int`, `string`}, `func(int, string)`}}, 586 }, 587 {`package reverse2c; func f(func(int, string)) {}; func g[P, Q any](P, Q) {}; func _() { f(g[int]) }`, 588 []testInst{{`g`, []string{`int`, `string`}, `func(int, string)`}}, 589 }, 590 // reverse3a not possible (cannot assign to generic function outside of argument passing) 591 {`package reverse3b; func f[R any](func(int) R) {}; func g[P any](P) string { return "" }; func _() { f(g) }`, 592 []testInst{ 593 {`f`, []string{`string`}, `func(func(int) string)`}, 594 {`g`, []string{`int`}, `func(int) string`}, 595 }, 596 }, 597 {`package reverse4a; var _, _ func([]int, *float32) = g, h; func g[P, Q any]([]P, *Q) {}; func h[R any]([]R, *float32) {}`, 598 []testInst{ 599 {`g`, []string{`int`, `float32`}, `func([]int, *float32)`}, 600 {`h`, []string{`int`}, `func([]int, *float32)`}, 601 }, 602 }, 603 {`package reverse4b; func f(_, _ func([]int, *float32)) {}; func g[P, Q any]([]P, *Q) {}; func h[R any]([]R, *float32) {}; func _() { f(g, h) }`, 604 []testInst{ 605 {`g`, []string{`int`, `float32`}, `func([]int, *float32)`}, 606 {`h`, []string{`int`}, `func([]int, *float32)`}, 607 }, 608 }, 609 {`package issue59956; func f(func(int), func(string), func(bool)) {}; func g[P any](P) {}; func _() { f(g, g, g) }`, 610 []testInst{ 611 {`g`, []string{`int`}, `func(int)`}, 612 {`g`, []string{`string`}, `func(string)`}, 613 {`g`, []string{`bool`}, `func(bool)`}, 614 }, 615 }, 616 } 617 618 for _, test := range tests { 619 imports := make(testImporter) 620 conf := Config{Importer: imports} 621 instMap := make(map[*ast.Ident]Instance) 622 useMap := make(map[*ast.Ident]Object) 623 makePkg := func(src string) *Package { 624 pkg, err := typecheck(src, &conf, &Info{Instances: instMap, Uses: useMap}) 625 // allow error for issue51803 626 if err != nil && (pkg == nil || pkg.Name() != "issue51803") { 627 t.Fatal(err) 628 } 629 imports[pkg.Name()] = pkg 630 return pkg 631 } 632 makePkg(lib) 633 pkg := makePkg(test.src) 634 635 t.Run(pkg.Name(), func(t *testing.T) { 636 // Sort instances in source order for stability. 637 instances := sortedInstances(instMap) 638 if got, want := len(instances), len(test.instances); got != want { 639 t.Fatalf("got %d instances, want %d", got, want) 640 } 641 642 // Pairwise compare with the expected instances. 643 for ii, inst := range instances { 644 var targs []Type 645 for i := 0; i < inst.Inst.TypeArgs.Len(); i++ { 646 targs = append(targs, inst.Inst.TypeArgs.At(i)) 647 } 648 typ := inst.Inst.Type 649 650 testInst := test.instances[ii] 651 if got := inst.Ident.Name; got != testInst.name { 652 t.Fatalf("got name %s, want %s", got, testInst.name) 653 } 654 if len(targs) != len(testInst.targs) { 655 t.Fatalf("got %d type arguments; want %d", len(targs), len(testInst.targs)) 656 } 657 for i, targ := range targs { 658 if got := targ.String(); got != testInst.targs[i] { 659 t.Errorf("type argument %d: got %s; want %s", i, got, testInst.targs[i]) 660 } 661 } 662 if got := typ.Underlying().String(); got != testInst.typ { 663 t.Errorf("package %s: got %s; want %s", pkg.Name(), got, testInst.typ) 664 } 665 666 // Verify the invariant that re-instantiating the corresponding generic 667 // type with TypeArgs results in an identical instance. 668 ptype := useMap[inst.Ident].Type() 669 lister, _ := ptype.(interface{ TypeParams() *TypeParamList }) 670 if lister == nil || lister.TypeParams().Len() == 0 { 671 t.Fatalf("info.Types[%v] = %v, want parameterized type", inst.Ident, ptype) 672 } 673 inst2, err := Instantiate(nil, ptype, targs, true) 674 if err != nil { 675 t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err) 676 } 677 if !Identical(inst.Inst.Type, inst2) { 678 t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2) 679 } 680 } 681 }) 682 } 683 } 684 685 type recordedInstance struct { 686 Ident *ast.Ident 687 Inst Instance 688 } 689 690 func sortedInstances(m map[*ast.Ident]Instance) (instances []recordedInstance) { 691 for id, inst := range m { 692 instances = append(instances, recordedInstance{id, inst}) 693 } 694 sort.Slice(instances, func(i, j int) bool { 695 return CmpPos(instances[i].Ident.Pos(), instances[j].Ident.Pos()) < 0 696 }) 697 return instances 698 } 699 700 func TestDefsInfo(t *testing.T) { 701 var tests = []struct { 702 src string 703 obj string 704 want string 705 }{ 706 {`package p0; const x = 42`, `x`, `const p0.x untyped int`}, 707 {`package p1; const x int = 42`, `x`, `const p1.x int`}, 708 {`package p2; var x int`, `x`, `var p2.x int`}, 709 {`package p3; type x int`, `x`, `type p3.x int`}, 710 {`package p4; func f()`, `f`, `func p4.f()`}, 711 {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`}, 712 713 // Tests using generics. 714 {`package g0; type x[T any] int`, `x`, `type g0.x[T any] int`}, 715 {`package g1; func f[T any]() {}`, `f`, `func g1.f[T any]()`}, 716 {`package g2; type x[T any] int; func (*x[_]) m() {}`, `m`, `func (*g2.x[_]).m()`}, 717 } 718 719 for _, test := range tests { 720 info := Info{ 721 Defs: make(map[*ast.Ident]Object), 722 } 723 name := mustTypecheck(test.src, nil, &info).Name() 724 725 // find object 726 var def Object 727 for id, obj := range info.Defs { 728 if id.Name == test.obj { 729 def = obj 730 break 731 } 732 } 733 if def == nil { 734 t.Errorf("package %s: %s not found", name, test.obj) 735 continue 736 } 737 738 if got := def.String(); got != test.want { 739 t.Errorf("package %s: got %s; want %s", name, got, test.want) 740 } 741 } 742 } 743 744 func TestUsesInfo(t *testing.T) { 745 var tests = []struct { 746 src string 747 obj string 748 want string 749 }{ 750 {`package p0; func _() { _ = x }; const x = 42`, `x`, `const p0.x untyped int`}, 751 {`package p1; func _() { _ = x }; const x int = 42`, `x`, `const p1.x int`}, 752 {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`}, 753 {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`}, 754 {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`}, 755 756 // Tests using generics. 757 {`package g0; func _[T any]() { _ = x }; const x = 42`, `x`, `const g0.x untyped int`}, 758 {`package g1; func _[T any](x T) { }`, `T`, `type parameter T any`}, 759 {`package g2; type N[A any] int; var _ N[int]`, `N`, `type g2.N[A any] int`}, 760 {`package g3; type N[A any] int; func (N[_]) m() {}`, `N`, `type g3.N[A any] int`}, 761 762 // Uses of fields are instantiated. 763 {`package s1; type N[A any] struct{ a A }; var f = N[int]{}.a`, `a`, `field a int`}, 764 {`package s1; type N[A any] struct{ a A }; func (r N[B]) m(b B) { r.a = b }`, `a`, `field a B`}, 765 766 // Uses of methods are uses of the instantiated method. 767 {`package m0; type N[A any] int; func (r N[B]) m() { r.n() }; func (N[C]) n() {}`, `n`, `func (m0.N[B]).n()`}, 768 {`package m1; type N[A any] int; func (r N[B]) m() { }; var f = N[int].m`, `m`, `func (m1.N[int]).m()`}, 769 {`package m2; func _[A any](v interface{ m() A }) { v.m() }`, `m`, `func (interface).m() A`}, 770 {`package m3; func f[A any]() interface{ m() A } { return nil }; var _ = f[int]().m()`, `m`, `func (interface).m() int`}, 771 {`package m4; type T[A any] func() interface{ m() A }; var x T[int]; var y = x().m`, `m`, `func (interface).m() int`}, 772 {`package m5; type T[A any] interface{ m() A }; func _[B any](t T[B]) { t.m() }`, `m`, `func (m5.T[B]).m() B`}, 773 {`package m6; type T[A any] interface{ m() }; func _[B any](t T[B]) { t.m() }`, `m`, `func (m6.T[B]).m()`}, 774 {`package m7; type T[A any] interface{ m() A }; func _(t T[int]) { t.m() }`, `m`, `func (m7.T[int]).m() int`}, 775 {`package m8; type T[A any] interface{ m() }; func _(t T[int]) { t.m() }`, `m`, `func (m8.T[int]).m()`}, 776 {`package m9; type T[A any] interface{ m() }; func _(t T[int]) { _ = t.m }`, `m`, `func (m9.T[int]).m()`}, 777 { 778 `package m10; type E[A any] interface{ m() }; type T[B any] interface{ E[B]; n() }; func _(t T[int]) { t.m() }`, 779 `m`, 780 `func (m10.E[int]).m()`, 781 }, 782 {`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()`}, 783 {`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()`}, 784 } 785 786 for _, test := range tests { 787 info := Info{ 788 Uses: make(map[*ast.Ident]Object), 789 } 790 name := mustTypecheck(test.src, nil, &info).Name() 791 792 // find object 793 var use Object 794 for id, obj := range info.Uses { 795 if id.Name == test.obj { 796 if use != nil { 797 panic(fmt.Sprintf("multiple uses of %q", id.Name)) 798 } 799 use = obj 800 } 801 } 802 if use == nil { 803 t.Errorf("package %s: %s not found", name, test.obj) 804 continue 805 } 806 807 if got := use.String(); got != test.want { 808 t.Errorf("package %s: got %s; want %s", name, got, test.want) 809 } 810 } 811 } 812 813 func TestGenericMethodInfo(t *testing.T) { 814 src := `package p 815 816 type N[A any] int 817 818 func (r N[B]) m() { r.m(); r.n() } 819 820 func (r *N[C]) n() { } 821 ` 822 fset := token.NewFileSet() 823 f := mustParse(fset, src) 824 info := Info{ 825 Defs: make(map[*ast.Ident]Object), 826 Uses: make(map[*ast.Ident]Object), 827 Selections: make(map[*ast.SelectorExpr]*Selection), 828 } 829 var conf Config 830 pkg, err := conf.Check("p", fset, []*ast.File{f}, &info) 831 if err != nil { 832 t.Fatal(err) 833 } 834 835 N := pkg.Scope().Lookup("N").Type().(*Named) 836 837 // Find the generic methods stored on N. 838 gm, gn := N.Method(0), N.Method(1) 839 if gm.Name() == "n" { 840 gm, gn = gn, gm 841 } 842 843 // Collect objects from info. 844 var dm, dn *Func // the declared methods 845 var dmm, dmn *Func // the methods used in the body of m 846 for _, decl := range f.Decls { 847 fdecl, ok := decl.(*ast.FuncDecl) 848 if !ok { 849 continue 850 } 851 def := info.Defs[fdecl.Name].(*Func) 852 switch fdecl.Name.Name { 853 case "m": 854 dm = def 855 ast.Inspect(fdecl.Body, func(n ast.Node) bool { 856 if call, ok := n.(*ast.CallExpr); ok { 857 sel := call.Fun.(*ast.SelectorExpr) 858 use := info.Uses[sel.Sel].(*Func) 859 selection := info.Selections[sel] 860 if selection.Kind() != MethodVal { 861 t.Errorf("Selection kind = %v, want %v", selection.Kind(), MethodVal) 862 } 863 if selection.Obj() != use { 864 t.Errorf("info.Selections contains %v, want %v", selection.Obj(), use) 865 } 866 switch sel.Sel.Name { 867 case "m": 868 dmm = use 869 case "n": 870 dmn = use 871 } 872 } 873 return true 874 }) 875 case "n": 876 dn = def 877 } 878 } 879 880 if gm != dm { 881 t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm) 882 } 883 if gn != dn { 884 t.Errorf(`N.Method(...) returns %v for "m", but Info.Defs has %v`, gm, dm) 885 } 886 if dmm != dm { 887 t.Errorf(`Inside "m", r.m uses %v, want the defined func %v`, dmm, dm) 888 } 889 if dmn == dn { 890 t.Errorf(`Inside "m", r.n uses %v, want a func distinct from %v`, dmm, dm) 891 } 892 } 893 894 func TestImplicitsInfo(t *testing.T) { 895 testenv.MustHaveGoBuild(t) 896 897 var tests = []struct { 898 src string 899 want string 900 }{ 901 {`package p2; import . "fmt"; var _ = Println`, ""}, // no Implicits entry 902 {`package p0; import local "fmt"; var _ = local.Println`, ""}, // no Implicits entry 903 {`package p1; import "fmt"; var _ = fmt.Println`, "importSpec: package fmt"}, 904 905 {`package p3; func f(x interface{}) { switch x.(type) { case int: } }`, ""}, // no Implicits entry 906 {`package p4; func f(x interface{}) { switch t := x.(type) { case int: _ = t } }`, "caseClause: var t int"}, 907 {`package p5; func f(x interface{}) { switch t := x.(type) { case int, uint: _ = t } }`, "caseClause: var t interface{}"}, 908 {`package p6; func f(x interface{}) { switch t := x.(type) { default: _ = t } }`, "caseClause: var t interface{}"}, 909 910 {`package p7; func f(x int) {}`, ""}, // no Implicits entry 911 {`package p8; func f(int) {}`, "field: var int"}, 912 {`package p9; func f() (complex64) { return 0 }`, "field: var complex64"}, 913 {`package p10; type T struct{}; func (*T) f() {}`, "field: var *p10.T"}, 914 915 // Tests using generics. 916 {`package f0; func f[T any](x int) {}`, ""}, // no Implicits entry 917 {`package f1; func f[T any](int) {}`, "field: var int"}, 918 {`package f2; func f[T any](T) {}`, "field: var T"}, 919 {`package f3; func f[T any]() (complex64) { return 0 }`, "field: var complex64"}, 920 {`package f4; func f[T any](t T) (T) { return t }`, "field: var T"}, 921 {`package t0; type T[A any] struct{}; func (*T[_]) f() {}`, "field: var *t0.T[_]"}, 922 {`package t1; type T[A any] struct{}; func _(x interface{}) { switch t := x.(type) { case T[int]: _ = t } }`, "caseClause: var t t1.T[int]"}, 923 {`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]"}, 924 {`package t3; func _[P any](x interface{}) { switch t := x.(type) { case P: _ = t } }`, "caseClause: var t P"}, 925 } 926 927 for _, test := range tests { 928 info := Info{ 929 Implicits: make(map[ast.Node]Object), 930 } 931 name := mustTypecheck(test.src, nil, &info).Name() 932 933 // the test cases expect at most one Implicits entry 934 if len(info.Implicits) > 1 { 935 t.Errorf("package %s: %d Implicits entries found", name, len(info.Implicits)) 936 continue 937 } 938 939 // extract Implicits entry, if any 940 var got string 941 for n, obj := range info.Implicits { 942 switch x := n.(type) { 943 case *ast.ImportSpec: 944 got = "importSpec" 945 case *ast.CaseClause: 946 got = "caseClause" 947 case *ast.Field: 948 got = "field" 949 default: 950 t.Fatalf("package %s: unexpected %T", name, x) 951 } 952 got += ": " + obj.String() 953 } 954 955 // verify entry 956 if got != test.want { 957 t.Errorf("package %s: got %q; want %q", name, got, test.want) 958 } 959 } 960 } 961 962 func predString(tv TypeAndValue) string { 963 var buf strings.Builder 964 pred := func(b bool, s string) { 965 if b { 966 if buf.Len() > 0 { 967 buf.WriteString(", ") 968 } 969 buf.WriteString(s) 970 } 971 } 972 973 pred(tv.IsVoid(), "void") 974 pred(tv.IsType(), "type") 975 pred(tv.IsBuiltin(), "builtin") 976 pred(tv.IsValue() && tv.Value != nil, "const") 977 pred(tv.IsValue() && tv.Value == nil, "value") 978 pred(tv.IsNil(), "nil") 979 pred(tv.Addressable(), "addressable") 980 pred(tv.Assignable(), "assignable") 981 pred(tv.HasOk(), "hasOk") 982 983 if buf.Len() == 0 { 984 return "invalid" 985 } 986 return buf.String() 987 } 988 989 func TestPredicatesInfo(t *testing.T) { 990 testenv.MustHaveGoBuild(t) 991 992 var tests = []struct { 993 src string 994 expr string 995 pred string 996 }{ 997 // void 998 {`package n0; func f() { f() }`, `f()`, `void`}, 999 1000 // types 1001 {`package t0; type _ int`, `int`, `type`}, 1002 {`package t1; type _ []int`, `[]int`, `type`}, 1003 {`package t2; type _ func()`, `func()`, `type`}, 1004 {`package t3; type _ func(int)`, `int`, `type`}, 1005 {`package t3; type _ func(...int)`, `...int`, `type`}, 1006 1007 // built-ins 1008 {`package b0; var _ = len("")`, `len`, `builtin`}, 1009 {`package b1; var _ = (len)("")`, `(len)`, `builtin`}, 1010 1011 // constants 1012 {`package c0; var _ = 42`, `42`, `const`}, 1013 {`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`}, 1014 {`package c2; const (i = 1i; _ = i)`, `i`, `const`}, 1015 1016 // values 1017 {`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`}, 1018 {`package v1; var _ = &[]int{1}`, `[]int{…}`, `value`}, 1019 {`package v2; var _ = func(){}`, `(func() literal)`, `value`}, 1020 {`package v4; func f() { _ = f }`, `f`, `value`}, 1021 {`package v3; var _ *int = nil`, `nil`, `value, nil`}, 1022 {`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`}, 1023 1024 // addressable (and thus assignable) operands 1025 {`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`}, 1026 {`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`}, 1027 {`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`}, 1028 {`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`}, 1029 {`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`}, 1030 {`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`}, 1031 {`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`}, 1032 {`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`}, 1033 // composite literals are not addressable 1034 1035 // assignable but not addressable values 1036 {`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`}, 1037 {`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`}, 1038 1039 // hasOk expressions 1040 {`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`}, 1041 {`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`}, 1042 1043 // missing entries 1044 // - package names are collected in the Uses map 1045 // - identifiers being declared are collected in the Defs map 1046 {`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`}, 1047 {`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`}, 1048 {`package m2; const c = 0`, `c`, `<missing>`}, 1049 {`package m3; type T int`, `T`, `<missing>`}, 1050 {`package m4; var v int`, `v`, `<missing>`}, 1051 {`package m5; func f() {}`, `f`, `<missing>`}, 1052 {`package m6; func _(x int) {}`, `x`, `<missing>`}, 1053 {`package m6; func _()(x int) { return }`, `x`, `<missing>`}, 1054 {`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`}, 1055 } 1056 1057 for _, test := range tests { 1058 info := Info{Types: make(map[ast.Expr]TypeAndValue)} 1059 name := mustTypecheck(test.src, nil, &info).Name() 1060 1061 // look for expression predicates 1062 got := "<missing>" 1063 for e, tv := range info.Types { 1064 //println(name, ExprString(e)) 1065 if ExprString(e) == test.expr { 1066 got = predString(tv) 1067 break 1068 } 1069 } 1070 1071 if got != test.pred { 1072 t.Errorf("package %s: got %s; want %s", name, got, test.pred) 1073 } 1074 } 1075 } 1076 1077 func TestScopesInfo(t *testing.T) { 1078 testenv.MustHaveGoBuild(t) 1079 1080 var tests = []struct { 1081 src string 1082 scopes []string // list of scope descriptors of the form kind:varlist 1083 }{ 1084 {`package p0`, []string{ 1085 "file:", 1086 }}, 1087 {`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{ 1088 "file:fmt m", 1089 }}, 1090 {`package p2; func _() {}`, []string{ 1091 "file:", "func:", 1092 }}, 1093 {`package p3; func _(x, y int) {}`, []string{ 1094 "file:", "func:x y", 1095 }}, 1096 {`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{ 1097 "file:", "func:x y z", // redeclaration of x 1098 }}, 1099 {`package p5; func _(x, y int) (u, _ int) { return }`, []string{ 1100 "file:", "func:u x y", 1101 }}, 1102 {`package p6; func _() { { var x int; _ = x } }`, []string{ 1103 "file:", "func:", "block:x", 1104 }}, 1105 {`package p7; func _() { if true {} }`, []string{ 1106 "file:", "func:", "if:", "block:", 1107 }}, 1108 {`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{ 1109 "file:", "func:", "if:x", "block:y", 1110 }}, 1111 {`package p9; func _() { switch x := 0; x {} }`, []string{ 1112 "file:", "func:", "switch:x", 1113 }}, 1114 {`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{ 1115 "file:", "func:", "switch:x", "case:y", "case:", 1116 }}, 1117 {`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{ 1118 "file:", "func:t", "type switch:", 1119 }}, 1120 {`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{ 1121 "file:", "func:t", "type switch:t", 1122 }}, 1123 {`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{ 1124 "file:", "func:t", "type switch:", "case:x", // x implicitly declared 1125 }}, 1126 {`package p14; func _() { select{} }`, []string{ 1127 "file:", "func:", 1128 }}, 1129 {`package p15; func _(c chan int) { select{ case <-c: } }`, []string{ 1130 "file:", "func:c", "comm:", 1131 }}, 1132 {`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{ 1133 "file:", "func:c", "comm:i x", 1134 }}, 1135 {`package p17; func _() { for{} }`, []string{ 1136 "file:", "func:", "for:", "block:", 1137 }}, 1138 {`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{ 1139 "file:", "func:n", "for:i", "block:", 1140 }}, 1141 {`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{ 1142 "file:", "func:a", "range:i", "block:", 1143 }}, 1144 {`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{ 1145 "file:", "func:a", "range:i x", "block:", 1146 }}, 1147 } 1148 1149 for _, test := range tests { 1150 info := Info{Scopes: make(map[ast.Node]*Scope)} 1151 name := mustTypecheck(test.src, nil, &info).Name() 1152 1153 // number of scopes must match 1154 if len(info.Scopes) != len(test.scopes) { 1155 t.Errorf("package %s: got %d scopes; want %d", name, len(info.Scopes), len(test.scopes)) 1156 } 1157 1158 // scope descriptions must match 1159 for node, scope := range info.Scopes { 1160 kind := "<unknown node kind>" 1161 switch node.(type) { 1162 case *ast.File: 1163 kind = "file" 1164 case *ast.FuncType: 1165 kind = "func" 1166 case *ast.BlockStmt: 1167 kind = "block" 1168 case *ast.IfStmt: 1169 kind = "if" 1170 case *ast.SwitchStmt: 1171 kind = "switch" 1172 case *ast.TypeSwitchStmt: 1173 kind = "type switch" 1174 case *ast.CaseClause: 1175 kind = "case" 1176 case *ast.CommClause: 1177 kind = "comm" 1178 case *ast.ForStmt: 1179 kind = "for" 1180 case *ast.RangeStmt: 1181 kind = "range" 1182 } 1183 1184 // look for matching scope description 1185 desc := kind + ":" + strings.Join(scope.Names(), " ") 1186 found := false 1187 for _, d := range test.scopes { 1188 if desc == d { 1189 found = true 1190 break 1191 } 1192 } 1193 if !found { 1194 t.Errorf("package %s: no matching scope found for %s", name, desc) 1195 } 1196 } 1197 } 1198 } 1199 1200 func TestInitOrderInfo(t *testing.T) { 1201 var tests = []struct { 1202 src string 1203 inits []string 1204 }{ 1205 {`package p0; var (x = 1; y = x)`, []string{ 1206 "x = 1", "y = x", 1207 }}, 1208 {`package p1; var (a = 1; b = 2; c = 3)`, []string{ 1209 "a = 1", "b = 2", "c = 3", 1210 }}, 1211 {`package p2; var (a, b, c = 1, 2, 3)`, []string{ 1212 "a = 1", "b = 2", "c = 3", 1213 }}, 1214 {`package p3; var _ = f(); func f() int { return 1 }`, []string{ 1215 "_ = f()", // blank var 1216 }}, 1217 {`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{ 1218 "a = 0", "z = 0", "y = z", "x = y", 1219 }}, 1220 {`package p5; var (a, _ = m[0]; m map[int]string)`, []string{ 1221 "a, _ = m[0]", // blank var 1222 }}, 1223 {`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{ 1224 "z = 0", "a, b = f()", 1225 }}, 1226 {`package p7; var (a = func() int { return b }(); b = 1)`, []string{ 1227 "b = 1", "a = (func() int literal)()", 1228 }}, 1229 {`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{ 1230 "c = 1", "a, b = (func() (_, _ int) literal)()", 1231 }}, 1232 {`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{ 1233 "y = 1", "x = T.m", 1234 }}, 1235 {`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{ 1236 "a = 0", "b = 0", "c = 0", "d = c + b", 1237 }}, 1238 {`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{ 1239 "c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c", 1240 }}, 1241 // emit an initializer for n:1 initializations only once (not for each node 1242 // on the lhs which may appear in different order in the dependency graph) 1243 {`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{ 1244 "b = 0", "x, y = m[0]", "a = x", 1245 }}, 1246 // test case from spec section on package initialization 1247 {`package p12 1248 1249 var ( 1250 a = c + b 1251 b = f() 1252 c = f() 1253 d = 3 1254 ) 1255 1256 func f() int { 1257 d++ 1258 return d 1259 }`, []string{ 1260 "d = 3", "b = f()", "c = f()", "a = c + b", 1261 }}, 1262 // test case for go.dev/issue/7131 1263 {`package main 1264 1265 var counter int 1266 func next() int { counter++; return counter } 1267 1268 var _ = makeOrder() 1269 func makeOrder() []int { return []int{f, b, d, e, c, a} } 1270 1271 var a = next() 1272 var b, c = next(), next() 1273 var d, e, f = next(), next(), next() 1274 `, []string{ 1275 "a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()", 1276 }}, 1277 // test case for go.dev/issue/10709 1278 {`package p13 1279 1280 var ( 1281 v = t.m() 1282 t = makeT(0) 1283 ) 1284 1285 type T struct{} 1286 1287 func (T) m() int { return 0 } 1288 1289 func makeT(n int) T { 1290 if n > 0 { 1291 return makeT(n-1) 1292 } 1293 return T{} 1294 }`, []string{ 1295 "t = makeT(0)", "v = t.m()", 1296 }}, 1297 // test case for go.dev/issue/10709: same as test before, but variable decls swapped 1298 {`package p14 1299 1300 var ( 1301 t = makeT(0) 1302 v = t.m() 1303 ) 1304 1305 type T struct{} 1306 1307 func (T) m() int { return 0 } 1308 1309 func makeT(n int) T { 1310 if n > 0 { 1311 return makeT(n-1) 1312 } 1313 return T{} 1314 }`, []string{ 1315 "t = makeT(0)", "v = t.m()", 1316 }}, 1317 // another candidate possibly causing problems with go.dev/issue/10709 1318 {`package p15 1319 1320 var y1 = f1() 1321 1322 func f1() int { return g1() } 1323 func g1() int { f1(); return x1 } 1324 1325 var x1 = 0 1326 1327 var y2 = f2() 1328 1329 func f2() int { return g2() } 1330 func g2() int { return x2 } 1331 1332 var x2 = 0`, []string{ 1333 "x1 = 0", "y1 = f1()", "x2 = 0", "y2 = f2()", 1334 }}, 1335 } 1336 1337 for _, test := range tests { 1338 info := Info{} 1339 name := mustTypecheck(test.src, nil, &info).Name() 1340 1341 // number of initializers must match 1342 if len(info.InitOrder) != len(test.inits) { 1343 t.Errorf("package %s: got %d initializers; want %d", name, len(info.InitOrder), len(test.inits)) 1344 continue 1345 } 1346 1347 // initializers must match 1348 for i, want := range test.inits { 1349 got := info.InitOrder[i].String() 1350 if got != want { 1351 t.Errorf("package %s, init %d: got %s; want %s", name, i, got, want) 1352 continue 1353 } 1354 } 1355 } 1356 } 1357 1358 func TestMultiFileInitOrder(t *testing.T) { 1359 fset := token.NewFileSet() 1360 fileA := mustParse(fset, `package main; var a = 1`) 1361 fileB := mustParse(fset, `package main; var b = 2`) 1362 1363 // The initialization order must not depend on the parse 1364 // order of the files, only on the presentation order to 1365 // the type-checker. 1366 for _, test := range []struct { 1367 files []*ast.File 1368 want string 1369 }{ 1370 {[]*ast.File{fileA, fileB}, "[a = 1 b = 2]"}, 1371 {[]*ast.File{fileB, fileA}, "[b = 2 a = 1]"}, 1372 } { 1373 var info Info 1374 if _, err := new(Config).Check("main", fset, test.files, &info); err != nil { 1375 t.Fatal(err) 1376 } 1377 if got := fmt.Sprint(info.InitOrder); got != test.want { 1378 t.Fatalf("got %s; want %s", got, test.want) 1379 } 1380 } 1381 } 1382 1383 func TestFiles(t *testing.T) { 1384 var sources = []string{ 1385 "package p; type T struct{}; func (T) m1() {}", 1386 "package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}", 1387 "package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}", 1388 "package p", 1389 } 1390 1391 var conf Config 1392 fset := token.NewFileSet() 1393 pkg := NewPackage("p", "p") 1394 var info Info 1395 check := NewChecker(&conf, fset, pkg, &info) 1396 1397 for _, src := range sources { 1398 if err := check.Files([]*ast.File{mustParse(fset, src)}); err != nil { 1399 t.Error(err) 1400 } 1401 } 1402 1403 // check InitOrder is [x y] 1404 var vars []string 1405 for _, init := range info.InitOrder { 1406 for _, v := range init.Lhs { 1407 vars = append(vars, v.Name()) 1408 } 1409 } 1410 if got, want := fmt.Sprint(vars), "[x y]"; got != want { 1411 t.Errorf("InitOrder == %s, want %s", got, want) 1412 } 1413 } 1414 1415 type testImporter map[string]*Package 1416 1417 func (m testImporter) Import(path string) (*Package, error) { 1418 if pkg := m[path]; pkg != nil { 1419 return pkg, nil 1420 } 1421 return nil, fmt.Errorf("package %q not found", path) 1422 } 1423 1424 func TestSelection(t *testing.T) { 1425 selections := make(map[*ast.SelectorExpr]*Selection) 1426 1427 // We need a specific fileset in this test below for positions. 1428 // Cannot use typecheck helper. 1429 fset := token.NewFileSet() 1430 imports := make(testImporter) 1431 conf := Config{Importer: imports} 1432 makePkg := func(path, src string) { 1433 pkg, err := conf.Check(path, fset, []*ast.File{mustParse(fset, src)}, &Info{Selections: selections}) 1434 if err != nil { 1435 t.Fatal(err) 1436 } 1437 imports[path] = pkg 1438 } 1439 1440 const libSrc = ` 1441 package lib 1442 type T float64 1443 const C T = 3 1444 var V T 1445 func F() {} 1446 func (T) M() {} 1447 ` 1448 const mainSrc = ` 1449 package main 1450 import "lib" 1451 1452 type A struct { 1453 *B 1454 C 1455 } 1456 1457 type B struct { 1458 b int 1459 } 1460 1461 func (B) f(int) 1462 1463 type C struct { 1464 c int 1465 } 1466 1467 type G[P any] struct { 1468 p P 1469 } 1470 1471 func (G[P]) m(P) {} 1472 1473 var Inst G[int] 1474 1475 func (C) g() 1476 func (*C) h() 1477 1478 func main() { 1479 // qualified identifiers 1480 var _ lib.T 1481 _ = lib.C 1482 _ = lib.F 1483 _ = lib.V 1484 _ = lib.T.M 1485 1486 // fields 1487 _ = A{}.B 1488 _ = new(A).B 1489 1490 _ = A{}.C 1491 _ = new(A).C 1492 1493 _ = A{}.b 1494 _ = new(A).b 1495 1496 _ = A{}.c 1497 _ = new(A).c 1498 1499 _ = Inst.p 1500 _ = G[string]{}.p 1501 1502 // methods 1503 _ = A{}.f 1504 _ = new(A).f 1505 _ = A{}.g 1506 _ = new(A).g 1507 _ = new(A).h 1508 1509 _ = B{}.f 1510 _ = new(B).f 1511 1512 _ = C{}.g 1513 _ = new(C).g 1514 _ = new(C).h 1515 _ = Inst.m 1516 1517 // method expressions 1518 _ = A.f 1519 _ = (*A).f 1520 _ = B.f 1521 _ = (*B).f 1522 _ = G[string].m 1523 }` 1524 1525 wantOut := map[string][2]string{ 1526 "lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"}, 1527 1528 "A{}.B": {"field (main.A) B *main.B", ".[0]"}, 1529 "new(A).B": {"field (*main.A) B *main.B", "->[0]"}, 1530 "A{}.C": {"field (main.A) C main.C", ".[1]"}, 1531 "new(A).C": {"field (*main.A) C main.C", "->[1]"}, 1532 "A{}.b": {"field (main.A) b int", "->[0 0]"}, 1533 "new(A).b": {"field (*main.A) b int", "->[0 0]"}, 1534 "A{}.c": {"field (main.A) c int", ".[1 0]"}, 1535 "new(A).c": {"field (*main.A) c int", "->[1 0]"}, 1536 "Inst.p": {"field (main.G[int]) p int", ".[0]"}, 1537 1538 "A{}.f": {"method (main.A) f(int)", "->[0 0]"}, 1539 "new(A).f": {"method (*main.A) f(int)", "->[0 0]"}, 1540 "A{}.g": {"method (main.A) g()", ".[1 0]"}, 1541 "new(A).g": {"method (*main.A) g()", "->[1 0]"}, 1542 "new(A).h": {"method (*main.A) h()", "->[1 1]"}, // TODO(gri) should this report .[1 1] ? 1543 "B{}.f": {"method (main.B) f(int)", ".[0]"}, 1544 "new(B).f": {"method (*main.B) f(int)", "->[0]"}, 1545 "C{}.g": {"method (main.C) g()", ".[0]"}, 1546 "new(C).g": {"method (*main.C) g()", "->[0]"}, 1547 "new(C).h": {"method (*main.C) h()", "->[1]"}, // TODO(gri) should this report .[1] ? 1548 "Inst.m": {"method (main.G[int]) m(int)", ".[0]"}, 1549 1550 "A.f": {"method expr (main.A) f(main.A, int)", "->[0 0]"}, 1551 "(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"}, 1552 "B.f": {"method expr (main.B) f(main.B, int)", ".[0]"}, 1553 "(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"}, 1554 "G[string].m": {"method expr (main.G[string]) m(main.G[string], string)", ".[0]"}, 1555 "G[string]{}.p": {"field (main.G[string]) p string", ".[0]"}, 1556 } 1557 1558 makePkg("lib", libSrc) 1559 makePkg("main", mainSrc) 1560 1561 for e, sel := range selections { 1562 _ = sel.String() // assertion: must not panic 1563 1564 start := fset.Position(e.Pos()).Offset 1565 end := fset.Position(e.End()).Offset 1566 syntax := mainSrc[start:end] // (all SelectorExprs are in main, not lib) 1567 1568 direct := "." 1569 if sel.Indirect() { 1570 direct = "->" 1571 } 1572 got := [2]string{ 1573 sel.String(), 1574 fmt.Sprintf("%s%v", direct, sel.Index()), 1575 } 1576 want := wantOut[syntax] 1577 if want != got { 1578 t.Errorf("%s: got %q; want %q", syntax, got, want) 1579 } 1580 delete(wantOut, syntax) 1581 1582 // We must explicitly assert properties of the 1583 // Signature's receiver since it doesn't participate 1584 // in Identical() or String(). 1585 sig, _ := sel.Type().(*Signature) 1586 if sel.Kind() == MethodVal { 1587 got := sig.Recv().Type() 1588 want := sel.Recv() 1589 if !Identical(got, want) { 1590 t.Errorf("%s: Recv() = %s, want %s", syntax, got, want) 1591 } 1592 } else if sig != nil && sig.Recv() != nil { 1593 t.Errorf("%s: signature has receiver %s", sig, sig.Recv().Type()) 1594 } 1595 } 1596 // Assert that all wantOut entries were used exactly once. 1597 for syntax := range wantOut { 1598 t.Errorf("no ast.Selection found with syntax %q", syntax) 1599 } 1600 } 1601 1602 func TestIssue8518(t *testing.T) { 1603 fset := token.NewFileSet() 1604 imports := make(testImporter) 1605 conf := Config{ 1606 Error: func(err error) { t.Log(err) }, // don't exit after first error 1607 Importer: imports, 1608 } 1609 makePkg := func(path, src string) { 1610 imports[path], _ = conf.Check(path, fset, []*ast.File{mustParse(fset, src)}, nil) // errors logged via conf.Error 1611 } 1612 1613 const libSrc = ` 1614 package a 1615 import "missing" 1616 const C1 = foo 1617 const C2 = missing.C 1618 ` 1619 1620 const mainSrc = ` 1621 package main 1622 import "a" 1623 var _ = a.C1 1624 var _ = a.C2 1625 ` 1626 1627 makePkg("a", libSrc) 1628 makePkg("main", mainSrc) // don't crash when type-checking this package 1629 } 1630 1631 func TestIssue59603(t *testing.T) { 1632 fset := token.NewFileSet() 1633 imports := make(testImporter) 1634 conf := Config{ 1635 Error: func(err error) { t.Log(err) }, // don't exit after first error 1636 Importer: imports, 1637 } 1638 makePkg := func(path, src string) { 1639 imports[path], _ = conf.Check(path, fset, []*ast.File{mustParse(fset, src)}, nil) // errors logged via conf.Error 1640 } 1641 1642 const libSrc = ` 1643 package a 1644 const C = foo 1645 ` 1646 1647 const mainSrc = ` 1648 package main 1649 import "a" 1650 const _ = a.C 1651 ` 1652 1653 makePkg("a", libSrc) 1654 makePkg("main", mainSrc) // don't crash when type-checking this package 1655 } 1656 1657 func TestLookupFieldOrMethodOnNil(t *testing.T) { 1658 // LookupFieldOrMethod on a nil type is expected to produce a run-time panic. 1659 defer func() { 1660 const want = "LookupFieldOrMethod on nil type" 1661 p := recover() 1662 if s, ok := p.(string); !ok || s != want { 1663 t.Fatalf("got %v, want %s", p, want) 1664 } 1665 }() 1666 LookupFieldOrMethod(nil, false, nil, "") 1667 } 1668 1669 func TestLookupFieldOrMethod(t *testing.T) { 1670 // Test cases assume a lookup of the form a.f or x.f, where a stands for an 1671 // addressable value, and x for a non-addressable value (even though a variable 1672 // for ease of test case writing). 1673 // 1674 // Should be kept in sync with TestMethodSet. 1675 var tests = []struct { 1676 src string 1677 found bool 1678 index []int 1679 indirect bool 1680 }{ 1681 // field lookups 1682 {"var x T; type T struct{}", false, nil, false}, 1683 {"var x T; type T struct{ f int }", true, []int{0}, false}, 1684 {"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false}, 1685 1686 // field lookups on a generic type 1687 {"var x T[int]; type T[P any] struct{}", false, nil, false}, 1688 {"var x T[int]; type T[P any] struct{ f P }", true, []int{0}, false}, 1689 {"var x T[int]; type T[P any] struct{ a, b, f, c P }", true, []int{2}, false}, 1690 1691 // method lookups 1692 {"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false}, 1693 {"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true}, 1694 {"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false}, 1695 {"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false? 1696 1697 // method lookups on a generic type 1698 {"var a T[int]; type T[P any] struct{}; func (T[P]) f() {}", true, []int{0}, false}, 1699 {"var a *T[int]; type T[P any] struct{}; func (T[P]) f() {}", true, []int{0}, true}, 1700 {"var a T[int]; type T[P any] struct{}; func (*T[P]) f() {}", true, []int{0}, false}, 1701 {"var a *T[int]; type T[P any] struct{}; func (*T[P]) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false? 1702 1703 // collisions 1704 {"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false}, 1705 {"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false}, 1706 1707 // collisions on a generic type 1708 {"type ( E1[P any] struct{ f P }; E2[P any] struct{ f P }; x struct{ E1[int]; *E2[int] })", false, []int{1, 0}, false}, 1709 {"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}, 1710 1711 // outside methodset 1712 // (*T).f method exists, but value of type T is not addressable 1713 {"var x T; type T struct{}; func (*T) f() {}", false, nil, true}, 1714 1715 // outside method set of a generic type 1716 {"var x T[int]; type T[P any] struct{}; func (*T[P]) f() {}", false, nil, true}, 1717 1718 // recursive generic types; see go.dev/issue/52715 1719 {"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}, 1720 {"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}, 1721 } 1722 1723 for _, test := range tests { 1724 pkg := mustTypecheck("package p;"+test.src, nil, nil) 1725 1726 obj := pkg.Scope().Lookup("a") 1727 if obj == nil { 1728 if obj = pkg.Scope().Lookup("x"); obj == nil { 1729 t.Errorf("%s: incorrect test case - no object a or x", test.src) 1730 continue 1731 } 1732 } 1733 1734 f, index, indirect := LookupFieldOrMethod(obj.Type(), obj.Name() == "a", pkg, "f") 1735 if (f != nil) != test.found { 1736 if f == nil { 1737 t.Errorf("%s: got no object; want one", test.src) 1738 } else { 1739 t.Errorf("%s: got object = %v; want none", test.src, f) 1740 } 1741 } 1742 if !sameSlice(index, test.index) { 1743 t.Errorf("%s: got index = %v; want %v", test.src, index, test.index) 1744 } 1745 if indirect != test.indirect { 1746 t.Errorf("%s: got indirect = %v; want %v", test.src, indirect, test.indirect) 1747 } 1748 } 1749 } 1750 1751 // Test for go.dev/issue/52715 1752 func TestLookupFieldOrMethod_RecursiveGeneric(t *testing.T) { 1753 const src = ` 1754 package pkg 1755 1756 type Tree[T any] struct { 1757 *Node[T] 1758 } 1759 1760 func (*Tree[R]) N(r R) R { return r } 1761 1762 type Node[T any] struct { 1763 *Tree[T] 1764 } 1765 1766 type Instance = *Tree[int] 1767 ` 1768 1769 fset := token.NewFileSet() 1770 f := mustParse(fset, src) 1771 pkg := NewPackage("pkg", f.Name.Name) 1772 if err := NewChecker(nil, fset, pkg, nil).Files([]*ast.File{f}); err != nil { 1773 panic(err) 1774 } 1775 1776 T := pkg.Scope().Lookup("Instance").Type() 1777 _, _, _ = LookupFieldOrMethod(T, false, pkg, "M") // verify that LookupFieldOrMethod terminates 1778 } 1779 1780 func sameSlice(a, b []int) bool { 1781 if len(a) != len(b) { 1782 return false 1783 } 1784 for i, x := range a { 1785 if x != b[i] { 1786 return false 1787 } 1788 } 1789 return true 1790 } 1791 1792 // TestScopeLookupParent ensures that (*Scope).LookupParent returns 1793 // the correct result at various positions with the source. 1794 func TestScopeLookupParent(t *testing.T) { 1795 fset := token.NewFileSet() 1796 imports := make(testImporter) 1797 conf := Config{Importer: imports} 1798 var info Info 1799 makePkg := func(path string, files ...*ast.File) { 1800 var err error 1801 imports[path], err = conf.Check(path, fset, files, &info) 1802 if err != nil { 1803 t.Fatal(err) 1804 } 1805 } 1806 1807 makePkg("lib", mustParse(fset, "package lib; var X int")) 1808 // Each /*name=kind:line*/ comment makes the test look up the 1809 // name at that point and checks that it resolves to a decl of 1810 // the specified kind and line number. "undef" means undefined. 1811 mainSrc := ` 1812 /*lib=pkgname:5*/ /*X=var:1*/ /*Pi=const:8*/ /*T=typename:9*/ /*Y=var:10*/ /*F=func:12*/ 1813 package main 1814 1815 import "lib" 1816 import . "lib" 1817 1818 const Pi = 3.1415 1819 type T struct{} 1820 var Y, _ = lib.X, X 1821 1822 func F(){ 1823 const pi, e = 3.1415, /*pi=undef*/ 2.71828 /*pi=const:13*/ /*e=const:13*/ 1824 type /*t=undef*/ t /*t=typename:14*/ *t 1825 print(Y) /*Y=var:10*/ 1826 x, Y := Y, /*x=undef*/ /*Y=var:10*/ Pi /*x=var:16*/ /*Y=var:16*/ ; _ = x; _ = Y 1827 var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F 1828 1829 var a []int 1830 for i, x := range a /*i=undef*/ /*x=var:16*/ { _ = i; _ = x } 1831 1832 var i interface{} 1833 switch y := i.(type) { /*y=undef*/ 1834 case /*y=undef*/ int /*y=var:23*/ : 1835 case float32, /*y=undef*/ float64 /*y=var:23*/ : 1836 default /*y=var:23*/: 1837 println(y) 1838 } 1839 /*y=undef*/ 1840 1841 switch int := i.(type) { 1842 case /*int=typename:0*/ int /*int=var:31*/ : 1843 println(int) 1844 default /*int=var:31*/ : 1845 } 1846 } 1847 /*main=undef*/ 1848 ` 1849 1850 info.Uses = make(map[*ast.Ident]Object) 1851 f := mustParse(fset, mainSrc) 1852 makePkg("main", f) 1853 mainScope := imports["main"].Scope() 1854 rx := regexp.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`) 1855 for _, group := range f.Comments { 1856 for _, comment := range group.List { 1857 // Parse the assertion in the comment. 1858 m := rx.FindStringSubmatch(comment.Text) 1859 if m == nil { 1860 t.Errorf("%s: bad comment: %s", 1861 fset.Position(comment.Pos()), comment.Text) 1862 continue 1863 } 1864 name, want := m[1], m[2] 1865 1866 // Look up the name in the innermost enclosing scope. 1867 inner := mainScope.Innermost(comment.Pos()) 1868 if inner == nil { 1869 t.Errorf("%s: at %s: can't find innermost scope", 1870 fset.Position(comment.Pos()), comment.Text) 1871 continue 1872 } 1873 got := "undef" 1874 if _, obj := inner.LookupParent(name, comment.Pos()); obj != nil { 1875 kind := strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types.")) 1876 got = fmt.Sprintf("%s:%d", kind, fset.Position(obj.Pos()).Line) 1877 } 1878 if got != want { 1879 t.Errorf("%s: at %s: %s resolved to %s, want %s", 1880 fset.Position(comment.Pos()), comment.Text, name, got, want) 1881 } 1882 } 1883 } 1884 1885 // Check that for each referring identifier, 1886 // a lookup of its name on the innermost 1887 // enclosing scope returns the correct object. 1888 1889 for id, wantObj := range info.Uses { 1890 inner := mainScope.Innermost(id.Pos()) 1891 if inner == nil { 1892 t.Errorf("%s: can't find innermost scope enclosing %q", 1893 fset.Position(id.Pos()), id.Name) 1894 continue 1895 } 1896 1897 // Exclude selectors and qualified identifiers---lexical 1898 // refs only. (Ideally, we'd see if the AST parent is a 1899 // SelectorExpr, but that requires PathEnclosingInterval 1900 // from golang.org/x/tools/go/ast/astutil.) 1901 if id.Name == "X" { 1902 continue 1903 } 1904 1905 _, gotObj := inner.LookupParent(id.Name, id.Pos()) 1906 if gotObj != wantObj { 1907 t.Errorf("%s: got %v, want %v", 1908 fset.Position(id.Pos()), gotObj, wantObj) 1909 continue 1910 } 1911 } 1912 } 1913 1914 // newDefined creates a new defined type named T with the given underlying type. 1915 // Helper function for use with TestIncompleteInterfaces only. 1916 func newDefined(underlying Type) *Named { 1917 tname := NewTypeName(nopos, nil, "T", nil) 1918 return NewNamed(tname, underlying, nil) 1919 } 1920 1921 func TestConvertibleTo(t *testing.T) { 1922 for _, test := range []struct { 1923 v, t Type 1924 want bool 1925 }{ 1926 {Typ[Int], Typ[Int], true}, 1927 {Typ[Int], Typ[Float32], true}, 1928 {Typ[Int], Typ[String], true}, 1929 {newDefined(Typ[Int]), Typ[Int], true}, 1930 {newDefined(new(Struct)), new(Struct), true}, 1931 {newDefined(Typ[Int]), new(Struct), false}, 1932 {Typ[UntypedInt], Typ[Int], true}, 1933 {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), true}, 1934 {NewSlice(Typ[Int]), NewArray(Typ[Uint], 10), false}, 1935 {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true}, 1936 {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false}, 1937 // Untyped string values are not permitted by the spec, so the behavior below is undefined. 1938 {Typ[UntypedString], Typ[String], true}, 1939 } { 1940 if got := ConvertibleTo(test.v, test.t); got != test.want { 1941 t.Errorf("ConvertibleTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want) 1942 } 1943 } 1944 } 1945 1946 func TestAssignableTo(t *testing.T) { 1947 for _, test := range []struct { 1948 v, t Type 1949 want bool 1950 }{ 1951 {Typ[Int], Typ[Int], true}, 1952 {Typ[Int], Typ[Float32], false}, 1953 {newDefined(Typ[Int]), Typ[Int], false}, 1954 {newDefined(new(Struct)), new(Struct), true}, 1955 {Typ[UntypedBool], Typ[Bool], true}, 1956 {Typ[UntypedString], Typ[Bool], false}, 1957 // Neither untyped string nor untyped numeric assignments arise during 1958 // normal type checking, so the below behavior is technically undefined by 1959 // the spec. 1960 {Typ[UntypedString], Typ[String], true}, 1961 {Typ[UntypedInt], Typ[Int], true}, 1962 } { 1963 if got := AssignableTo(test.v, test.t); got != test.want { 1964 t.Errorf("AssignableTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want) 1965 } 1966 } 1967 } 1968 1969 func TestIdentical(t *testing.T) { 1970 // For each test, we compare the types of objects X and Y in the source. 1971 tests := []struct { 1972 src string 1973 want bool 1974 }{ 1975 // Basic types. 1976 {"var X int; var Y int", true}, 1977 {"var X int; var Y string", false}, 1978 1979 // TODO: add more tests for complex types. 1980 1981 // Named types. 1982 {"type X int; type Y int", false}, 1983 1984 // Aliases. 1985 {"type X = int; type Y = int", true}, 1986 1987 // Functions. 1988 {`func X(int) string { return "" }; func Y(int) string { return "" }`, true}, 1989 {`func X() string { return "" }; func Y(int) string { return "" }`, false}, 1990 {`func X(int) string { return "" }; func Y(int) {}`, false}, 1991 1992 // Generic functions. Type parameters should be considered identical modulo 1993 // renaming. See also go.dev/issue/49722. 1994 {`func X[P ~int](){}; func Y[Q ~int]() {}`, true}, 1995 {`func X[P1 any, P2 ~*P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, true}, 1996 {`func X[P1 any, P2 ~[]P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, false}, 1997 {`func X[P ~int](P){}; func Y[Q ~int](Q) {}`, true}, 1998 {`func X[P ~string](P){}; func Y[Q ~int](Q) {}`, false}, 1999 {`func X[P ~int]([]P){}; func Y[Q ~int]([]Q) {}`, true}, 2000 } 2001 2002 for _, test := range tests { 2003 pkg := mustTypecheck("package p;"+test.src, nil, nil) 2004 X := pkg.Scope().Lookup("X") 2005 Y := pkg.Scope().Lookup("Y") 2006 if X == nil || Y == nil { 2007 t.Fatal("test must declare both X and Y") 2008 } 2009 if got := Identical(X.Type(), Y.Type()); got != test.want { 2010 t.Errorf("Identical(%s, %s) = %t, want %t", X.Type(), Y.Type(), got, test.want) 2011 } 2012 } 2013 } 2014 2015 func TestIdentical_issue15173(t *testing.T) { 2016 // Identical should allow nil arguments and be symmetric. 2017 for _, test := range []struct { 2018 x, y Type 2019 want bool 2020 }{ 2021 {Typ[Int], Typ[Int], true}, 2022 {Typ[Int], nil, false}, 2023 {nil, Typ[Int], false}, 2024 {nil, nil, true}, 2025 } { 2026 if got := Identical(test.x, test.y); got != test.want { 2027 t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got) 2028 } 2029 } 2030 } 2031 2032 func TestIdenticalUnions(t *testing.T) { 2033 tname := NewTypeName(nopos, nil, "myInt", nil) 2034 myInt := NewNamed(tname, Typ[Int], nil) 2035 tmap := map[string]*Term{ 2036 "int": NewTerm(false, Typ[Int]), 2037 "~int": NewTerm(true, Typ[Int]), 2038 "string": NewTerm(false, Typ[String]), 2039 "~string": NewTerm(true, Typ[String]), 2040 "myInt": NewTerm(false, myInt), 2041 } 2042 makeUnion := func(s string) *Union { 2043 parts := strings.Split(s, "|") 2044 var terms []*Term 2045 for _, p := range parts { 2046 term := tmap[p] 2047 if term == nil { 2048 t.Fatalf("missing term %q", p) 2049 } 2050 terms = append(terms, term) 2051 } 2052 return NewUnion(terms) 2053 } 2054 for _, test := range []struct { 2055 x, y string 2056 want bool 2057 }{ 2058 // These tests are just sanity checks. The tests for type sets and 2059 // interfaces provide much more test coverage. 2060 {"int|~int", "~int", true}, 2061 {"myInt|~int", "~int", true}, 2062 {"int|string", "string|int", true}, 2063 {"int|int|string", "string|int", true}, 2064 {"myInt|string", "int|string", false}, 2065 } { 2066 x := makeUnion(test.x) 2067 y := makeUnion(test.y) 2068 if got := Identical(x, y); got != test.want { 2069 t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got) 2070 } 2071 } 2072 } 2073 2074 func TestIssue15305(t *testing.T) { 2075 const src = "package p; func f() int16; var _ = f(undef)" 2076 fset := token.NewFileSet() 2077 f := mustParse(fset, src) 2078 conf := Config{ 2079 Error: func(err error) {}, // allow errors 2080 } 2081 info := &Info{ 2082 Types: make(map[ast.Expr]TypeAndValue), 2083 } 2084 conf.Check("p", fset, []*ast.File{f}, info) // ignore result 2085 for e, tv := range info.Types { 2086 if _, ok := e.(*ast.CallExpr); ok { 2087 if tv.Type != Typ[Int16] { 2088 t.Errorf("CallExpr has type %v, want int16", tv.Type) 2089 } 2090 return 2091 } 2092 } 2093 t.Errorf("CallExpr has no type") 2094 } 2095 2096 // TestCompositeLitTypes verifies that Info.Types registers the correct 2097 // types for composite literal expressions and composite literal type 2098 // expressions. 2099 func TestCompositeLitTypes(t *testing.T) { 2100 for i, test := range []struct { 2101 lit, typ string 2102 }{ 2103 {`[16]byte{}`, `[16]byte`}, 2104 {`[...]byte{}`, `[0]byte`}, // test for go.dev/issue/14092 2105 {`[...]int{1, 2, 3}`, `[3]int`}, // test for go.dev/issue/14092 2106 {`[...]int{90: 0, 98: 1, 2}`, `[100]int`}, // test for go.dev/issue/14092 2107 {`[]int{}`, `[]int`}, 2108 {`map[string]bool{"foo": true}`, `map[string]bool`}, 2109 {`struct{}{}`, `struct{}`}, 2110 {`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`}, 2111 } { 2112 fset := token.NewFileSet() 2113 f := mustParse(fset, fmt.Sprintf("package p%d; var _ = %s", i, test.lit)) 2114 types := make(map[ast.Expr]TypeAndValue) 2115 if _, err := new(Config).Check("p", fset, []*ast.File{f}, &Info{Types: types}); err != nil { 2116 t.Fatalf("%s: %v", test.lit, err) 2117 } 2118 2119 cmptype := func(x ast.Expr, want string) { 2120 tv, ok := types[x] 2121 if !ok { 2122 t.Errorf("%s: no Types entry found", test.lit) 2123 return 2124 } 2125 if tv.Type == nil { 2126 t.Errorf("%s: type is nil", test.lit) 2127 return 2128 } 2129 if got := tv.Type.String(); got != want { 2130 t.Errorf("%s: got %v, want %s", test.lit, got, want) 2131 } 2132 } 2133 2134 // test type of composite literal expression 2135 rhs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0] 2136 cmptype(rhs, test.typ) 2137 2138 // test type of composite literal type expression 2139 cmptype(rhs.(*ast.CompositeLit).Type, test.typ) 2140 } 2141 } 2142 2143 // TestObjectParents verifies that objects have parent scopes or not 2144 // as specified by the Object interface. 2145 func TestObjectParents(t *testing.T) { 2146 const src = ` 2147 package p 2148 2149 const C = 0 2150 2151 type T1 struct { 2152 a, b int 2153 T2 2154 } 2155 2156 type T2 interface { 2157 im1() 2158 im2() 2159 } 2160 2161 func (T1) m1() {} 2162 func (*T1) m2() {} 2163 2164 func f(x int) { y := x; print(y) } 2165 ` 2166 2167 fset := token.NewFileSet() 2168 f := mustParse(fset, src) 2169 2170 info := &Info{ 2171 Defs: make(map[*ast.Ident]Object), 2172 } 2173 if _, err := new(Config).Check("p", fset, []*ast.File{f}, info); err != nil { 2174 t.Fatal(err) 2175 } 2176 2177 for ident, obj := range info.Defs { 2178 if obj == nil { 2179 // only package names and implicit vars have a nil object 2180 // (in this test we only need to handle the package name) 2181 if ident.Name != "p" { 2182 t.Errorf("%v has nil object", ident) 2183 } 2184 continue 2185 } 2186 2187 // struct fields, type-associated and interface methods 2188 // have no parent scope 2189 wantParent := true 2190 switch obj := obj.(type) { 2191 case *Var: 2192 if obj.IsField() { 2193 wantParent = false 2194 } 2195 case *Func: 2196 if obj.Type().(*Signature).Recv() != nil { // method 2197 wantParent = false 2198 } 2199 } 2200 2201 gotParent := obj.Parent() != nil 2202 switch { 2203 case gotParent && !wantParent: 2204 t.Errorf("%v: want no parent, got %s", ident, obj.Parent()) 2205 case !gotParent && wantParent: 2206 t.Errorf("%v: no parent found", ident) 2207 } 2208 } 2209 } 2210 2211 // TestFailedImport tests that we don't get follow-on errors 2212 // elsewhere in a package due to failing to import a package. 2213 func TestFailedImport(t *testing.T) { 2214 testenv.MustHaveGoBuild(t) 2215 2216 const src = ` 2217 package p 2218 2219 import foo "go/types/thisdirectorymustnotexistotherwisethistestmayfail/foo" // should only see an error here 2220 2221 const c = foo.C 2222 type T = foo.T 2223 var v T = c 2224 func f(x T) T { return foo.F(x) } 2225 ` 2226 fset := token.NewFileSet() 2227 f := mustParse(fset, src) 2228 files := []*ast.File{f} 2229 2230 // type-check using all possible importers 2231 for _, compiler := range []string{"gc", "gccgo", "source"} { 2232 errcount := 0 2233 conf := Config{ 2234 Error: func(err error) { 2235 // we should only see the import error 2236 if errcount > 0 || !strings.Contains(err.Error(), "could not import") { 2237 t.Errorf("for %s importer, got unexpected error: %v", compiler, err) 2238 } 2239 errcount++ 2240 }, 2241 Importer: importer.For(compiler, nil), 2242 } 2243 2244 info := &Info{ 2245 Uses: make(map[*ast.Ident]Object), 2246 } 2247 pkg, _ := conf.Check("p", fset, files, info) 2248 if pkg == nil { 2249 t.Errorf("for %s importer, type-checking failed to return a package", compiler) 2250 continue 2251 } 2252 2253 imports := pkg.Imports() 2254 if len(imports) != 1 { 2255 t.Errorf("for %s importer, got %d imports, want 1", compiler, len(imports)) 2256 continue 2257 } 2258 imp := imports[0] 2259 if imp.Name() != "foo" { 2260 t.Errorf(`for %s importer, got %q, want "foo"`, compiler, imp.Name()) 2261 continue 2262 } 2263 2264 // verify that all uses of foo refer to the imported package foo (imp) 2265 for ident, obj := range info.Uses { 2266 if ident.Name == "foo" { 2267 if obj, ok := obj.(*PkgName); ok { 2268 if obj.Imported() != imp { 2269 t.Errorf("%s resolved to %v; want %v", ident, obj.Imported(), imp) 2270 } 2271 } else { 2272 t.Errorf("%s resolved to %v; want package name", ident, obj) 2273 } 2274 } 2275 } 2276 } 2277 } 2278 2279 func TestInstantiate(t *testing.T) { 2280 // eventually we like more tests but this is a start 2281 const src = "package p; type T[P any] *T[P]" 2282 pkg := mustTypecheck(src, nil, nil) 2283 2284 // type T should have one type parameter 2285 T := pkg.Scope().Lookup("T").Type().(*Named) 2286 if n := T.TypeParams().Len(); n != 1 { 2287 t.Fatalf("expected 1 type parameter; found %d", n) 2288 } 2289 2290 // instantiation should succeed (no endless recursion) 2291 // even with a nil *Checker 2292 res, err := Instantiate(nil, T, []Type{Typ[Int]}, false) 2293 if err != nil { 2294 t.Fatal(err) 2295 } 2296 2297 // instantiated type should point to itself 2298 if p := res.Underlying().(*Pointer).Elem(); p != res { 2299 t.Fatalf("unexpected result type: %s points to %s", res, p) 2300 } 2301 } 2302 2303 func TestInstantiateErrors(t *testing.T) { 2304 tests := []struct { 2305 src string // by convention, T must be the type being instantiated 2306 targs []Type 2307 wantAt int // -1 indicates no error 2308 }{ 2309 {"type T[P interface{~string}] int", []Type{Typ[Int]}, 0}, 2310 {"type T[P1 interface{int}, P2 interface{~string}] int", []Type{Typ[Int], Typ[Int]}, 1}, 2311 {"type T[P1 any, P2 interface{~[]P1}] int", []Type{Typ[Int], NewSlice(Typ[String])}, 1}, 2312 {"type T[P1 interface{~[]P2}, P2 any] int", []Type{NewSlice(Typ[String]), Typ[Int]}, 0}, 2313 } 2314 2315 for _, test := range tests { 2316 src := "package p; " + test.src 2317 pkg := mustTypecheck(src, nil, nil) 2318 2319 T := pkg.Scope().Lookup("T").Type().(*Named) 2320 2321 _, err := Instantiate(nil, T, test.targs, true) 2322 if err == nil { 2323 t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) 2324 } 2325 2326 var argErr *ArgumentError 2327 if !errors.As(err, &argErr) { 2328 t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) 2329 } 2330 2331 if argErr.Index != test.wantAt { 2332 t.Errorf("Instantiate(%v, %v): error at index %d, want index %d", T, test.targs, argErr.Index, test.wantAt) 2333 } 2334 } 2335 } 2336 2337 func TestArgumentErrorUnwrapping(t *testing.T) { 2338 var err error = &ArgumentError{ 2339 Index: 1, 2340 Err: Error{Msg: "test"}, 2341 } 2342 var e Error 2343 if !errors.As(err, &e) { 2344 t.Fatalf("error %v does not wrap types.Error", err) 2345 } 2346 if e.Msg != "test" { 2347 t.Errorf("e.Msg = %q, want %q", e.Msg, "test") 2348 } 2349 } 2350 2351 func TestInstanceIdentity(t *testing.T) { 2352 imports := make(testImporter) 2353 conf := Config{Importer: imports} 2354 makePkg := func(src string) { 2355 fset := token.NewFileSet() 2356 f := mustParse(fset, src) 2357 name := f.Name.Name 2358 pkg, err := conf.Check(name, fset, []*ast.File{f}, nil) 2359 if err != nil { 2360 t.Fatal(err) 2361 } 2362 imports[name] = pkg 2363 } 2364 makePkg(`package lib; type T[P any] struct{}`) 2365 makePkg(`package a; import "lib"; var A lib.T[int]`) 2366 makePkg(`package b; import "lib"; var B lib.T[int]`) 2367 a := imports["a"].Scope().Lookup("A") 2368 b := imports["b"].Scope().Lookup("B") 2369 if !Identical(a.Type(), b.Type()) { 2370 t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type()) 2371 } 2372 } 2373 2374 // TestInstantiatedObjects verifies properties of instantiated objects. 2375 func TestInstantiatedObjects(t *testing.T) { 2376 const src = ` 2377 package p 2378 2379 type T[P any] struct { 2380 field P 2381 } 2382 2383 func (recv *T[Q]) concreteMethod(mParam Q) (mResult Q) { return } 2384 2385 type FT[P any] func(ftParam P) (ftResult P) 2386 2387 func F[P any](fParam P) (fResult P){ return } 2388 2389 type I[P any] interface { 2390 interfaceMethod(P) 2391 } 2392 2393 type R[P any] T[P] 2394 2395 func (R[P]) m() {} // having a method triggers expansion of R 2396 2397 var ( 2398 t T[int] 2399 ft FT[int] 2400 f = F[int] 2401 i I[int] 2402 ) 2403 2404 func fn() { 2405 var r R[int] 2406 _ = r 2407 } 2408 ` 2409 info := &Info{ 2410 Defs: make(map[*ast.Ident]Object), 2411 } 2412 fset := token.NewFileSet() 2413 f := mustParse(fset, src) 2414 conf := Config{} 2415 pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info) 2416 if err != nil { 2417 t.Fatal(err) 2418 } 2419 2420 lookup := func(name string) Type { return pkg.Scope().Lookup(name).Type() } 2421 fnScope := pkg.Scope().Lookup("fn").(*Func).Scope() 2422 2423 tests := []struct { 2424 name string 2425 obj Object 2426 }{ 2427 // Struct fields 2428 {"field", lookup("t").Underlying().(*Struct).Field(0)}, 2429 {"field", fnScope.Lookup("r").Type().Underlying().(*Struct).Field(0)}, 2430 2431 // Methods and method fields 2432 {"concreteMethod", lookup("t").(*Named).Method(0)}, 2433 {"recv", lookup("t").(*Named).Method(0).Type().(*Signature).Recv()}, 2434 {"mParam", lookup("t").(*Named).Method(0).Type().(*Signature).Params().At(0)}, 2435 {"mResult", lookup("t").(*Named).Method(0).Type().(*Signature).Results().At(0)}, 2436 2437 // Interface methods 2438 {"interfaceMethod", lookup("i").Underlying().(*Interface).Method(0)}, 2439 2440 // Function type fields 2441 {"ftParam", lookup("ft").Underlying().(*Signature).Params().At(0)}, 2442 {"ftResult", lookup("ft").Underlying().(*Signature).Results().At(0)}, 2443 2444 // Function fields 2445 {"fParam", lookup("f").(*Signature).Params().At(0)}, 2446 {"fResult", lookup("f").(*Signature).Results().At(0)}, 2447 } 2448 2449 // Collect all identifiers by name. 2450 idents := make(map[string][]*ast.Ident) 2451 ast.Inspect(f, func(n ast.Node) bool { 2452 if id, ok := n.(*ast.Ident); ok { 2453 idents[id.Name] = append(idents[id.Name], id) 2454 } 2455 return true 2456 }) 2457 2458 for _, test := range tests { 2459 test := test 2460 t.Run(test.name, func(t *testing.T) { 2461 if got := len(idents[test.name]); got != 1 { 2462 t.Fatalf("found %d identifiers named %s, want 1", got, test.name) 2463 } 2464 ident := idents[test.name][0] 2465 def := info.Defs[ident] 2466 if def == test.obj { 2467 t.Fatalf("info.Defs[%s] contains the test object", test.name) 2468 } 2469 if orig := originObject(test.obj); def != orig { 2470 t.Errorf("info.Defs[%s] does not match obj.Origin()", test.name) 2471 } 2472 if def.Pkg() != test.obj.Pkg() { 2473 t.Errorf("Pkg() = %v, want %v", def.Pkg(), test.obj.Pkg()) 2474 } 2475 if def.Name() != test.obj.Name() { 2476 t.Errorf("Name() = %v, want %v", def.Name(), test.obj.Name()) 2477 } 2478 if def.Pos() != test.obj.Pos() { 2479 t.Errorf("Pos() = %v, want %v", def.Pos(), test.obj.Pos()) 2480 } 2481 if def.Parent() != test.obj.Parent() { 2482 t.Fatalf("Parent() = %v, want %v", def.Parent(), test.obj.Parent()) 2483 } 2484 if def.Exported() != test.obj.Exported() { 2485 t.Fatalf("Exported() = %v, want %v", def.Exported(), test.obj.Exported()) 2486 } 2487 if def.Id() != test.obj.Id() { 2488 t.Fatalf("Id() = %v, want %v", def.Id(), test.obj.Id()) 2489 } 2490 // String and Type are expected to differ. 2491 }) 2492 } 2493 } 2494 2495 func originObject(obj Object) Object { 2496 switch obj := obj.(type) { 2497 case *Var: 2498 return obj.Origin() 2499 case *Func: 2500 return obj.Origin() 2501 } 2502 return obj 2503 } 2504 2505 func TestImplements(t *testing.T) { 2506 const src = ` 2507 package p 2508 2509 type EmptyIface interface{} 2510 2511 type I interface { 2512 m() 2513 } 2514 2515 type C interface { 2516 m() 2517 ~int 2518 } 2519 2520 type Integer interface{ 2521 int8 | int16 | int32 | int64 2522 } 2523 2524 type EmptyTypeSet interface{ 2525 Integer 2526 ~string 2527 } 2528 2529 type N1 int 2530 func (N1) m() {} 2531 2532 type N2 int 2533 func (*N2) m() {} 2534 2535 type N3 int 2536 func (N3) m(int) {} 2537 2538 type N4 string 2539 func (N4) m() 2540 2541 type Bad Bad // invalid type 2542 ` 2543 2544 fset := token.NewFileSet() 2545 f := mustParse(fset, src) 2546 conf := Config{Error: func(error) {}} 2547 pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) 2548 2549 lookup := func(tname string) Type { return pkg.Scope().Lookup(tname).Type() } 2550 var ( 2551 EmptyIface = lookup("EmptyIface").Underlying().(*Interface) 2552 I = lookup("I").(*Named) 2553 II = I.Underlying().(*Interface) 2554 C = lookup("C").(*Named) 2555 CI = C.Underlying().(*Interface) 2556 Integer = lookup("Integer").Underlying().(*Interface) 2557 EmptyTypeSet = lookup("EmptyTypeSet").Underlying().(*Interface) 2558 N1 = lookup("N1") 2559 N1p = NewPointer(N1) 2560 N2 = lookup("N2") 2561 N2p = NewPointer(N2) 2562 N3 = lookup("N3") 2563 N4 = lookup("N4") 2564 Bad = lookup("Bad") 2565 ) 2566 2567 tests := []struct { 2568 V Type 2569 T *Interface 2570 want bool 2571 }{ 2572 {I, II, true}, 2573 {I, CI, false}, 2574 {C, II, true}, 2575 {C, CI, true}, 2576 {Typ[Int8], Integer, true}, 2577 {Typ[Int64], Integer, true}, 2578 {Typ[String], Integer, false}, 2579 {EmptyTypeSet, II, true}, 2580 {EmptyTypeSet, EmptyTypeSet, true}, 2581 {Typ[Int], EmptyTypeSet, false}, 2582 {N1, II, true}, 2583 {N1, CI, true}, 2584 {N1p, II, true}, 2585 {N1p, CI, false}, 2586 {N2, II, false}, 2587 {N2, CI, false}, 2588 {N2p, II, true}, 2589 {N2p, CI, false}, 2590 {N3, II, false}, 2591 {N3, CI, false}, 2592 {N4, II, true}, 2593 {N4, CI, false}, 2594 {Bad, II, false}, 2595 {Bad, CI, false}, 2596 {Bad, EmptyIface, true}, 2597 } 2598 2599 for _, test := range tests { 2600 if got := Implements(test.V, test.T); got != test.want { 2601 t.Errorf("Implements(%s, %s) = %t, want %t", test.V, test.T, got, test.want) 2602 } 2603 2604 // The type assertion x.(T) is valid if T is an interface or if T implements the type of x. 2605 // The assertion is never valid if T is a bad type. 2606 V := test.T 2607 T := test.V 2608 want := false 2609 if _, ok := T.Underlying().(*Interface); (ok || Implements(T, V)) && T != Bad { 2610 want = true 2611 } 2612 if got := AssertableTo(V, T); got != want { 2613 t.Errorf("AssertableTo(%s, %s) = %t, want %t", V, T, got, want) 2614 } 2615 } 2616 } 2617 2618 func TestMissingMethodAlternative(t *testing.T) { 2619 const src = ` 2620 package p 2621 type T interface { 2622 m() 2623 } 2624 2625 type V0 struct{} 2626 func (V0) m() {} 2627 2628 type V1 struct{} 2629 2630 type V2 struct{} 2631 func (V2) m() int 2632 2633 type V3 struct{} 2634 func (*V3) m() 2635 2636 type V4 struct{} 2637 func (V4) M() 2638 ` 2639 2640 pkg := mustTypecheck(src, nil, nil) 2641 2642 T := pkg.Scope().Lookup("T").Type().Underlying().(*Interface) 2643 lookup := func(name string) (*Func, bool) { 2644 return MissingMethod(pkg.Scope().Lookup(name).Type(), T, true) 2645 } 2646 2647 // V0 has method m with correct signature. Should not report wrongType. 2648 method, wrongType := lookup("V0") 2649 if method != nil || wrongType { 2650 t.Fatalf("V0: got method = %v, wrongType = %v", method, wrongType) 2651 } 2652 2653 checkMissingMethod := func(tname string, reportWrongType bool) { 2654 method, wrongType := lookup(tname) 2655 if method == nil || method.Name() != "m" || wrongType != reportWrongType { 2656 t.Fatalf("%s: got method = %v, wrongType = %v", tname, method, wrongType) 2657 } 2658 } 2659 2660 // V1 has no method m. Should not report wrongType. 2661 checkMissingMethod("V1", false) 2662 2663 // V2 has method m with wrong signature type (ignoring receiver). Should report wrongType. 2664 checkMissingMethod("V2", true) 2665 2666 // V3 has no method m but it exists on *V3. Should report wrongType. 2667 checkMissingMethod("V3", true) 2668 2669 // V4 has no method m but has M. Should not report wrongType. 2670 checkMissingMethod("V4", false) 2671 }