1
2
3
4
5
6
7 package types2_test
8
9 import (
10 "bytes"
11 "cmd/compile/internal/syntax"
12 "fmt"
13 "internal/testenv"
14 "sort"
15 "strings"
16 "testing"
17
18 . "cmd/compile/internal/types2"
19 )
20
21 func mustParse(t *testing.T, src string) *syntax.File {
22 f, err := parseSrc("", src)
23 if err != nil {
24 t.Fatal(err)
25 }
26 return f
27 }
28 func TestIssue5770(t *testing.T) {
29 f := mustParse(t, `package p; type S struct{T}`)
30 var conf Config
31 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
32 want := "undeclared name: T"
33 if err == nil || !strings.Contains(err.Error(), want) {
34 t.Errorf("got: %v; want: %s", err, want)
35 }
36 }
37
38 func TestIssue5849(t *testing.T) {
39 src := `
40 package p
41 var (
42 s uint
43 _ = uint8(8)
44 _ = uint16(16) << s
45 _ = uint32(32 << s)
46 _ = uint64(64 << s + s)
47 _ = (interface{})("foo")
48 _ = (interface{})(nil)
49 )`
50 f := mustParse(t, src)
51
52 var conf Config
53 types := make(map[syntax.Expr]TypeAndValue)
54 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, &Info{Types: types})
55 if err != nil {
56 t.Fatal(err)
57 }
58
59 for x, tv := range types {
60 var want Type
61 switch x := x.(type) {
62 case *syntax.BasicLit:
63 switch x.Value {
64 case `8`:
65 want = Typ[Uint8]
66 case `16`:
67 want = Typ[Uint16]
68 case `32`:
69 want = Typ[Uint32]
70 case `64`:
71 want = Typ[Uint]
72 case `"foo"`:
73 want = Typ[String]
74 }
75 case *syntax.Name:
76 if x.Value == "nil" {
77 want = NewInterfaceType(nil, nil)
78 }
79 }
80 if want != nil && !Identical(tv.Type, want) {
81 t.Errorf("got %s; want %s", tv.Type, want)
82 }
83 }
84 }
85
86 func TestIssue6413(t *testing.T) {
87 src := `
88 package p
89 func f() int {
90 defer f()
91 go f()
92 return 0
93 }
94 `
95 f := mustParse(t, src)
96
97 var conf Config
98 types := make(map[syntax.Expr]TypeAndValue)
99 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, &Info{Types: types})
100 if err != nil {
101 t.Fatal(err)
102 }
103
104 want := Typ[Int]
105 n := 0
106 for x, tv := range types {
107 if _, ok := x.(*syntax.CallExpr); ok {
108 if tv.Type != want {
109 t.Errorf("%s: got %s; want %s", x.Pos(), tv.Type, want)
110 }
111 n++
112 }
113 }
114
115 if n != 2 {
116 t.Errorf("got %d CallExprs; want 2", n)
117 }
118 }
119
120 func TestIssue7245(t *testing.T) {
121 src := `
122 package p
123 func (T) m() (res bool) { return }
124 type T struct{} // receiver type after method declaration
125 `
126 f := mustParse(t, src)
127
128 var conf Config
129 defs := make(map[*syntax.Name]Object)
130 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, &Info{Defs: defs})
131 if err != nil {
132 t.Fatal(err)
133 }
134
135 m := f.DeclList[0].(*syntax.FuncDecl)
136 res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
137 res2 := defs[m.Type.ResultList[0].Name].(*Var)
138
139 if res1 != res2 {
140 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
141 }
142 }
143
144
145
146
147 func TestIssue7827(t *testing.T) {
148 const src = `
149 package p
150 func _() {
151 const w = 1 // defs w
152 x, y := 2, 3 // defs x, y
153 w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
154 _, _, _ = x, y, z // uses x, y, z
155 }
156 `
157 f := mustParse(t, src)
158
159 const want = `L3 defs func p._()
160 L4 defs const w untyped int
161 L5 defs var x int
162 L5 defs var y int
163 L6 defs var z int
164 L6 uses const w untyped int
165 L6 uses var x int
166 L7 uses var x int
167 L7 uses var y int
168 L7 uses var z int`
169
170
171 conf := Config{Error: func(err error) { t.Log(err) }}
172 defs := make(map[*syntax.Name]Object)
173 uses := make(map[*syntax.Name]Object)
174 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, &Info{Defs: defs, Uses: uses})
175 if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
176 t.Errorf("Check: unexpected error: %s", s)
177 }
178
179 var facts []string
180 for id, obj := range defs {
181 if obj != nil {
182 fact := fmt.Sprintf("L%d defs %s", id.Pos().Line(), obj)
183 facts = append(facts, fact)
184 }
185 }
186 for id, obj := range uses {
187 fact := fmt.Sprintf("L%d uses %s", id.Pos().Line(), obj)
188 facts = append(facts, fact)
189 }
190 sort.Strings(facts)
191
192 got := strings.Join(facts, "\n")
193 if got != want {
194 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
195 }
196 }
197
198
199
200
201
202
203
204 func TestIssue13898(t *testing.T) {
205 testenv.MustHaveGoBuild(t)
206
207 const src0 = `
208 package main
209
210 import "go/types"
211
212 func main() {
213 var info types.Info
214 for _, obj := range info.Uses {
215 _ = obj.Pkg()
216 }
217 }
218 `
219
220 const src1 = `
221 package main
222
223 import (
224 "go/types"
225 _ "go/importer"
226 )
227
228 func main() {
229 var info types.Info
230 for _, obj := range info.Uses {
231 _ = obj.Pkg()
232 }
233 }
234 `
235
236
237 const src2 = `
238 package main
239
240 import (
241 _ "go/importer"
242 "go/types"
243 )
244
245 func main() {
246 var info types.Info
247 for _, obj := range info.Uses {
248 _ = obj.Pkg()
249 }
250 }
251 `
252 f := func(test, src string) {
253 f := mustParse(t, src)
254 conf := Config{Importer: defaultImporter()}
255 info := Info{Uses: make(map[*syntax.Name]Object)}
256 _, err := conf.Check("main", []*syntax.File{f}, &info)
257 if err != nil {
258 t.Fatal(err)
259 }
260
261 var pkg *Package
262 count := 0
263 for id, obj := range info.Uses {
264 if id.Value == "Pkg" {
265 pkg = obj.Pkg()
266 count++
267 }
268 }
269 if count != 1 {
270 t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
271 }
272 if pkg.Name() != "types" {
273 t.Fatalf("%s: got %v; want package types2", test, pkg)
274 }
275 }
276
277 f("src0", src0)
278 f("src1", src1)
279 f("src2", src2)
280 }
281
282 func TestIssue22525(t *testing.T) {
283 f := mustParse(t, `package p; func f() { var a, b, c, d, e int }`)
284
285 got := "\n"
286 conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
287 conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
288 want := `
289 :1:27: a declared but not used
290 :1:30: b declared but not used
291 :1:33: c declared but not used
292 :1:36: d declared but not used
293 :1:39: e declared but not used
294 `
295 if got != want {
296 t.Errorf("got: %swant: %s", got, want)
297 }
298 }
299
300 func TestIssue25627(t *testing.T) {
301 const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
302
303
304 for _, src := range []string{
305 `struct { x Missing }`,
306 `struct { Missing }`,
307 `struct { *Missing }`,
308 `struct { unsafe.Pointer }`,
309 `struct { P }`,
310 `struct { *I }`,
311 `struct { a int; b Missing; *Missing }`,
312 } {
313 f := mustParse(t, prefix+src)
314
315 conf := Config{Importer: defaultImporter(), Error: func(err error) {}}
316 info := &Info{Types: make(map[syntax.Expr]TypeAndValue)}
317 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
318 if err != nil {
319 if _, ok := err.(Error); !ok {
320 t.Fatal(err)
321 }
322 }
323
324 syntax.Crawl(f, func(n syntax.Node) bool {
325 if decl, _ := n.(*syntax.TypeDecl); decl != nil {
326 if tv, ok := info.Types[decl.Type]; ok && decl.Name.Value == "T" {
327 want := strings.Count(src, ";") + 1
328 if got := tv.Type.(*Struct).NumFields(); got != want {
329 t.Errorf("%s: got %d fields; want %d", src, got, want)
330 }
331 }
332 }
333 return false
334 })
335 }
336 }
337
338 func TestIssue28005(t *testing.T) {
339
340
341 sources := [...]string{
342 "package p; type A interface{ A() }",
343 "package p; type B interface{ B() }",
344 "package p; type X interface{ A; B }",
345 }
346
347
348 var orig [len(sources)]*syntax.File
349 for i, src := range sources {
350 orig[i] = mustParse(t, src)
351 }
352
353
354 for _, perm := range [][len(sources)]int{
355 {0, 1, 2},
356 {0, 2, 1},
357 {1, 0, 2},
358 {1, 2, 0},
359 {2, 0, 1},
360 {2, 1, 0},
361 } {
362
363 files := make([]*syntax.File, len(sources))
364 for i := range perm {
365 files[i] = orig[perm[i]]
366 }
367
368
369 var conf Config
370 info := &Info{Defs: make(map[*syntax.Name]Object)}
371 _, err := conf.Check("", files, info)
372 if err != nil {
373 t.Fatal(err)
374 }
375
376
377 var obj Object
378 for name, def := range info.Defs {
379 if name.Value == "X" {
380 obj = def
381 break
382 }
383 }
384 if obj == nil {
385 t.Fatal("object X not found")
386 }
387 iface := obj.Type().Underlying().(*Interface)
388
389
390
391 for i := 0; i < iface.NumMethods(); i++ {
392 m := iface.Method(i)
393 recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
394 if recvName != m.Name() {
395 t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
396 }
397 }
398 }
399 }
400
401 func TestIssue28282(t *testing.T) {
402
403 et := Universe.Lookup("error").Type()
404 it := NewInterfaceType(nil, []Type{et})
405
406
407
408 want := et.Underlying().(*Interface).Method(0)
409 got := it.Method(0)
410 if got != want {
411 t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
412 }
413
414 obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
415 if obj != want {
416 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
417 }
418 obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
419 if obj != want {
420 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
421 }
422 }
423
424 func TestIssue29029(t *testing.T) {
425 f1 := mustParse(t, `package p; type A interface { M() }`)
426 f2 := mustParse(t, `package p; var B interface { A }`)
427
428
429 printInfo := func(info *Info) string {
430 var buf bytes.Buffer
431 for _, obj := range info.Defs {
432 if fn, ok := obj.(*Func); ok {
433 fmt.Fprintln(&buf, fn)
434 }
435 }
436 return buf.String()
437 }
438
439
440
441
442
443
444 var conf Config
445 info := &Info{Defs: make(map[*syntax.Name]Object)}
446 check := NewChecker(&conf, NewPackage("", "p"), info)
447 if err := check.Files([]*syntax.File{f1, f2}); err != nil {
448 t.Fatal(err)
449 }
450 want := printInfo(info)
451
452
453 info = &Info{Defs: make(map[*syntax.Name]Object)}
454 check = NewChecker(&conf, NewPackage("", "p"), info)
455 if err := check.Files([]*syntax.File{f1}); err != nil {
456 t.Fatal(err)
457 }
458 if err := check.Files([]*syntax.File{f2}); err != nil {
459 t.Fatal(err)
460 }
461 got := printInfo(info)
462
463 if got != want {
464 t.Errorf("\ngot : %swant: %s", got, want)
465 }
466 }
467
468 func TestIssue34151(t *testing.T) {
469 const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
470 const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
471
472 a, err := pkgFor("a", asrc, nil)
473 if err != nil {
474 t.Fatalf("package %s failed to typecheck: %v", a.Name(), err)
475 }
476
477 bast := mustParse(t, bsrc)
478 conf := Config{Importer: importHelper{pkg: a}}
479 b, err := conf.Check(bast.PkgName.Value, []*syntax.File{bast}, nil)
480 if err != nil {
481 t.Errorf("package %s failed to typecheck: %v", b.Name(), err)
482 }
483 }
484
485 type importHelper struct {
486 pkg *Package
487 fallback Importer
488 }
489
490 func (h importHelper) Import(path string) (*Package, error) {
491 if path == h.pkg.Path() {
492 return h.pkg, nil
493 }
494 if h.fallback == nil {
495 return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
496 }
497 return h.fallback.Import(path)
498 }
499
500
501
502
503
504
505
506 func TestIssue34921(t *testing.T) {
507 defer func() {
508 if r := recover(); r != nil {
509 t.Error(r)
510 }
511 }()
512
513 var sources = []string{
514 `package a; type T int`,
515 `package b; import "a"; type T a.T`,
516 }
517
518 var pkg *Package
519 for _, src := range sources {
520 f := mustParse(t, src)
521 conf := Config{Importer: importHelper{pkg: pkg}}
522 res, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil)
523 if err != nil {
524 t.Errorf("%q failed to typecheck: %v", src, err)
525 }
526 pkg = res
527 }
528 }
529
530 func TestIssue43088(t *testing.T) {
531
532
533
534
535
536
537
538
539
540 n1 := NewTypeName(syntax.Pos{}, nil, "T1", nil)
541 T1 := NewNamed(n1, nil, nil)
542 n2 := NewTypeName(syntax.Pos{}, nil, "T2", nil)
543 T2 := NewNamed(n2, nil, nil)
544 s1 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
545 T1.SetUnderlying(s1)
546 s2 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
547 s3 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", s2, false)}, nil)
548 T2.SetUnderlying(s3)
549
550
551 Comparable(T1)
552 Comparable(T2)
553 }
554
555 func TestIssue44515(t *testing.T) {
556 typ := Unsafe.Scope().Lookup("Pointer").Type()
557
558 got := TypeString(typ, nil)
559 want := "unsafe.Pointer"
560 if got != want {
561 t.Errorf("got %q; want %q", got, want)
562 }
563
564 qf := func(pkg *Package) string {
565 if pkg == Unsafe {
566 return "foo"
567 }
568 return ""
569 }
570 got = TypeString(typ, qf)
571 want = "foo.Pointer"
572 if got != want {
573 t.Errorf("got %q; want %q", got, want)
574 }
575 }
576
577 func TestIssue43124(t *testing.T) {
578
579
580
581 const (
582 asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
583 bsrc = `package b; import ("a"; "html/template"); func _() { a.F(template.Template{}) }`
584 csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }`
585 )
586
587 a, err := pkgFor("a", asrc, nil)
588 if err != nil {
589 t.Fatalf("package a failed to typecheck: %v", err)
590 }
591 conf := Config{Importer: importHelper{pkg: a, fallback: defaultImporter()}}
592
593
594
595 bast := mustParse(t, bsrc)
596 _, err = conf.Check(bast.PkgName.Value, []*syntax.File{bast}, nil)
597 if err == nil {
598 t.Fatal("package b had no errors")
599 }
600 if !strings.Contains(err.Error(), "text/template") || !strings.Contains(err.Error(), "html/template") {
601 t.Errorf("type checking error for b does not disambiguate package template: %q", err)
602 }
603
604
605 cast := mustParse(t, csrc)
606 _, err = conf.Check(cast.PkgName.Value, []*syntax.File{cast}, nil)
607 if err == nil {
608 t.Fatal("package c had no errors")
609 }
610 if !strings.Contains(err.Error(), "html/template") {
611 t.Errorf("type checking error for c does not disambiguate package template: %q", err)
612 }
613 }
614
615 func TestIssue50646(t *testing.T) {
616 anyType := Universe.Lookup("any").Type()
617 comparableType := Universe.Lookup("comparable").Type()
618
619 if !Comparable(anyType) {
620 t.Errorf("any is not a comparable type")
621 }
622 if !Comparable(comparableType) {
623 t.Errorf("comparable is not a comparable type")
624 }
625
626 if Implements(anyType, comparableType.Underlying().(*Interface)) {
627 t.Errorf("any implements comparable")
628 }
629 if !Implements(comparableType, anyType.(*Interface)) {
630 t.Errorf("comparable does not implement any")
631 }
632
633 if AssignableTo(anyType, comparableType) {
634 t.Errorf("any assignable to comparable")
635 }
636 if !AssignableTo(comparableType, anyType) {
637 t.Errorf("comparable not assignable to any")
638 }
639 }
640
View as plain text