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