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