Source file
src/go/types/issues_test.go
1
2
3
4
5
6
7 package types_test
8
9 import (
10 "fmt"
11 "go/ast"
12 "go/importer"
13 "go/parser"
14 "go/token"
15 "internal/testenv"
16 "regexp"
17 "slices"
18 "strings"
19 "testing"
20
21 . "go/types"
22 )
23
24 func TestIssue5770(t *testing.T) {
25 _, err := typecheck(`package p; type S struct{T}`, nil, nil)
26 const want = "undefined: T"
27 if err == nil || !strings.Contains(err.Error(), want) {
28 t.Errorf("got: %v; want: %s", err, want)
29 }
30 }
31
32 func TestIssue5849(t *testing.T) {
33 src := `
34 package p
35 var (
36 s uint
37 _ = uint8(8)
38 _ = uint16(16) << s
39 _ = uint32(32 << s)
40 _ = uint64(64 << s + s)
41 _ = (interface{})("foo")
42 _ = (interface{})(nil)
43 )`
44 types := make(map[ast.Expr]TypeAndValue)
45 mustTypecheck(src, nil, &Info{Types: types})
46
47 for x, tv := range types {
48 var want Type
49 switch x := x.(type) {
50 case *ast.BasicLit:
51 switch x.Value {
52 case `8`:
53 want = Typ[Uint8]
54 case `16`:
55 want = Typ[Uint16]
56 case `32`:
57 want = Typ[Uint32]
58 case `64`:
59 want = Typ[Uint]
60 case `"foo"`:
61 want = Typ[String]
62 }
63 case *ast.Ident:
64 if x.Name == "nil" {
65 want = Typ[UntypedNil]
66 }
67 }
68 if want != nil && !Identical(tv.Type, want) {
69 t.Errorf("got %s; want %s", tv.Type, want)
70 }
71 }
72 }
73
74 func TestIssue6413(t *testing.T) {
75 src := `
76 package p
77 func f() int {
78 defer f()
79 go f()
80 return 0
81 }
82 `
83 types := make(map[ast.Expr]TypeAndValue)
84 mustTypecheck(src, nil, &Info{Types: types})
85
86 want := Typ[Int]
87 n := 0
88 for x, tv := range types {
89 if _, ok := x.(*ast.CallExpr); ok {
90 if tv.Type != want {
91 t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want)
92 }
93 n++
94 }
95 }
96
97 if n != 2 {
98 t.Errorf("got %d CallExprs; want 2", n)
99 }
100 }
101
102 func TestIssue7245(t *testing.T) {
103 src := `
104 package p
105 func (T) m() (res bool) { return }
106 type T struct{} // receiver type after method declaration
107 `
108 f := mustParse(fset, src)
109
110 var conf Config
111 defs := make(map[*ast.Ident]Object)
112 _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
113 if err != nil {
114 t.Fatal(err)
115 }
116
117 m := f.Decls[0].(*ast.FuncDecl)
118 res1 := defs[m.Name].(*Func).Signature().Results().At(0)
119 res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
120
121 if res1 != res2 {
122 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
123 }
124 }
125
126
127
128
129 func TestIssue7827(t *testing.T) {
130 const src = `
131 package p
132 func _() {
133 const w = 1 // defs w
134 x, y := 2, 3 // defs x, y
135 w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
136 _, _, _ = x, y, z // uses x, y, z
137 }
138 `
139
140
141 fset := token.NewFileSet()
142 f := mustParse(fset, src)
143
144 const want = `L3 defs func p._()
145 L4 defs const w untyped int
146 L5 defs var x int
147 L5 defs var y int
148 L6 defs var z int
149 L6 uses const w untyped int
150 L6 uses var x int
151 L7 uses var x int
152 L7 uses var y int
153 L7 uses var z int`
154
155
156 conf := Config{Error: func(err error) { t.Log(err) }}
157 defs := make(map[*ast.Ident]Object)
158 uses := make(map[*ast.Ident]Object)
159 _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
160 if s := err.Error(); !strings.HasSuffix(s, "cannot assign to w") {
161 t.Errorf("Check: unexpected error: %s", s)
162 }
163
164 var facts []string
165 for id, obj := range defs {
166 if obj != nil {
167 fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
168 facts = append(facts, fact)
169 }
170 }
171 for id, obj := range uses {
172 fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
173 facts = append(facts, fact)
174 }
175 slices.Sort(facts)
176
177 got := strings.Join(facts, "\n")
178 if got != want {
179 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
180 }
181 }
182
183
184
185
186
187
188
189 func TestIssue13898(t *testing.T) {
190 testenv.MustHaveGoBuild(t)
191
192 const src0 = `
193 package main
194
195 import "go/types"
196
197 func main() {
198 var info types.Info
199 for _, obj := range info.Uses {
200 _ = obj.Pkg()
201 }
202 }
203 `
204
205 const src1 = `
206 package main
207
208 import (
209 "go/types"
210 _ "go/importer"
211 )
212
213 func main() {
214 var info types.Info
215 for _, obj := range info.Uses {
216 _ = obj.Pkg()
217 }
218 }
219 `
220
221
222 const src2 = `
223 package main
224
225 import (
226 _ "go/importer"
227 "go/types"
228 )
229
230 func main() {
231 var info types.Info
232 for _, obj := range info.Uses {
233 _ = obj.Pkg()
234 }
235 }
236 `
237 f := func(test, src string) {
238 info := &Info{Uses: make(map[*ast.Ident]Object)}
239 mustTypecheck(src, nil, info)
240
241 var pkg *Package
242 count := 0
243 for id, obj := range info.Uses {
244 if id.Name == "Pkg" {
245 pkg = obj.Pkg()
246 count++
247 }
248 }
249 if count != 1 {
250 t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
251 }
252 if pkg.Name() != "types" {
253 t.Fatalf("%s: got %v; want package types", test, pkg)
254 }
255 }
256
257 f("src0", src0)
258 f("src1", src1)
259 f("src2", src2)
260 }
261
262 func TestIssue22525(t *testing.T) {
263 const src = `package p; func f() { var a, b, c, d, e int }`
264
265 got := "\n"
266 conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
267 typecheck(src, &conf, nil)
268 want := "\n" +
269 "p:1:27: declared and not used: a\n" +
270 "p:1:30: declared and not used: b\n" +
271 "p:1:33: declared and not used: c\n" +
272 "p:1:36: declared and not used: d\n" +
273 "p:1:39: declared and not used: e\n"
274 if got != want {
275 t.Errorf("got: %swant: %s", got, want)
276 }
277 }
278
279 func TestIssue25627(t *testing.T) {
280 const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
281
282
283 for _, src := range []string{
284 `struct { x Missing }`,
285 `struct { Missing }`,
286 `struct { *Missing }`,
287 `struct { unsafe.Pointer }`,
288 `struct { P }`,
289 `struct { *I }`,
290 `struct { a int; b Missing; *Missing }`,
291 } {
292 f := mustParse(fset, prefix+src)
293
294 cfg := Config{Importer: importer.Default(), Error: func(err error) {}}
295 info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
296 _, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
297 if err != nil {
298 if _, ok := err.(Error); !ok {
299 t.Fatal(err)
300 }
301 }
302
303 ast.Inspect(f, func(n ast.Node) bool {
304 if spec, _ := n.(*ast.TypeSpec); spec != nil {
305 if tv, ok := info.Types[spec.Type]; ok && spec.Name.Name == "T" {
306 want := strings.Count(src, ";") + 1
307 if got := tv.Type.(*Struct).NumFields(); got != want {
308 t.Errorf("%s: got %d fields; want %d", src, got, want)
309 }
310 }
311 }
312 return true
313 })
314 }
315 }
316
317 func TestIssue28005(t *testing.T) {
318
319
320 sources := [...]string{
321 "package p; type A interface{ A() }",
322 "package p; type B interface{ B() }",
323 "package p; type X interface{ A; B }",
324 }
325
326
327 var orig [len(sources)]*ast.File
328 for i, src := range sources {
329 orig[i] = mustParse(fset, src)
330 }
331
332
333 for _, perm := range [][len(sources)]int{
334 {0, 1, 2},
335 {0, 2, 1},
336 {1, 0, 2},
337 {1, 2, 0},
338 {2, 0, 1},
339 {2, 1, 0},
340 } {
341
342 files := make([]*ast.File, len(sources))
343 for i := range perm {
344 files[i] = orig[perm[i]]
345 }
346
347
348 var conf Config
349 info := &Info{Defs: make(map[*ast.Ident]Object)}
350 _, err := conf.Check("", fset, files, info)
351 if err != nil {
352 t.Fatal(err)
353 }
354
355
356 var obj Object
357 for name, def := range info.Defs {
358 if name.Name == "X" {
359 obj = def
360 break
361 }
362 }
363 if obj == nil {
364 t.Fatal("object X not found")
365 }
366 iface := obj.Type().Underlying().(*Interface)
367
368
369
370 for i := 0; i < iface.NumMethods(); i++ {
371 m := iface.Method(i)
372 recvName := m.Signature().Recv().Type().(*Named).Obj().Name()
373 if recvName != m.Name() {
374 t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
375 }
376 }
377 }
378 }
379
380 func TestIssue28282(t *testing.T) {
381
382 et := Universe.Lookup("error").Type()
383 it := NewInterfaceType(nil, []Type{et})
384 it.Complete()
385
386 want := et.Underlying().(*Interface).Method(0)
387 got := it.Method(0)
388 if got != want {
389 t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
390 }
391
392 obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
393 if obj != want {
394 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
395 }
396 obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
397 if obj != want {
398 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
399 }
400 }
401
402 func TestIssue29029(t *testing.T) {
403 f1 := mustParse(fset, `package p; type A interface { M() }`)
404 f2 := mustParse(fset, `package p; var B interface { A }`)
405
406
407 printInfo := func(info *Info) string {
408 var buf strings.Builder
409 for _, obj := range info.Defs {
410 if fn, ok := obj.(*Func); ok {
411 fmt.Fprintln(&buf, fn)
412 }
413 }
414 return buf.String()
415 }
416
417
418
419
420
421
422 var conf Config
423 info := &Info{Defs: make(map[*ast.Ident]Object)}
424 check := NewChecker(&conf, fset, NewPackage("", "p"), info)
425 if err := check.Files([]*ast.File{f1, f2}); err != nil {
426 t.Fatal(err)
427 }
428 want := printInfo(info)
429
430
431 info = &Info{Defs: make(map[*ast.Ident]Object)}
432 check = NewChecker(&conf, fset, NewPackage("", "p"), info)
433 if err := check.Files([]*ast.File{f1}); err != nil {
434 t.Fatal(err)
435 }
436 if err := check.Files([]*ast.File{f2}); err != nil {
437 t.Fatal(err)
438 }
439 got := printInfo(info)
440
441 if got != want {
442 t.Errorf("\ngot : %swant: %s", got, want)
443 }
444 }
445
446 func TestIssue34151(t *testing.T) {
447 const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
448 const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
449
450 a := mustTypecheck(asrc, nil, nil)
451
452 conf := Config{Importer: importHelper{pkg: a}}
453 mustTypecheck(bsrc, &conf, nil)
454 }
455
456 type importHelper struct {
457 pkg *Package
458 fallback Importer
459 }
460
461 func (h importHelper) Import(path string) (*Package, error) {
462 if path == h.pkg.Path() {
463 return h.pkg, nil
464 }
465 if h.fallback == nil {
466 return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
467 }
468 return h.fallback.Import(path)
469 }
470
471
472
473
474
475
476
477 func TestIssue34921(t *testing.T) {
478 defer func() {
479 if r := recover(); r != nil {
480 t.Error(r)
481 }
482 }()
483
484 var sources = []string{
485 `package a; type T int`,
486 `package b; import "a"; type T a.T`,
487 }
488
489 var pkg *Package
490 for _, src := range sources {
491 conf := Config{Importer: importHelper{pkg: pkg}}
492 pkg = mustTypecheck(src, &conf, nil)
493 }
494 }
495
496 func TestIssue43088(t *testing.T) {
497
498
499
500
501
502
503
504
505
506 n1 := NewTypeName(nopos, nil, "T1", nil)
507 T1 := NewNamed(n1, nil, nil)
508 n2 := NewTypeName(nopos, nil, "T2", nil)
509 T2 := NewNamed(n2, nil, nil)
510 s1 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
511 T1.SetUnderlying(s1)
512 s2 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
513 s3 := NewStruct([]*Var{NewField(nopos, nil, "_", s2, false)}, nil)
514 T2.SetUnderlying(s3)
515
516
517 Comparable(T1)
518 Comparable(T2)
519 }
520
521 func TestIssue44515(t *testing.T) {
522 typ := Unsafe.Scope().Lookup("Pointer").Type()
523
524 got := TypeString(typ, nil)
525 want := "unsafe.Pointer"
526 if got != want {
527 t.Errorf("got %q; want %q", got, want)
528 }
529
530 qf := func(pkg *Package) string {
531 if pkg == Unsafe {
532 return "foo"
533 }
534 return ""
535 }
536 got = TypeString(typ, qf)
537 want = "foo.Pointer"
538 if got != want {
539 t.Errorf("got %q; want %q", got, want)
540 }
541 }
542
543 func TestIssue43124(t *testing.T) {
544
545
546 testenv.MustHaveGoBuild(t)
547
548
549
550
551 const (
552 asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
553 bsrc = `
554 package b
555
556 import (
557 "a"
558 "html/template"
559 )
560
561 func _() {
562 // Packages should be fully qualified when there is ambiguity within the
563 // error string itself.
564 a.F(template /* ERRORx "cannot use.*html/template.* as .*text/template" */ .Template{})
565 }
566 `
567 csrc = `
568 package c
569
570 import (
571 "a"
572 "fmt"
573 "html/template"
574 )
575
576 // go.dev/issue/46905: make sure template is not the first package qualified.
577 var _ fmt.Stringer = 1 // ERRORx "cannot use 1.*as fmt\\.Stringer"
578
579 // Packages should be fully qualified when there is ambiguity in reachable
580 // packages. In this case both a (and for that matter html/template) import
581 // text/template.
582 func _() { a.G(template /* ERRORx "cannot use .*html/template.*Template" */ .Template{}) }
583 `
584
585 tsrc = `
586 package template
587
588 import "text/template"
589
590 type T int
591
592 // Verify that the current package name also causes disambiguation.
593 var _ T = template /* ERRORx "cannot use.*text/template.* as T value" */.Template{}
594 `
595 )
596
597 a := mustTypecheck(asrc, nil, nil)
598 imp := importHelper{pkg: a, fallback: importer.Default()}
599
600 withImporter := func(cfg *Config) {
601 cfg.Importer = imp
602 }
603
604 testFiles(t, []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, withImporter)
605 testFiles(t, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, withImporter)
606 testFiles(t, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, withImporter)
607 }
608
609 func TestIssue50646(t *testing.T) {
610 anyType := Universe.Lookup("any").Type().Underlying()
611 comparableType := Universe.Lookup("comparable").Type()
612
613 if !Comparable(anyType) {
614 t.Error("any is not a comparable type")
615 }
616 if !Comparable(comparableType) {
617 t.Error("comparable is not a comparable type")
618 }
619
620 if Implements(anyType, comparableType.Underlying().(*Interface)) {
621 t.Error("any implements comparable")
622 }
623 if !Implements(comparableType, anyType.(*Interface)) {
624 t.Error("comparable does not implement any")
625 }
626
627 if AssignableTo(anyType, comparableType) {
628 t.Error("any assignable to comparable")
629 }
630 if !AssignableTo(comparableType, anyType) {
631 t.Error("comparable not assignable to any")
632 }
633 }
634
635 func TestIssue55030(t *testing.T) {
636
637 makeSig := func(typ Type) {
638 par := NewVar(nopos, nil, "", typ)
639 params := NewTuple(par)
640 NewSignatureType(nil, nil, nil, params, nil, true)
641 }
642
643
644
645 makeSig(NewSlice(Typ[Int]))
646
647
648 makeSig(Typ[String])
649
650
651 {
652 P := NewTypeName(nopos, nil, "P", nil)
653 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
654 }
655
656
657 {
658 P := NewTypeName(nopos, nil, "P", nil)
659 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
660 }
661
662
663 {
664 t1 := NewTerm(true, Typ[String])
665 t2 := NewTerm(false, NewSlice(Typ[Byte]))
666 u := NewUnion([]*Term{t1, t2})
667 P := NewTypeName(nopos, nil, "P", nil)
668 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
669 }
670 }
671
672 func TestIssue51093(t *testing.T) {
673
674
675
676
677 var tests = []struct {
678 typ string
679 val string
680 }{
681 {"bool", "false"},
682 {"int", "-1"},
683 {"uint", "1.0"},
684 {"rune", "'a'"},
685 {"float64", "3.5"},
686 {"complex64", "1.25"},
687 {"string", "\"foo\""},
688
689
690 {"~byte", "1"},
691 {"~int | ~float64 | complex128", "1"},
692 {"~uint64 | ~rune", "'X'"},
693 }
694
695 for _, test := range tests {
696 src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
697 types := make(map[ast.Expr]TypeAndValue)
698 mustTypecheck(src, nil, &Info{Types: types})
699
700 var n int
701 for x, tv := range types {
702 if x, _ := x.(*ast.CallExpr); x != nil {
703
704 n++
705 tpar, _ := tv.Type.(*TypeParam)
706 if tpar == nil {
707 t.Fatalf("%s: got type %s, want type parameter", ExprString(x), tv.Type)
708 }
709 if name := tpar.Obj().Name(); name != "P" {
710 t.Fatalf("%s: got type parameter name %s, want P", ExprString(x), name)
711 }
712
713 if tv.Value != nil {
714 t.Errorf("%s: got constant value %s (%s), want no constant", ExprString(x), tv.Value, tv.Value.String())
715 }
716 }
717 }
718
719 if n != 1 {
720 t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1)
721 }
722 }
723 }
724
725 func TestIssue54258(t *testing.T) {
726
727 tests := []struct{ main, b, want string }{
728 {
729 `package main
730 import "b"
731 type I0 interface {
732 M0(w struct{ f string })
733 }
734 var _ I0 = b.S{}
735 `,
736 `package b
737 type S struct{}
738 func (S) M0(struct{ f string }) {}
739 `,
740 `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
741 .*have M0[(]struct{f string /[*] package b [*]/ }[)]
742 .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
743
744 {
745 `package main
746 import "b"
747 type I1 interface {
748 M1(struct{ string })
749 }
750 var _ I1 = b.S{}
751 `,
752 `package b
753 type S struct{}
754 func (S) M1(struct{ string }) {}
755 `,
756 `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
757 .*have M1[(]struct{string /[*] package b [*]/ }[)]
758 .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
759
760 {
761 `package main
762 import "b"
763 type I2 interface {
764 M2(y struct{ f struct{ f string } })
765 }
766 var _ I2 = b.S{}
767 `,
768 `package b
769 type S struct{}
770 func (S) M2(struct{ f struct{ f string } }) {}
771 `,
772 `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
773 .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
774 .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
775
776 {
777 `package main
778 import "b"
779 type I3 interface {
780 M3(z struct{ F struct{ f string } })
781 }
782 var _ I3 = b.S{}
783 `,
784 `package b
785 type S struct{}
786 func (S) M3(struct{ F struct{ f string } }) {}
787 `,
788 `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
789 .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
790 .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
791
792 {
793 `package main
794 import "b"
795 type I4 interface {
796 M4(_ struct { *string })
797 }
798 var _ I4 = b.S{}
799 `,
800 `package b
801 type S struct{}
802 func (S) M4(struct { *string }) {}
803 `,
804 `6:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
805 .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
806 .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
807
808 {
809 `package main
810 import "b"
811 type t struct{ A int }
812 type I5 interface {
813 M5(_ struct {b.S;t})
814 }
815 var _ I5 = b.S{}
816 `,
817 `package b
818 type S struct{}
819 type t struct{ A int }
820 func (S) M5(struct {S;t}) {}
821 `,
822 `7:12: cannot use b[.]S{} [(]value of struct type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
823 .*have M5[(]struct{b[.]S; b[.]t}[)]
824 .*want M5[(]struct{b[.]S; t}[)]`},
825 }
826
827 fset := token.NewFileSet()
828 test := func(main, b, want string) {
829 re := regexp.MustCompile(want)
830 bpkg := mustTypecheck(b, nil, nil)
831 mast := mustParse(fset, main)
832 conf := Config{Importer: importHelper{pkg: bpkg}}
833 _, err := conf.Check(mast.Name.Name, fset, []*ast.File{mast}, nil)
834 if err == nil {
835 t.Error("Expected failure, but it did not")
836 } else if got := err.Error(); !re.MatchString(got) {
837 t.Errorf("Wanted match for\n\t%s\n but got\n\t%s", want, got)
838 } else if testing.Verbose() {
839 t.Logf("Saw expected\n\t%s", err.Error())
840 }
841 }
842 for _, t := range tests {
843 test(t.main, t.b, t.want)
844 }
845 }
846
847 func TestIssue59944(t *testing.T) {
848 testenv.MustHaveCGO(t)
849
850
851 const src = `
852 package p
853
854 /*
855 struct layout {
856 int field;
857 };
858 */
859 import "C"
860
861 type Layout = C.struct_layout
862
863 func (l *Layout) Binding() {}
864
865 func _() {
866 _ = (*Layout).Binding
867 }
868 `
869
870
871 const cgoTypes = `
872 // Code generated by cmd/cgo; DO NOT EDIT.
873
874 package p
875
876 import "unsafe"
877
878 import "syscall"
879
880 import _cgopackage "runtime/cgo"
881
882 type _ _cgopackage.Incomplete
883 var _ syscall.Errno
884 func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }
885
886 //go:linkname _Cgo_always_false runtime.cgoAlwaysFalse
887 var _Cgo_always_false bool
888 //go:linkname _Cgo_use runtime.cgoUse
889 func _Cgo_use(interface{})
890 type _Ctype_int int32
891
892 type _Ctype_struct_layout struct {
893 field _Ctype_int
894 }
895
896 type _Ctype_void [0]byte
897
898 //go:linkname _cgo_runtime_cgocall runtime.cgocall
899 func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
900
901 //go:linkname _cgoCheckPointer runtime.cgoCheckPointer
902 func _cgoCheckPointer(interface{}, interface{})
903
904 //go:linkname _cgoCheckResult runtime.cgoCheckResult
905 func _cgoCheckResult(interface{})
906 `
907 testFiles(t, []string{"p.go", "_cgo_gotypes.go"}, [][]byte{[]byte(src), []byte(cgoTypes)}, false, func(cfg *Config) {
908 *boolFieldAddr(cfg, "go115UsesCgo") = true
909 })
910 }
911
912 func TestIssue61931(t *testing.T) {
913 const src = `
914 package p
915
916 func A(func(any), ...any) {}
917 func B[T any](T) {}
918
919 func _() {
920 A(B, nil // syntax error: missing ',' before newline in argument list
921 }
922 `
923 fset := token.NewFileSet()
924 f, err := parser.ParseFile(fset, pkgName(src), src, 0)
925 if err == nil {
926 t.Fatal("expected syntax error")
927 }
928
929 var conf Config
930 conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
931 }
932
933 func TestIssue61938(t *testing.T) {
934 const src = `
935 package p
936
937 func f[T any]() {}
938 func _() { f() }
939 `
940
941 var conf Config
942 typecheck(src, &conf, nil)
943
944
945 conf.Error = func(error) {}
946 typecheck(src, &conf, nil)
947 }
948
949 func TestIssue63260(t *testing.T) {
950 const src = `
951 package p
952
953 func _() {
954 use(f[*string])
955 }
956
957 func use(func()) {}
958
959 func f[I *T, T any]() {
960 var v T
961 _ = v
962 }`
963
964 info := Info{
965 Defs: make(map[*ast.Ident]Object),
966 }
967 pkg := mustTypecheck(src, nil, &info)
968
969
970 T := pkg.Scope().Lookup("f").Type().(*Signature).TypeParams().At(1)
971 if T.Obj().Name() != "T" {
972 t.Fatalf("got type parameter %s, want T", T)
973 }
974
975
976 var v Object
977 for name, obj := range info.Defs {
978 if name.Name == "v" {
979 v = obj
980 break
981 }
982 }
983 if v == nil {
984 t.Fatal("variable v not found")
985 }
986
987
988 if v.Type() != T {
989 t.Fatalf("types of v and T are not pointer-identical: %p != %p", v.Type().(*TypeParam), T)
990 }
991 }
992
993 func TestIssue44410(t *testing.T) {
994 const src = `
995 package p
996
997 type A = []int
998 type S struct{ A }
999 `
1000
1001 t.Setenv("GODEBUG", "gotypesalias=1")
1002 pkg := mustTypecheck(src, nil, nil)
1003
1004 S := pkg.Scope().Lookup("S")
1005 if S == nil {
1006 t.Fatal("object S not found")
1007 }
1008
1009 got := S.String()
1010 const want = "type p.S struct{p.A}"
1011 if got != want {
1012 t.Fatalf("got %q; want %q", got, want)
1013 }
1014 }
1015
1016 func TestIssue59831(t *testing.T) {
1017
1018
1019 const asrc = `package a; type S struct{}; func (S) m() {}`
1020 apkg := mustTypecheck(asrc, nil, nil)
1021
1022
1023
1024 const bsrc = `package b; type S struct{}; func (S) M() {}`
1025 bpkg := mustTypecheck(bsrc, nil, nil)
1026
1027 tests := []struct {
1028 imported *Package
1029 src, err string
1030 }{
1031
1032 {apkg, `package a1; import "a"; var _ interface { M() } = a.S{}`,
1033 "a.S does not implement interface{M()} (missing method M) have m() want M()"},
1034
1035 {apkg, `package a2; import "a"; var _ interface { m() } = a.S{}`,
1036 "a.S does not implement interface{m()} (unexported method m)"},
1037
1038 {nil, `package a3; type S struct{}; func (S) m(); var _ interface { M() } = S{}`,
1039 "S does not implement interface{M()} (missing method M) have m() want M()"},
1040
1041 {nil, `package a4; type S struct{}; func (S) m(); var _ interface { m() } = S{}`,
1042 ""},
1043
1044 {nil, `package a5; type S struct{}; func (S) m(); var _ interface { n() } = S{}`,
1045 "S does not implement interface{n()} (missing method n)"},
1046
1047
1048 {bpkg, `package b1; import "b"; var _ interface { m() } = b.S{}`,
1049 "b.S does not implement interface{m()} (missing method m) have M() want m()"},
1050
1051 {bpkg, `package b2; import "b"; var _ interface { M() } = b.S{}`,
1052 ""},
1053
1054 {nil, `package b3; type S struct{}; func (S) M(); var _ interface { M() } = S{}`,
1055 ""},
1056
1057 {nil, `package b4; type S struct{}; func (S) M(); var _ interface { m() } = S{}`,
1058 "S does not implement interface{m()} (missing method m) have M() want m()"},
1059
1060 {nil, `package b5; type S struct{}; func (S) M(); var _ interface { n() } = S{}`,
1061 "S does not implement interface{n()} (missing method n)"},
1062 }
1063
1064 for _, test := range tests {
1065
1066 conf := Config{Importer: importHelper{pkg: test.imported}}
1067 pkg, err := typecheck(test.src, &conf, nil)
1068 if err == nil {
1069 if test.err != "" {
1070 t.Errorf("package %s: got no error, want %q", pkg.Name(), test.err)
1071 }
1072 continue
1073 }
1074 if test.err == "" {
1075 t.Errorf("package %s: got %q, want not error", pkg.Name(), err.Error())
1076 }
1077
1078
1079 errmsg := strings.ReplaceAll(err.Error(), "\n", " ")
1080 errmsg = strings.ReplaceAll(errmsg, "\t", "")
1081
1082
1083 if !strings.Contains(errmsg, test.err) {
1084 t.Errorf("package %s: got %q, want %q", pkg.Name(), errmsg, test.err)
1085 }
1086 }
1087 }
1088
1089 func TestIssue64759(t *testing.T) {
1090 const src = `
1091 //go:build go1.18
1092 package p
1093
1094 func f[S ~[]E, E any](S) {}
1095
1096 func _() {
1097 f([]string{})
1098 }
1099 `
1100
1101
1102 conf := Config{GoVersion: "go1.17"}
1103 mustTypecheck(src, &conf, nil)
1104 }
1105
1106 func TestIssue68334(t *testing.T) {
1107 const src = `
1108 package p
1109
1110 func f(x int) {
1111 for i, j := range x {
1112 _, _ = i, j
1113 }
1114 var a, b int
1115 for a, b = range x {
1116 _, _ = a, b
1117 }
1118 }
1119 `
1120
1121 got := ""
1122 conf := Config{
1123 GoVersion: "go1.21",
1124 Error: func(err error) { got += err.Error() + "\n" },
1125 }
1126 typecheck(src, &conf, nil)
1127
1128 want := "p:5:20: cannot range over x (variable of type int): requires go1.22 or later\n" +
1129 "p:9:19: cannot range over x (variable of type int): requires go1.22 or later\n"
1130 if got != want {
1131 t.Errorf("got: %s want: %s", got, want)
1132 }
1133 }
1134
1135 func TestIssue68877(t *testing.T) {
1136 const src = `
1137 package p
1138
1139 type (
1140 S struct{}
1141 A = S
1142 T A
1143 )`
1144
1145 t.Setenv("GODEBUG", "gotypesalias=1")
1146 pkg := mustTypecheck(src, nil, nil)
1147 T := pkg.Scope().Lookup("T").(*TypeName)
1148 got := T.String()
1149 const want = "type p.T struct{}"
1150 if got != want {
1151 t.Errorf("got %s, want %s", got, want)
1152 }
1153 }
1154
1155 func TestIssue69092(t *testing.T) {
1156 const src = `
1157 package p
1158
1159 var _ = T{{x}}
1160 `
1161
1162 fset := token.NewFileSet()
1163 file := mustParse(fset, src)
1164 conf := Config{Error: func(err error) {}}
1165 info := Info{Types: make(map[ast.Expr]TypeAndValue)}
1166 conf.Check("p", fset, []*ast.File{file}, &info)
1167
1168
1169 outer := file.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0].(*ast.CompositeLit)
1170 inner := outer.Elts[0]
1171
1172
1173 tv, ok := info.Types[inner]
1174 if !ok {
1175 t.Fatal("no type found for {x}")
1176 }
1177 if tv.Type != Typ[Invalid] {
1178 t.Fatalf("unexpected type for {x}: %s", tv.Type)
1179 }
1180 }
1181
View as plain text