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.
10 "cmd/compile/internal/syntax"
19 . "cmd/compile/internal/types2"
22 func TestIssue5770(t *testing.T) {
23 _, err := typecheck(`package p; type S struct{T}`, nil, nil)
24 const want = "undefined: T"
25 if err == nil || !strings.Contains(err.Error(), want) {
26 t.Errorf("got: %v; want: %s", err, want)
30 func TestIssue5849(t *testing.T) {
38 _ = uint64(64 << s + s)
39 _ = (interface{})("foo")
40 _ = (interface{})(nil)
42 types := make(map[syntax.Expr]TypeAndValue)
43 mustTypecheck(src, nil, &Info{Types: types})
45 for x, tv := range types {
47 switch x := x.(type) {
48 case *syntax.BasicLit:
57 want = Typ[Uint] // because of "+ s", s is of type uint
63 want = NewInterfaceType(nil, nil) // interface{} (for now, go/types types this as "untyped nil")
66 if want != nil && !Identical(tv.Type, want) {
67 t.Errorf("got %s; want %s", tv.Type, want)
72 func TestIssue6413(t *testing.T) {
81 types := make(map[syntax.Expr]TypeAndValue)
82 mustTypecheck(src, nil, &Info{Types: types})
86 for x, tv := range types {
87 if _, ok := x.(*syntax.CallExpr); ok {
89 t.Errorf("%s: got %s; want %s", x.Pos(), tv.Type, want)
96 t.Errorf("got %d CallExprs; want 2", n)
100 func TestIssue7245(t *testing.T) {
103 func (T) m() (res bool) { return }
104 type T struct{} // receiver type after method declaration
109 defs := make(map[*syntax.Name]Object)
110 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, &Info{Defs: defs})
115 m := f.DeclList[0].(*syntax.FuncDecl)
116 res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
117 res2 := defs[m.Type.ResultList[0].Name].(*Var)
120 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
124 // This tests that uses of existing vars on the LHS of an assignment
125 // are Uses, not Defs; and also that the (illegal) use of a non-var on
126 // the LHS of an assignment is a Use nonetheless.
127 func TestIssue7827(t *testing.T) {
131 const w = 1 // defs w
132 x, y := 2, 3 // defs x, y
133 w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
134 _, _, _ = x, y, z // uses x, y, z
137 const want = `L3 defs func p._()
138 L4 defs const w untyped int
142 L6 uses const w untyped int
148 // don't abort at the first error
149 conf := Config{Error: func(err error) { t.Log(err) }}
150 defs := make(map[*syntax.Name]Object)
151 uses := make(map[*syntax.Name]Object)
152 _, err := typecheck(src, &conf, &Info{Defs: defs, Uses: uses})
153 if s := err.Error(); !strings.HasSuffix(s, "cannot assign to w") {
154 t.Errorf("Check: unexpected error: %s", s)
158 for id, obj := range defs {
160 fact := fmt.Sprintf("L%d defs %s", id.Pos().Line(), obj)
161 facts = append(facts, fact)
164 for id, obj := range uses {
165 fact := fmt.Sprintf("L%d uses %s", id.Pos().Line(), obj)
166 facts = append(facts, fact)
170 got := strings.Join(facts, "\n")
172 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
176 // This tests that the package associated with the types2.Object.Pkg method
177 // is the type's package independent of the order in which the imports are
178 // listed in the sources src1, src2 below.
179 // The actual issue is in go/internal/gcimporter which has a corresponding
180 // test; we leave this test here to verify correct behavior at the go/types
182 func TestIssue13898(t *testing.T) {
183 testenv.MustHaveGoBuild(t)
192 for _, obj := range info.Uses {
197 // like src0, but also imports go/importer
208 for _, obj := range info.Uses {
213 // like src1 but with different import order
214 // (used to fail with this issue)
225 for _, obj := range info.Uses {
230 f := func(test, src string) {
231 info := &Info{Uses: make(map[*syntax.Name]Object)}
232 mustTypecheck(src, nil, info)
236 for id, obj := range info.Uses {
237 if id.Value == "Pkg" {
243 t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
245 if pkg.Name() != "types" {
246 t.Fatalf("%s: got %v; want package types2", test, pkg)
255 func TestIssue22525(t *testing.T) {
256 const src = `package p; func f() { var a, b, c, d, e int }`
259 conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
260 typecheck(src, &conf, nil) // do not crash
262 p:1:27: a declared and not used
263 p:1:30: b declared and not used
264 p:1:33: c declared and not used
265 p:1:36: d declared and not used
266 p:1:39: e declared and not used
269 t.Errorf("got: %swant: %s", got, want)
273 func TestIssue25627(t *testing.T) {
274 const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
275 // The src strings (without prefix) are constructed such that the number of semicolons
276 // plus one corresponds to the number of fields expected in the respective struct.
277 for _, src := range []string{
278 `struct { x Missing }`,
279 `struct { Missing }`,
280 `struct { *Missing }`,
281 `struct { unsafe.Pointer }`,
284 `struct { a int; b Missing; *Missing }`,
286 f := mustParse(prefix + src)
288 conf := Config{Importer: defaultImporter(), Error: func(err error) {}}
289 info := &Info{Types: make(map[syntax.Expr]TypeAndValue)}
290 _, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
292 if _, ok := err.(Error); !ok {
297 syntax.Inspect(f, func(n syntax.Node) bool {
298 if decl, _ := n.(*syntax.TypeDecl); decl != nil {
299 if tv, ok := info.Types[decl.Type]; ok && decl.Name.Value == "T" {
300 want := strings.Count(src, ";") + 1
301 if got := tv.Type.(*Struct).NumFields(); got != want {
302 t.Errorf("%s: got %d fields; want %d", src, got, want)
311 func TestIssue28005(t *testing.T) {
312 // method names must match defining interface name for this test
313 // (see last comment in this function)
314 sources := [...]string{
315 "package p; type A interface{ A() }",
316 "package p; type B interface{ B() }",
317 "package p; type X interface{ A; B }",
320 // compute original file ASTs
321 var orig [len(sources)]*syntax.File
322 for i, src := range sources {
323 orig[i] = mustParse(src)
326 // run the test for all order permutations of the incoming files
327 for _, perm := range [][len(sources)]int{
335 // create file order permutation
336 files := make([]*syntax.File, len(sources))
337 for i := range perm {
338 files[i] = orig[perm[i]]
341 // type-check package with given file order permutation
343 info := &Info{Defs: make(map[*syntax.Name]Object)}
344 _, err := conf.Check("", files, info)
349 // look for interface object X
351 for name, def := range info.Defs {
352 if name.Value == "X" {
358 t.Fatal("object X not found")
360 iface := obj.Type().Underlying().(*Interface) // object X must be an interface
362 // Each iface method m is embedded; and m's receiver base type name
363 // must match the method's name per the choice in the source file.
364 for i := 0; i < iface.NumMethods(); i++ {
366 recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
367 if recvName != m.Name() {
368 t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
374 func TestIssue28282(t *testing.T) {
375 // create type interface { error }
376 et := Universe.Lookup("error").Type()
377 it := NewInterfaceType(nil, []Type{et})
378 // verify that after completing the interface, the embedded method remains unchanged
379 // (interfaces are "completed" lazily now, so the completion happens implicitly when
380 // accessing Method(0))
381 want := et.Underlying().(*Interface).Method(0)
384 t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
386 // verify that lookup finds the same method in both interfaces (redundant check)
387 obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
389 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
391 obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
393 t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
397 func TestIssue29029(t *testing.T) {
398 f1 := mustParse(`package p; type A interface { M() }`)
399 f2 := mustParse(`package p; var B interface { A }`)
401 // printInfo prints the *Func definitions recorded in info, one *Func per line.
402 printInfo := func(info *Info) string {
403 var buf strings.Builder
404 for _, obj := range info.Defs {
405 if fn, ok := obj.(*Func); ok {
406 fmt.Fprintln(&buf, fn)
412 // The *Func (method) definitions for package p must be the same
413 // independent on whether f1 and f2 are type-checked together, or
416 // type-check together
418 info := &Info{Defs: make(map[*syntax.Name]Object)}
419 check := NewChecker(&conf, NewPackage("", "p"), info)
420 if err := check.Files([]*syntax.File{f1, f2}); err != nil {
423 want := printInfo(info)
425 // type-check incrementally
426 info = &Info{Defs: make(map[*syntax.Name]Object)}
427 check = NewChecker(&conf, NewPackage("", "p"), info)
428 if err := check.Files([]*syntax.File{f1}); err != nil {
431 if err := check.Files([]*syntax.File{f2}); err != nil {
434 got := printInfo(info)
437 t.Errorf("\ngot : %swant: %s", got, want)
441 func TestIssue34151(t *testing.T) {
442 const asrc = `package a; type I interface{ M() }; type T struct { F interface { I } }`
443 const bsrc = `package b; import "a"; type T struct { F interface { a.I } }; var _ = a.T(T{})`
445 a := mustTypecheck(asrc, nil, nil)
447 conf := Config{Importer: importHelper{pkg: a}}
448 mustTypecheck(bsrc, &conf, nil)
451 type importHelper struct {
456 func (h importHelper) Import(path string) (*Package, error) {
457 if path == h.pkg.Path() {
460 if h.fallback == nil {
461 return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path())
463 return h.fallback.Import(path)
466 // TestIssue34921 verifies that we don't update an imported type's underlying
467 // type when resolving an underlying type. Specifically, when determining the
468 // underlying type of b.T (which is the underlying type of a.T, which is int)
469 // we must not set the underlying type of a.T again since that would lead to
470 // a race condition if package b is imported elsewhere, in a package that is
471 // concurrently type-checked.
472 func TestIssue34921(t *testing.T) {
474 if r := recover(); r != nil {
479 var sources = []string{
480 `package a; type T int`,
481 `package b; import "a"; type T a.T`,
485 for _, src := range sources {
486 conf := Config{Importer: importHelper{pkg: pkg}}
487 pkg = mustTypecheck(src, &conf, nil) // pkg imported by the next package in this test
491 func TestIssue43088(t *testing.T) {
501 n1 := NewTypeName(syntax.Pos{}, nil, "T1", nil)
502 T1 := NewNamed(n1, nil, nil)
503 n2 := NewTypeName(syntax.Pos{}, nil, "T2", nil)
504 T2 := NewNamed(n2, nil, nil)
505 s1 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
507 s2 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
508 s3 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", s2, false)}, nil)
511 // These calls must terminate (no endless recursion).
516 func TestIssue44515(t *testing.T) {
517 typ := Unsafe.Scope().Lookup("Pointer").Type()
519 got := TypeString(typ, nil)
520 want := "unsafe.Pointer"
522 t.Errorf("got %q; want %q", got, want)
525 qf := func(pkg *Package) string {
531 got = TypeString(typ, qf)
534 t.Errorf("got %q; want %q", got, want)
538 func TestIssue43124(t *testing.T) {
539 testenv.MustHaveGoBuild(t)
541 // All involved packages have the same name (template). Error messages should
542 // disambiguate between text/template and html/template by printing the full
545 asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
546 bsrc = `package b; import ("a"; "html/template"); func _() { a.F(template.Template{}) }`
547 csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }`
550 a := mustTypecheck(asrc, nil, nil)
551 conf := Config{Importer: importHelper{pkg: a, fallback: defaultImporter()}}
553 // Packages should be fully qualified when there is ambiguity within the
554 // error string itself.
555 _, err := typecheck(bsrc, &conf, nil)
557 t.Fatal("package b had no errors")
559 if !strings.Contains(err.Error(), "text/template") || !strings.Contains(err.Error(), "html/template") {
560 t.Errorf("type checking error for b does not disambiguate package template: %q", err)
563 // ...and also when there is any ambiguity in reachable packages.
564 _, err = typecheck(csrc, &conf, nil)
566 t.Fatal("package c had no errors")
568 if !strings.Contains(err.Error(), "html/template") {
569 t.Errorf("type checking error for c does not disambiguate package template: %q", err)
573 func TestIssue50646(t *testing.T) {
574 anyType := Universe.Lookup("any").Type()
575 comparableType := Universe.Lookup("comparable").Type()
577 if !Comparable(anyType) {
578 t.Error("any is not a comparable type")
580 if !Comparable(comparableType) {
581 t.Error("comparable is not a comparable type")
584 if Implements(anyType, comparableType.Underlying().(*Interface)) {
585 t.Error("any implements comparable")
587 if !Implements(comparableType, anyType.(*Interface)) {
588 t.Error("comparable does not implement any")
591 if AssignableTo(anyType, comparableType) {
592 t.Error("any assignable to comparable")
594 if !AssignableTo(comparableType, anyType) {
595 t.Error("comparable not assignable to any")
599 func TestIssue55030(t *testing.T) {
600 // makeSig makes the signature func(typ...)
601 makeSig := func(typ Type) {
602 par := NewVar(nopos, nil, "", typ)
603 params := NewTuple(par)
604 NewSignatureType(nil, nil, nil, params, nil, true)
607 // makeSig must not panic for the following (example) types:
609 makeSig(NewSlice(Typ[Int]))
614 // P where P's core type is string
616 P := NewTypeName(nopos, nil, "P", nil) // [P string]
617 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
620 // P where P's core type is an (unnamed) slice
622 P := NewTypeName(nopos, nil, "P", nil) // [P []int]
623 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
626 // P where P's core type is bytestring (i.e., string or []byte)
628 t1 := NewTerm(true, Typ[String]) // ~string
629 t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
630 u := NewUnion([]*Term{t1, t2}) // ~string | []byte
631 P := NewTypeName(nopos, nil, "P", nil) // [P ~string | []byte]
632 makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
636 func TestIssue51093(t *testing.T) {
637 // Each test stands for a conversion of the form P(val)
638 // where P is a type parameter with typ as constraint.
639 // The test ensures that P(val) has the correct type P
640 // and is not a constant.
641 var tests = []struct {
650 {"complex64", "1.25"},
651 {"string", "\"foo\""},
653 // some more complex constraints
655 {"~int | ~float64 | complex128", "1"},
656 {"~uint64 | ~rune", "'X'"},
659 for _, test := range tests {
660 src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val)
661 types := make(map[syntax.Expr]TypeAndValue)
662 mustTypecheck(src, nil, &Info{Types: types})
665 for x, tv := range types {
666 if x, _ := x.(*syntax.CallExpr); x != nil {
667 // there must be exactly one CallExpr which is the P(val) conversion
669 tpar, _ := tv.Type.(*TypeParam)
671 t.Fatalf("%s: got type %s, want type parameter", syntax.String(x), tv.Type)
673 if name := tpar.Obj().Name(); name != "P" {
674 t.Fatalf("%s: got type parameter name %s, want P", syntax.String(x), name)
676 // P(val) must not be constant
678 t.Errorf("%s: got constant value %s (%s), want no constant", syntax.String(x), tv.Value, tv.Value.String())
684 t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1)
689 func TestIssue54258(t *testing.T) {
690 tests := []struct{ main, b, want string }{
691 { //---------------------------------------------------------------
695 M0(w struct{ f string })
701 func (S) M0(struct{ f string }) {}
703 `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I0 value in variable declaration: b[.]S does not implement I0 [(]wrong type for method M0[)]
704 .*have M0[(]struct{f string /[*] package b [*]/ }[)]
705 .*want M0[(]struct{f string /[*] package main [*]/ }[)]`},
707 { //---------------------------------------------------------------
717 func (S) M1(struct{ string }) {}
719 `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I1 value in variable declaration: b[.]S does not implement I1 [(]wrong type for method M1[)]
720 .*have M1[(]struct{string /[*] package b [*]/ }[)]
721 .*want M1[(]struct{string /[*] package main [*]/ }[)]`},
723 { //---------------------------------------------------------------
727 M2(y struct{ f struct{ f string } })
733 func (S) M2(struct{ f struct{ f string } }) {}
735 `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I2 value in variable declaration: b[.]S does not implement I2 [(]wrong type for method M2[)]
736 .*have M2[(]struct{f struct{f string} /[*] package b [*]/ }[)]
737 .*want M2[(]struct{f struct{f string} /[*] package main [*]/ }[)]`},
739 { //---------------------------------------------------------------
743 M3(z struct{ F struct{ f string } })
749 func (S) M3(struct{ F struct{ f string } }) {}
751 `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I3 value in variable declaration: b[.]S does not implement I3 [(]wrong type for method M3[)]
752 .*have M3[(]struct{F struct{f string /[*] package b [*]/ }}[)]
753 .*want M3[(]struct{F struct{f string /[*] package main [*]/ }}[)]`},
755 { //---------------------------------------------------------------
759 M4(_ struct { *string })
765 func (S) M4(struct { *string }) {}
767 `6:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I4 value in variable declaration: b[.]S does not implement I4 [(]wrong type for method M4[)]
768 .*have M4[(]struct{[*]string /[*] package b [*]/ }[)]
769 .*want M4[(]struct{[*]string /[*] package main [*]/ }[)]`},
771 { //---------------------------------------------------------------
774 type t struct{ A int }
782 type t struct{ A int }
783 func (S) M5(struct {S;t}) {}
785 `7:12: cannot use b[.]S{} [(]value of type b[.]S[)] as I5 value in variable declaration: b[.]S does not implement I5 [(]wrong type for method M5[)]
786 .*have M5[(]struct{b[.]S; b[.]t}[)]
787 .*want M5[(]struct{b[.]S; t}[)]`},
790 test := func(main, b, want string) {
791 re := regexp.MustCompile(want)
792 bpkg := mustTypecheck(b, nil, nil)
793 mast := mustParse(main)
794 conf := Config{Importer: importHelper{pkg: bpkg}}
795 _, err := conf.Check(mast.PkgName.Value, []*syntax.File{mast}, nil)
797 t.Error("Expected failure, but it did not")
798 } else if got := err.Error(); !re.MatchString(got) {
799 t.Errorf("Wanted match for\n\t%s\n but got\n\t%s", want, got)
800 } else if testing.Verbose() {
801 t.Logf("Saw expected\n\t%s", err.Error())
804 for _, t := range tests {
805 test(t.main, t.b, t.want)
809 func TestIssue59944(t *testing.T) {
810 if runtime.GOARCH == "wasm" {
811 // While we don't use the cgo tool directly in this test, we must have the
813 t.Skip("cgo generated code does not compile on wasm")
815 // The typechecker should resolve methods declared on aliases of cgo types.
826 type Layout = C.struct_layout
828 func (l *Layout) Binding() {}
831 _ = (*Layout).Binding
835 // code generated by cmd/cgo for the above source.
837 // Code generated by cmd/cgo; DO NOT EDIT.
845 import _cgopackage "runtime/cgo"
847 type _ _cgopackage.Incomplete
849 func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }
851 //go:linkname _Cgo_always_false runtime.cgoAlwaysFalse
852 var _Cgo_always_false bool
853 //go:linkname _Cgo_use runtime.cgoUse
854 func _Cgo_use(interface{})
855 type _Ctype_int int32
857 type _Ctype_struct_layout struct {
861 type _Ctype_void [0]byte
863 //go:linkname _cgo_runtime_cgocall runtime.cgocall
864 func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
866 //go:linkname _cgoCheckPointer runtime.cgoCheckPointer
867 func _cgoCheckPointer(interface{}, interface{})
869 //go:linkname _cgoCheckResult runtime.cgoCheckResult
870 func _cgoCheckResult(interface{})
872 testFiles(t, []string{"p.go", "_cgo_gotypes.go"}, [][]byte{[]byte(src), []byte(cgoTypes)}, 0, false, func(cfg *Config) {
873 *boolFieldAddr(cfg, "go115UsesCgo") = true