]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/types2/issues_test.go
go/types: resolve cgo base type names
[gostls13.git] / src / cmd / compile / internal / types2 / issues_test.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This file implements tests for various issues.
6
7 package types2_test
8
9 import (
10         "cmd/compile/internal/syntax"
11         "fmt"
12         "internal/testenv"
13         "regexp"
14         "runtime"
15         "sort"
16         "strings"
17         "testing"
18
19         . "cmd/compile/internal/types2"
20 )
21
22 func TestIssue5770(t *testing.T) {
23         _, err := typecheck(`package p; type S struct{T}`, nil, nil)
24         const want = "undefined: T"
25         if err == nil || !strings.Contains(err.Error(), want) {
26                 t.Errorf("got: %v; want: %s", err, want)
27         }
28 }
29
30 func TestIssue5849(t *testing.T) {
31         src := `
32 package p
33 var (
34         s uint
35         _ = uint8(8)
36         _ = uint16(16) << s
37         _ = uint32(32 << s)
38         _ = uint64(64 << s + s)
39         _ = (interface{})("foo")
40         _ = (interface{})(nil)
41 )`
42         types := make(map[syntax.Expr]TypeAndValue)
43         mustTypecheck(src, nil, &Info{Types: types})
44
45         for x, tv := range types {
46                 var want Type
47                 switch x := x.(type) {
48                 case *syntax.BasicLit:
49                         switch x.Value {
50                         case `8`:
51                                 want = Typ[Uint8]
52                         case `16`:
53                                 want = Typ[Uint16]
54                         case `32`:
55                                 want = Typ[Uint32]
56                         case `64`:
57                                 want = Typ[Uint] // because of "+ s", s is of type uint
58                         case `"foo"`:
59                                 want = Typ[String]
60                         }
61                 case *syntax.Name:
62                         if x.Value == "nil" {
63                                 want = NewInterfaceType(nil, nil) // interface{} (for now, go/types types this as "untyped nil")
64                         }
65                 }
66                 if want != nil && !Identical(tv.Type, want) {
67                         t.Errorf("got %s; want %s", tv.Type, want)
68                 }
69         }
70 }
71
72 func TestIssue6413(t *testing.T) {
73         src := `
74 package p
75 func f() int {
76         defer f()
77         go f()
78         return 0
79 }
80 `
81         types := make(map[syntax.Expr]TypeAndValue)
82         mustTypecheck(src, nil, &Info{Types: types})
83
84         want := Typ[Int]
85         n := 0
86         for x, tv := range types {
87                 if _, ok := x.(*syntax.CallExpr); ok {
88                         if tv.Type != want {
89                                 t.Errorf("%s: got %s; want %s", x.Pos(), tv.Type, want)
90                         }
91                         n++
92                 }
93         }
94
95         if n != 2 {
96                 t.Errorf("got %d CallExprs; want 2", n)
97         }
98 }
99
100 func TestIssue7245(t *testing.T) {
101         src := `
102 package p
103 func (T) m() (res bool) { return }
104 type T struct{} // receiver type after method declaration
105 `
106         f := mustParse(src)
107
108         var conf Config
109         defs := make(map[*syntax.Name]Object)
110         _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, &Info{Defs: defs})
111         if err != nil {
112                 t.Fatal(err)
113         }
114
115         m := f.DeclList[0].(*syntax.FuncDecl)
116         res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
117         res2 := defs[m.Type.ResultList[0].Name].(*Var)
118
119         if res1 != res2 {
120                 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
121         }
122 }
123
124 // This tests that uses of existing vars on the LHS of an assignment
125 // are Uses, not Defs; and also that the (illegal) use of a non-var on
126 // the LHS of an assignment is a Use nonetheless.
127 func TestIssue7827(t *testing.T) {
128         const src = `
129 package p
130 func _() {
131         const w = 1        // defs w
132         x, y := 2, 3       // defs x, y
133         w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
134         _, _, _ = x, y, z  // uses x, y, z
135 }
136 `
137         const want = `L3 defs func p._()
138 L4 defs const w untyped int
139 L5 defs var x int
140 L5 defs var y int
141 L6 defs var z int
142 L6 uses const w untyped int
143 L6 uses var x int
144 L7 uses var x int
145 L7 uses var y int
146 L7 uses var z int`
147
148         // don't abort at the first error
149         conf := Config{Error: func(err error) { t.Log(err) }}
150         defs := make(map[*syntax.Name]Object)
151         uses := make(map[*syntax.Name]Object)
152         _, err := typecheck(src, &conf, &Info{Defs: defs, Uses: uses})
153         if s := err.Error(); !strings.HasSuffix(s, "cannot assign to w") {
154                 t.Errorf("Check: unexpected error: %s", s)
155         }
156
157         var facts []string
158         for id, obj := range defs {
159                 if obj != nil {
160                         fact := fmt.Sprintf("L%d defs %s", id.Pos().Line(), obj)
161                         facts = append(facts, fact)
162                 }
163         }
164         for id, obj := range uses {
165                 fact := fmt.Sprintf("L%d uses %s", id.Pos().Line(), obj)
166                 facts = append(facts, fact)
167         }
168         sort.Strings(facts)
169
170         got := strings.Join(facts, "\n")
171         if got != want {
172                 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
173         }
174 }
175
176 // This tests that the package associated with the types2.Object.Pkg method
177 // is the type's package independent of the order in which the imports are
178 // listed in the sources src1, src2 below.
179 // The actual issue is in go/internal/gcimporter which has a corresponding
180 // test; we leave this test here to verify correct behavior at the go/types
181 // level.
182 func TestIssue13898(t *testing.T) {
183         testenv.MustHaveGoBuild(t)
184
185         const src0 = `
186 package main
187
188 import "go/types"
189
190 func main() {
191         var info types.Info
192         for _, obj := range info.Uses {
193                 _ = obj.Pkg()
194         }
195 }
196 `
197         // like src0, but also imports go/importer
198         const src1 = `
199 package main
200
201 import (
202         "go/types"
203         _ "go/importer"
204 )
205
206 func main() {
207         var info types.Info
208         for _, obj := range info.Uses {
209                 _ = obj.Pkg()
210         }
211 }
212 `
213         // like src1 but with different import order
214         // (used to fail with this issue)
215         const src2 = `
216 package main
217
218 import (
219         _ "go/importer"
220         "go/types"
221 )
222
223 func main() {
224         var info types.Info
225         for _, obj := range info.Uses {
226                 _ = obj.Pkg()
227         }
228 }
229 `
230         f := func(test, src string) {
231                 info := &Info{Uses: make(map[*syntax.Name]Object)}
232                 mustTypecheck(src, nil, info)
233
234                 var pkg *Package
235                 count := 0
236                 for id, obj := range info.Uses {
237                         if id.Value == "Pkg" {
238                                 pkg = obj.Pkg()
239                                 count++
240                         }
241                 }
242                 if count != 1 {
243                         t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
244                 }
245                 if pkg.Name() != "types" {
246                         t.Fatalf("%s: got %v; want package types2", test, pkg)
247                 }
248         }
249
250         f("src0", src0)
251         f("src1", src1)
252         f("src2", src2)
253 }
254
255 func TestIssue22525(t *testing.T) {
256         const src = `package p; func f() { var a, b, c, d, e int }`
257
258         got := "\n"
259         conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
260         typecheck(src, &conf, nil) // do not crash
261         want := `
262 p:1:27: a declared and not used
263 p:1:30: b declared and not used
264 p:1:33: c declared and not used
265 p:1:36: d declared and not used
266 p:1:39: e declared and not used
267 `
268         if got != want {
269                 t.Errorf("got: %swant: %s", got, want)
270         }
271 }
272
273 func TestIssue25627(t *testing.T) {
274         const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
275         // The src strings (without prefix) are constructed such that the number of semicolons
276         // plus one corresponds to the number of fields expected in the respective struct.
277         for _, src := range []string{
278                 `struct { x Missing }`,
279                 `struct { Missing }`,
280                 `struct { *Missing }`,
281                 `struct { unsafe.Pointer }`,
282                 `struct { P }`,
283                 `struct { *I }`,
284                 `struct { a int; b Missing; *Missing }`,
285         } {
286                 f := mustParse(prefix + src)
287
288                 conf := Config{Importer: defaultImporter(), Error: func(err error) {}}
289                 info := &Info{Types: make(map[syntax.Expr]TypeAndValue)}
290                 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
291                 if err != nil {
292                         if _, ok := err.(Error); !ok {
293                                 t.Fatal(err)
294                         }
295                 }
296
297                 syntax.Inspect(f, func(n syntax.Node) bool {
298                         if decl, _ := n.(*syntax.TypeDecl); decl != nil {
299                                 if tv, ok := info.Types[decl.Type]; ok && decl.Name.Value == "T" {
300                                         want := strings.Count(src, ";") + 1
301                                         if got := tv.Type.(*Struct).NumFields(); got != want {
302                                                 t.Errorf("%s: got %d fields; want %d", src, got, want)
303                                         }
304                                 }
305                         }
306                         return true
307                 })
308         }
309 }
310
311 func TestIssue28005(t *testing.T) {
312         // method names must match defining interface name for this test
313         // (see last comment in this function)
314         sources := [...]string{
315                 "package p; type A interface{ A() }",
316                 "package p; type B interface{ B() }",
317                 "package p; type X interface{ A; B }",
318         }
319
320         // compute original file ASTs
321         var orig [len(sources)]*syntax.File
322         for i, src := range sources {
323                 orig[i] = mustParse(src)
324         }
325
326         // run the test for all order permutations of the incoming files
327         for _, perm := range [][len(sources)]int{
328                 {0, 1, 2},
329                 {0, 2, 1},
330                 {1, 0, 2},
331                 {1, 2, 0},
332                 {2, 0, 1},
333                 {2, 1, 0},
334         } {
335                 // create file order permutation
336                 files := make([]*syntax.File, len(sources))
337                 for i := range perm {
338                         files[i] = orig[perm[i]]
339                 }
340
341                 // type-check package with given file order permutation
342                 var conf Config
343                 info := &Info{Defs: make(map[*syntax.Name]Object)}
344                 _, err := conf.Check("", files, info)
345                 if err != nil {
346                         t.Fatal(err)
347                 }
348
349                 // look for interface object X
350                 var obj Object
351                 for name, def := range info.Defs {
352                         if name.Value == "X" {
353                                 obj = def
354                                 break
355                         }
356                 }
357                 if obj == nil {
358                         t.Fatal("object X not found")
359                 }
360                 iface := obj.Type().Underlying().(*Interface) // object X must be an interface
361
362                 // Each iface method m is embedded; and m's receiver base type name
363                 // must match the method's name per the choice in the source file.
364                 for i := 0; i < iface.NumMethods(); i++ {
365                         m := iface.Method(i)
366                         recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
367                         if recvName != m.Name() {
368                                 t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
369                         }
370                 }
371         }
372 }
373
374 func TestIssue28282(t *testing.T) {
375         // create type interface { error }
376         et := Universe.Lookup("error").Type()
377         it := NewInterfaceType(nil, []Type{et})
378         // verify that after completing the interface, the embedded method remains unchanged
379         // (interfaces are "completed" lazily now, so the completion happens implicitly when
380         // accessing Method(0))
381         want := et.Underlying().(*Interface).Method(0)
382         got := it.Method(0)
383         if got != want {
384                 t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
385         }
386         // verify that lookup finds the same method in both interfaces (redundant check)
387         obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
388         if obj != want {
389                 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
390         }
391         obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
392         if obj != want {
393                 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
394         }
395 }
396
397 func TestIssue29029(t *testing.T) {
398         f1 := mustParse(`package p; type A interface { M() }`)
399         f2 := mustParse(`package p; var B interface { A }`)
400
401         // printInfo prints the *Func definitions recorded in info, one *Func per line.
402         printInfo := func(info *Info) string {
403                 var buf strings.Builder
404                 for _, obj := range info.Defs {
405                         if fn, ok := obj.(*Func); ok {
406                                 fmt.Fprintln(&buf, fn)
407                         }
408                 }
409                 return buf.String()
410         }
411
412         // The *Func (method) definitions for package p must be the same
413         // independent on whether f1 and f2 are type-checked together, or
414         // incrementally.
415
416         // type-check together
417         var conf Config
418         info := &Info{Defs: make(map[*syntax.Name]Object)}
419         check := NewChecker(&conf, NewPackage("", "p"), info)
420         if err := check.Files([]*syntax.File{f1, f2}); err != nil {
421                 t.Fatal(err)
422         }
423         want := printInfo(info)
424
425         // type-check incrementally
426         info = &Info{Defs: make(map[*syntax.Name]Object)}
427         check = NewChecker(&conf, NewPackage("", "p"), info)
428         if err := check.Files([]*syntax.File{f1}); err != nil {
429                 t.Fatal(err)
430         }
431         if err := check.Files([]*syntax.File{f2}); err != nil {
432                 t.Fatal(err)
433         }
434         got := printInfo(info)
435
436         if got != want {
437                 t.Errorf("\ngot : %swant: %s", got, want)
438         }
439 }
440
441 func TestIssue34151(t *testing.T) {
442         const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
443         const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
444
445         a := mustTypecheck(asrc, nil, nil)
446
447         conf := Config{Importer: importHelper{pkg: a}}
448         mustTypecheck(bsrc, &conf, nil)
449 }
450
451 type importHelper struct {
452         pkg      *Package
453         fallback Importer
454 }
455
456 func (h importHelper) Import(path string) (*Package, error) {
457         if path == h.pkg.Path() {
458                 return h.pkg, nil
459         }
460         if h.fallback == nil {
461                 return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
462         }
463         return h.fallback.Import(path)
464 }
465
466 // TestIssue34921 verifies that we don't update an imported type's underlying
467 // type when resolving an underlying type. Specifically, when determining the
468 // underlying type of b.T (which is the underlying type of a.T, which is int)
469 // we must not set the underlying type of a.T again since that would lead to
470 // a race condition if package b is imported elsewhere, in a package that is
471 // concurrently type-checked.
472 func TestIssue34921(t *testing.T) {
473         defer func() {
474                 if r := recover(); r != nil {
475                         t.Error(r)
476                 }
477         }()
478
479         var sources = []string{
480                 `package a; type T int`,
481                 `package b; import "a"; type T a.T`,
482         }
483
484         var pkg *Package
485         for _, src := range sources {
486                 conf := Config{Importer: importHelper{pkg: pkg}}
487                 pkg = mustTypecheck(src, &conf, nil) // pkg imported by the next package in this test
488         }
489 }
490
491 func TestIssue43088(t *testing.T) {
492         // type T1 struct {
493         //         _ T2
494         // }
495         //
496         // type T2 struct {
497         //         _ struct {
498         //                 _ T2
499         //         }
500         // }
501         n1 := NewTypeName(syntax.Pos{}, nil, "T1", nil)
502         T1 := NewNamed(n1, nil, nil)
503         n2 := NewTypeName(syntax.Pos{}, nil, "T2", nil)
504         T2 := NewNamed(n2, nil, nil)
505         s1 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
506         T1.SetUnderlying(s1)
507         s2 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
508         s3 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", s2, false)}, nil)
509         T2.SetUnderlying(s3)
510
511         // These calls must terminate (no endless recursion).
512         Comparable(T1)
513         Comparable(T2)
514 }
515
516 func TestIssue44515(t *testing.T) {
517         typ := Unsafe.Scope().Lookup("Pointer").Type()
518
519         got := TypeString(typ, nil)
520         want := "unsafe.Pointer"
521         if got != want {
522                 t.Errorf("got %q; want %q", got, want)
523         }
524
525         qf := func(pkg *Package) string {
526                 if pkg == Unsafe {
527                         return "foo"
528                 }
529                 return ""
530         }
531         got = TypeString(typ, qf)
532         want = "foo.Pointer"
533         if got != want {
534                 t.Errorf("got %q; want %q", got, want)
535         }
536 }
537
538 func TestIssue43124(t *testing.T) {
539         testenv.MustHaveGoBuild(t)
540
541         // All involved packages have the same name (template). Error messages should
542         // disambiguate between text/template and html/template by printing the full
543         // path.
544         const (
545                 asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
546                 bsrc = `package b; import ("a"; "html/template"); func _() { a.F(template.Template{}) }`
547                 csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }`
548         )
549
550         a := mustTypecheck(asrc, nil, nil)
551         conf := Config{Importer: importHelper{pkg: a, fallback: defaultImporter()}}
552
553         // Packages should be fully qualified when there is ambiguity within the
554         // error string itself.
555         _, err := typecheck(bsrc, &conf, nil)
556         if err == nil {
557                 t.Fatal("package b had no errors")
558         }
559         if !strings.Contains(err.Error(), "text/template") || !strings.Contains(err.Error(), "html/template") {
560                 t.Errorf("type checking error for b does not disambiguate package template: %q", err)
561         }
562
563         // ...and also when there is any ambiguity in reachable packages.
564         _, err = typecheck(csrc, &conf, nil)
565         if err == nil {
566                 t.Fatal("package c had no errors")
567         }
568         if !strings.Contains(err.Error(), "html/template") {
569                 t.Errorf("type checking error for c does not disambiguate package template: %q", err)
570         }
571 }
572
573 func TestIssue50646(t *testing.T) {
574         anyType := Universe.Lookup("any").Type()
575         comparableType := Universe.Lookup("comparable").Type()
576
577         if !Comparable(anyType) {
578                 t.Error("any is not a comparable type")
579         }
580         if !Comparable(comparableType) {
581                 t.Error("comparable is not a comparable type")
582         }
583
584         if Implements(anyType, comparableType.Underlying().(*Interface)) {
585                 t.Error("any implements comparable")
586         }
587         if !Implements(comparableType, anyType.(*Interface)) {
588                 t.Error("comparable does not implement any")
589         }
590
591         if AssignableTo(anyType, comparableType) {
592                 t.Error("any assignable to comparable")
593         }
594         if !AssignableTo(comparableType, anyType) {
595                 t.Error("comparable not assignable to any")
596         }
597 }
598
599 func TestIssue55030(t *testing.T) {
600         // makeSig makes the signature func(typ...)
601         makeSig := func(typ Type) {
602                 par := NewVar(nopos, nil, "", typ)
603                 params := NewTuple(par)
604                 NewSignatureType(nil, nil, nil, params, nil, true)
605         }
606
607         // makeSig must not panic for the following (example) types:
608         // []int
609         makeSig(NewSlice(Typ[Int]))
610
611         // string
612         makeSig(Typ[String])
613
614         // P where P's core type is string
615         {
616                 P := NewTypeName(nopos, nil, "P", nil) // [P string]
617                 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
618         }
619
620         // P where P's core type is an (unnamed) slice
621         {
622                 P := NewTypeName(nopos, nil, "P", nil) // [P []int]
623                 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
624         }
625
626         // P where P's core type is bytestring (i.e., string or []byte)
627         {
628                 t1 := NewTerm(true, Typ[String])          // ~string
629                 t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
630                 u := NewUnion([]*Term{t1, t2})            // ~string | []byte
631                 P := NewTypeName(nopos, nil, "P", nil)    // [P ~string | []byte]
632                 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
633         }
634 }
635
636 func TestIssue51093(t *testing.T) {
637         // Each test stands for a conversion of the form P(val)
638         // where P is a type parameter with typ as constraint.
639         // The test ensures that P(val) has the correct type P
640         // and is not a constant.
641         var tests = []struct {
642                 typ string
643                 val string
644         }{
645                 {"bool", "false"},
646                 {"int", "-1"},
647                 {"uint", "1.0"},
648                 {"rune", "'a'"},
649                 {"float64", "3.5"},
650                 {"complex64", "1.25"},
651                 {"string", "\"foo\""},
652
653                 // some more complex constraints
654                 {"~byte", "1"},
655                 {"~int | ~float64 | complex128", "1"},
656                 {"~uint64 | ~rune", "'X'"},
657         }
658
659         for _, test := range tests {
660                 src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
661                 types := make(map[syntax.Expr]TypeAndValue)
662                 mustTypecheck(src, nil, &Info{Types: types})
663
664                 var n int
665                 for x, tv := range types {
666                         if x, _ := x.(*syntax.CallExpr); x != nil {
667                                 // there must be exactly one CallExpr which is the P(val) conversion
668                                 n++
669                                 tpar, _ := tv.Type.(*TypeParam)
670                                 if tpar == nil {
671                                         t.Fatalf("%s: got type %s, want type parameter", syntax.String(x), tv.Type)
672                                 }
673                                 if name := tpar.Obj().Name(); name != "P" {
674                                         t.Fatalf("%s: got type parameter name %s, want P", syntax.String(x), name)
675                                 }
676                                 // P(val) must not be constant
677                                 if tv.Value != nil {
678                                         t.Errorf("%s: got constant value %s (%s), want no constant", syntax.String(x), tv.Value, tv.Value.String())
679                                 }
680                         }
681                 }
682
683                 if n != 1 {
684                         t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1)
685                 }
686         }
687 }
688
689 func TestIssue54258(t *testing.T) {
690         tests := []struct{ main, b, want string }{
691                 { //---------------------------------------------------------------
692                         `package main
693 import "b"
694 type I0 interface {
695         M0(w struct{ f string })
696 }
697 var _ I0 = b.S{}
698 `,
699                         `package b
700 type S struct{}
701 func (S) M0(struct{ f string }) {}
702 `,
703                         `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
704 .*have M0[(]struct{f string /[*] package b [*]/ }[)]
705 .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
706
707                 { //---------------------------------------------------------------
708                         `package main
709 import "b"
710 type I1 interface {
711         M1(struct{ string })
712 }
713 var _ I1 = b.S{}
714 `,
715                         `package b
716 type S struct{}
717 func (S) M1(struct{ string }) {}
718 `,
719                         `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
720 .*have M1[(]struct{string /[*] package b [*]/ }[)]
721 .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
722
723                 { //---------------------------------------------------------------
724                         `package main
725 import "b"
726 type I2 interface {
727         M2(y struct{ f struct{ f string } })
728 }
729 var _ I2 = b.S{}
730 `,
731                         `package b
732 type S struct{}
733 func (S) M2(struct{ f struct{ f string } }) {}
734 `,
735                         `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
736 .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
737 .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
738
739                 { //---------------------------------------------------------------
740                         `package main
741 import "b"
742 type I3 interface {
743         M3(z struct{ F struct{ f string } })
744 }
745 var _ I3 = b.S{}
746 `,
747                         `package b
748 type S struct{}
749 func (S) M3(struct{ F struct{ f string } }) {}
750 `,
751                         `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
752 .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
753 .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
754
755                 { //---------------------------------------------------------------
756                         `package main
757 import "b"
758 type I4 interface {
759         M4(_ struct { *string })
760 }
761 var _ I4 = b.S{}
762 `,
763                         `package b
764 type S struct{}
765 func (S) M4(struct { *string }) {}
766 `,
767                         `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
768 .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
769 .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
770
771                 { //---------------------------------------------------------------
772                         `package main
773 import "b"
774 type t struct{ A int }
775 type I5 interface {
776         M5(_ struct {b.S;t})
777 }
778 var _ I5 = b.S{}
779 `,
780                         `package b
781 type S struct{}
782 type t struct{ A int }
783 func (S) M5(struct {S;t}) {}
784 `,
785                         `7:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
786 .*have M5[(]struct{b[.]S; b[.]t}[)]
787 .*want M5[(]struct{b[.]S; t}[)]`},
788         }
789
790         test := func(main, b, want string) {
791                 re := regexp.MustCompile(want)
792                 bpkg := mustTypecheck(b, nil, nil)
793                 mast := mustParse(main)
794                 conf := Config{Importer: importHelper{pkg: bpkg}}
795                 _, err := conf.Check(mast.PkgName.Value, []*syntax.File{mast}, nil)
796                 if err == nil {
797                         t.Error("Expected failure, but it did not")
798                 } else if got := err.Error(); !re.MatchString(got) {
799                         t.Errorf("Wanted match for\n\t%s\n but got\n\t%s", want, got)
800                 } else if testing.Verbose() {
801                         t.Logf("Saw expected\n\t%s", err.Error())
802                 }
803         }
804         for _, t := range tests {
805                 test(t.main, t.b, t.want)
806         }
807 }
808
809 func TestIssue59944(t *testing.T) {
810         if runtime.GOARCH == "wasm" {
811                 // While we don't use the cgo tool directly in this test, we must have the
812                 // syscall package.
813                 t.Skip("cgo generated code does not compile on wasm")
814         }
815         // The typechecker should resolve methods declared on aliases of cgo types.
816         const src = `
817 package p
818
819 /*
820 struct layout {
821         int field;
822 };
823 */
824 import "C"
825
826 type Layout = C.struct_layout
827
828 func (l *Layout) Binding() {}
829
830 func _() {
831         _ = (*Layout).Binding
832 }
833 `
834
835         // code generated by cmd/cgo for the above source.
836         const cgoTypes = `
837 // Code generated by cmd/cgo; DO NOT EDIT.
838
839 package p
840
841 import "unsafe"
842
843 import "syscall"
844
845 import _cgopackage "runtime/cgo"
846
847 type _ _cgopackage.Incomplete
848 var _ syscall.Errno
849 func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }
850
851 //go:linkname _Cgo_always_false runtime.cgoAlwaysFalse
852 var _Cgo_always_false bool
853 //go:linkname _Cgo_use runtime.cgoUse
854 func _Cgo_use(interface{})
855 type _Ctype_int int32
856
857 type _Ctype_struct_layout struct {
858         field _Ctype_int
859 }
860
861 type _Ctype_void [0]byte
862
863 //go:linkname _cgo_runtime_cgocall runtime.cgocall
864 func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
865
866 //go:linkname _cgoCheckPointer runtime.cgoCheckPointer
867 func _cgoCheckPointer(interface{}, interface{})
868
869 //go:linkname _cgoCheckResult runtime.cgoCheckResult
870 func _cgoCheckResult(interface{})
871 `
872         testFiles(t, []string{"p.go", "_cgo_gotypes.go"}, [][]byte{[]byte(src), []byte(cgoTypes)}, 0, false, func(cfg *Config) {
873                 *boolFieldAddr(cfg, "go115UsesCgo") = true
874         })
875 }