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.
5 // This file implements tests for various issues.
23 func mustParse(t *testing.T, src string) *ast.File {
24 f, err := parser.ParseFile(fset, "", src, 0)
30 func TestIssue5770(t *testing.T) {
31 f := mustParse(t, `package p; type S struct{T}`)
32 conf := Config{Importer: importer.Default()}
33 _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash
34 const want = "undefined: T"
35 if err == nil || !strings.Contains(err.Error(), want) {
36 t.Errorf("got: %v; want: %s", err, want)
40 func TestIssue5849(t *testing.T) {
48 _ = uint64(64 << s + s)
49 _ = (interface{})("foo")
50 _ = (interface{})(nil)
52 types := make(map[ast.Expr]TypeAndValue)
53 mustTypecheck(t, "p", src, &Info{Types: types})
55 for x, tv := range types {
57 switch x := x.(type) {
67 want = Typ[Uint] // because of "+ s", s is of type uint
73 want = Typ[UntypedNil]
76 if want != nil && !Identical(tv.Type, want) {
77 t.Errorf("got %s; want %s", tv.Type, want)
82 func TestIssue6413(t *testing.T) {
91 types := make(map[ast.Expr]TypeAndValue)
92 mustTypecheck(t, "p", src, &Info{Types: types})
96 for x, tv := range types {
97 if _, ok := x.(*ast.CallExpr); ok {
99 t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want)
106 t.Errorf("got %d CallExprs; want 2", n)
110 func TestIssue7245(t *testing.T) {
113 func (T) m() (res bool) { return }
114 type T struct{} // receiver type after method declaration
116 f := mustParse(t, src)
119 defs := make(map[*ast.Ident]Object)
120 _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
125 m := f.Decls[0].(*ast.FuncDecl)
126 res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
127 res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
130 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
134 // This tests that uses of existing vars on the LHS of an assignment
135 // are Uses, not Defs; and also that the (illegal) use of a non-var on
136 // the LHS of an assignment is a Use nonetheless.
137 func TestIssue7827(t *testing.T) {
141 const w = 1 // defs w
142 x, y := 2, 3 // defs x, y
143 w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
144 _, _, _ = x, y, z // uses x, y, z
147 f := mustParse(t, src)
149 const want = `L3 defs func p._()
150 L4 defs const w untyped int
154 L6 uses const w untyped int
160 // don't abort at the first error
161 conf := Config{Error: func(err error) { t.Log(err) }}
162 defs := make(map[*ast.Ident]Object)
163 uses := make(map[*ast.Ident]Object)
164 _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
165 if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
166 t.Errorf("Check: unexpected error: %s", s)
170 for id, obj := range defs {
172 fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
173 facts = append(facts, fact)
176 for id, obj := range uses {
177 fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
178 facts = append(facts, fact)
182 got := strings.Join(facts, "\n")
184 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
188 // This tests that the package associated with the types.Object.Pkg method
189 // is the type's package independent of the order in which the imports are
190 // listed in the sources src1, src2 below.
191 // The actual issue is in go/internal/gcimporter which has a corresponding
192 // test; we leave this test here to verify correct behavior at the go/types
194 func TestIssue13898(t *testing.T) {
195 testenv.MustHaveGoBuild(t)
204 for _, obj := range info.Uses {
209 // like src0, but also imports go/importer
220 for _, obj := range info.Uses {
225 // like src1 but with different import order
226 // (used to fail with this issue)
237 for _, obj := range info.Uses {
242 f := func(test, src string) {
243 f := mustParse(t, src)
244 cfg := Config{Importer: importer.Default()}
245 info := Info{Uses: make(map[*ast.Ident]Object)}
246 _, err := cfg.Check("main", fset, []*ast.File{f}, &info)
253 for id, obj := range info.Uses {
254 if id.Name == "Pkg" {
260 t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
262 if pkg.Name() != "types" {
263 t.Fatalf("%s: got %v; want package types", test, pkg)
272 func TestIssue22525(t *testing.T) {
273 f := mustParse(t, `package p; func f() { var a, b, c, d, e int }`)
276 conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
277 conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash
279 1:27: a declared and not used
280 1:30: b declared and not used
281 1:33: c declared and not used
282 1:36: d declared and not used
283 1:39: e declared and not used
286 t.Errorf("got: %swant: %s", got, want)
290 func TestIssue25627(t *testing.T) {
291 const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
292 // The src strings (without prefix) are constructed such that the number of semicolons
293 // plus one corresponds to the number of fields expected in the respective struct.
294 for _, src := range []string{
295 `struct { x Missing }`,
296 `struct { Missing }`,
297 `struct { *Missing }`,
298 `struct { unsafe.Pointer }`,
301 `struct { a int; b Missing; *Missing }`,
303 f := mustParse(t, prefix+src)
305 cfg := Config{Importer: importer.Default(), Error: func(err error) {}}
306 info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
307 _, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
309 if _, ok := err.(Error); !ok {
314 ast.Inspect(f, func(n ast.Node) bool {
315 if spec, _ := n.(*ast.TypeSpec); spec != nil {
316 if tv, ok := info.Types[spec.Type]; ok && spec.Name.Name == "T" {
317 want := strings.Count(src, ";") + 1
318 if got := tv.Type.(*Struct).NumFields(); got != want {
319 t.Errorf("%s: got %d fields; want %d", src, got, want)
328 func TestIssue28005(t *testing.T) {
329 // method names must match defining interface name for this test
330 // (see last comment in this function)
331 sources := [...]string{
332 "package p; type A interface{ A() }",
333 "package p; type B interface{ B() }",
334 "package p; type X interface{ A; B }",
337 // compute original file ASTs
338 var orig [len(sources)]*ast.File
339 for i, src := range sources {
340 orig[i] = mustParse(t, src)
343 // run the test for all order permutations of the incoming files
344 for _, perm := range [][len(sources)]int{
352 // create file order permutation
353 files := make([]*ast.File, len(sources))
354 for i := range perm {
355 files[i] = orig[perm[i]]
358 // type-check package with given file order permutation
360 info := &Info{Defs: make(map[*ast.Ident]Object)}
361 _, err := conf.Check("", fset, files, info)
366 // look for interface object X
368 for name, def := range info.Defs {
369 if name.Name == "X" {
375 t.Fatal("object X not found")
377 iface := obj.Type().Underlying().(*Interface) // object X must be an interface
379 // Each iface method m is embedded; and m's receiver base type name
380 // must match the method's name per the choice in the source file.
381 for i := 0; i < iface.NumMethods(); i++ {
383 recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
384 if recvName != m.Name() {
385 t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
391 func TestIssue28282(t *testing.T) {
392 // create type interface { error }
393 et := Universe.Lookup("error").Type()
394 it := NewInterfaceType(nil, []Type{et})
396 // verify that after completing the interface, the embedded method remains unchanged
397 want := et.Underlying().(*Interface).Method(0)
400 t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
402 // verify that lookup finds the same method in both interfaces (redundant check)
403 obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
405 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
407 obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
409 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
413 func TestIssue29029(t *testing.T) {
414 f1 := mustParse(t, `package p; type A interface { M() }`)
415 f2 := mustParse(t, `package p; var B interface { A }`)
417 // printInfo prints the *Func definitions recorded in info, one *Func per line.
418 printInfo := func(info *Info) string {
419 var buf strings.Builder
420 for _, obj := range info.Defs {
421 if fn, ok := obj.(*Func); ok {
422 fmt.Fprintln(&buf, fn)
428 // The *Func (method) definitions for package p must be the same
429 // independent on whether f1 and f2 are type-checked together, or
432 // type-check together
434 info := &Info{Defs: make(map[*ast.Ident]Object)}
435 check := NewChecker(&conf, fset, NewPackage("", "p"), info)
436 if err := check.Files([]*ast.File{f1, f2}); err != nil {
439 want := printInfo(info)
441 // type-check incrementally
442 info = &Info{Defs: make(map[*ast.Ident]Object)}
443 check = NewChecker(&conf, fset, NewPackage("", "p"), info)
444 if err := check.Files([]*ast.File{f1}); err != nil {
447 if err := check.Files([]*ast.File{f2}); err != nil {
450 got := printInfo(info)
453 t.Errorf("\ngot : %swant: %s", got, want)
457 func TestIssue34151(t *testing.T) {
458 const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
459 const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
461 a, err := pkgFor("a", asrc, nil)
463 t.Fatalf("package %s failed to typecheck: %v", a.Name(), err)
466 bast := mustParse(t, bsrc)
467 conf := Config{Importer: importHelper{pkg: a}}
468 b, err := conf.Check(bast.Name.Name, fset, []*ast.File{bast}, nil)
470 t.Errorf("package %s failed to typecheck: %v", b.Name(), err)
474 type importHelper struct {
479 func (h importHelper) Import(path string) (*Package, error) {
480 if path == h.pkg.Path() {
483 if h.fallback == nil {
484 return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
486 return h.fallback.Import(path)
489 // TestIssue34921 verifies that we don't update an imported type's underlying
490 // type when resolving an underlying type. Specifically, when determining the
491 // underlying type of b.T (which is the underlying type of a.T, which is int)
492 // we must not set the underlying type of a.T again since that would lead to
493 // a race condition if package b is imported elsewhere, in a package that is
494 // concurrently type-checked.
495 func TestIssue34921(t *testing.T) {
497 if r := recover(); r != nil {
502 var sources = []string{
503 `package a; type T int`,
504 `package b; import "a"; type T a.T`,
508 for _, src := range sources {
509 f := mustParse(t, src)
510 conf := Config{Importer: importHelper{pkg: pkg}}
511 res, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil)
513 t.Errorf("%q failed to typecheck: %v", src, err)
515 pkg = res // res is imported by the next package in this test
519 func TestIssue43088(t *testing.T) {
529 n1 := NewTypeName(token.NoPos, nil, "T1", nil)
530 T1 := NewNamed(n1, nil, nil)
531 n2 := NewTypeName(token.NoPos, nil, "T2", nil)
532 T2 := NewNamed(n2, nil, nil)
533 s1 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", T2, false)}, nil)
535 s2 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", T2, false)}, nil)
536 s3 := NewStruct([]*Var{NewField(token.NoPos, nil, "_", s2, false)}, nil)
539 // These calls must terminate (no endless recursion).
544 func TestIssue44515(t *testing.T) {
545 typ := Unsafe.Scope().Lookup("Pointer").Type()
547 got := TypeString(typ, nil)
548 want := "unsafe.Pointer"
550 t.Errorf("got %q; want %q", got, want)
553 qf := func(pkg *Package) string {
559 got = TypeString(typ, qf)
562 t.Errorf("got %q; want %q", got, want)
566 func TestIssue43124(t *testing.T) {
567 // TODO(rFindley) move this to testdata by enhancing support for importing.
569 testenv.MustHaveGoBuild(t) // The go command is needed for the importer to determine the locations of stdlib .a files.
571 // All involved packages have the same name (template). Error messages should
572 // disambiguate between text/template and html/template by printing the full
575 asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
585 // Packages should be fully qualified when there is ambiguity within the
586 // error string itself.
587 a.F(template /* ERROR cannot use.*html/template.* as .*text/template */ .Template{})
599 // Issue #46905: make sure template is not the first package qualified.
600 var _ fmt.Stringer = 1 // ERROR cannot use 1.*as fmt\.Stringer
602 // Packages should be fully qualified when there is ambiguity in reachable
603 // packages. In this case both a (and for that matter html/template) import
605 func _() { a.G(template /* ERROR cannot use .*html/template.*Template */ .Template{}) }
611 import "text/template"
615 // Verify that the current package name also causes disambiguation.
616 var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{}
620 a, err := pkgFor("a", asrc, nil)
622 t.Fatalf("package a failed to typecheck: %v", err)
624 imp := importHelper{pkg: a, fallback: importer.Default()}
626 testFiles(t, nil, []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp)
627 testFiles(t, nil, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
628 testFiles(t, nil, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
631 func TestIssue50646(t *testing.T) {
632 anyType := Universe.Lookup("any").Type()
633 comparableType := Universe.Lookup("comparable").Type()
635 if !Comparable(anyType) {
636 t.Errorf("any is not a comparable type")
638 if !Comparable(comparableType) {
639 t.Errorf("comparable is not a comparable type")
642 if Implements(anyType, comparableType.Underlying().(*Interface)) {
643 t.Errorf("any implements comparable")
645 if !Implements(comparableType, anyType.(*Interface)) {
646 t.Errorf("comparable does not implement any")
649 if AssignableTo(anyType, comparableType) {
650 t.Errorf("any assignable to comparable")
652 if !AssignableTo(comparableType, anyType) {
653 t.Errorf("comparable not assignable to any")
657 func TestIssue55030(t *testing.T) {
658 // makeSig makes the signature func(typ...)
659 makeSig := func(typ Type) {
660 par := NewVar(token.NoPos, nil, "", typ)
661 params := NewTuple(par)
662 NewSignatureType(nil, nil, nil, params, nil, true)
665 // makeSig must not panic for the following (example) types:
667 makeSig(NewSlice(Typ[Int]))
672 // P where P's core type is string
674 P := NewTypeName(token.NoPos, nil, "P", nil) // [P string]
675 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
678 // P where P's core type is an (unnamed) slice
680 P := NewTypeName(token.NoPos, nil, "P", nil) // [P []int]
681 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
684 // P where P's core type is bytestring (i.e., string or []byte)
686 t1 := NewTerm(true, Typ[String]) // ~string
687 t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
688 u := NewUnion([]*Term{t1, t2}) // ~string | []byte
689 P := NewTypeName(token.NoPos, nil, "P", nil) // [P ~string | []byte]
690 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
694 func TestIssue51093(t *testing.T) {
695 // Each test stands for a conversion of the form P(val)
696 // where P is a type parameter with typ as constraint.
697 // The test ensures that P(val) has the correct type P
698 // and is not a constant.
699 var tests = []struct {
708 {"complex64", "1.25"},
709 {"string", "\"foo\""},
711 // some more complex constraints
713 {"~int | ~float64 | complex128", "1"},
714 {"~uint64 | ~rune", "'X'"},
717 for _, test := range tests {
718 src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
719 types := make(map[ast.Expr]TypeAndValue)
720 mustTypecheck(t, "p", src, &Info{Types: types})
723 for x, tv := range types {
724 if x, _ := x.(*ast.CallExpr); x != nil {
725 // there must be exactly one CallExpr which is the P(val) conversion
727 tpar, _ := tv.Type.(*TypeParam)
729 t.Fatalf("%s: got type %s, want type parameter", ExprString(x), tv.Type)
731 if name := tpar.Obj().Name(); name != "P" {
732 t.Fatalf("%s: got type parameter name %s, want P", ExprString(x), name)
734 // P(val) must not be constant
736 t.Errorf("%s: got constant value %s (%s), want no constant", ExprString(x), tv.Value, tv.Value.String())
742 t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1)