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