github.com/AndrienkoAleksandr/go@v0.0.19/src/go/types/named_test.go (about) 1 // Copyright 2022 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 package types_test 6 7 import ( 8 "go/ast" 9 "go/token" 10 "testing" 11 12 . "go/types" 13 ) 14 15 func BenchmarkNamed(b *testing.B) { 16 const src = ` 17 package p 18 19 type T struct { 20 P int 21 } 22 23 func (T) M(int) {} 24 func (T) N() (i int) { return } 25 26 type G[P any] struct { 27 F P 28 } 29 30 func (G[P]) M(P) {} 31 func (G[P]) N() (p P) { return } 32 33 type Inst = G[int] 34 ` 35 pkg := mustTypecheck(src, nil, nil) 36 37 var ( 38 T = pkg.Scope().Lookup("T").Type() 39 G = pkg.Scope().Lookup("G").Type() 40 SrcInst = pkg.Scope().Lookup("Inst").Type() 41 UserInst = mustInstantiate(b, G, Typ[Int]) 42 ) 43 44 tests := []struct { 45 name string 46 typ Type 47 }{ 48 {"nongeneric", T}, 49 {"generic", G}, 50 {"src instance", SrcInst}, 51 {"user instance", UserInst}, 52 } 53 54 b.Run("Underlying", func(b *testing.B) { 55 for _, test := range tests { 56 b.Run(test.name, func(b *testing.B) { 57 // Access underlying once, to trigger any lazy calculation. 58 _ = test.typ.Underlying() 59 b.ResetTimer() 60 for i := 0; i < b.N; i++ { 61 _ = test.typ.Underlying() 62 } 63 }) 64 } 65 }) 66 67 b.Run("NewMethodSet", func(b *testing.B) { 68 for _, test := range tests { 69 b.Run(test.name, func(b *testing.B) { 70 // Access underlying once, to trigger any lazy calculation. 71 _ = NewMethodSet(test.typ) 72 b.ResetTimer() 73 for i := 0; i < b.N; i++ { 74 _ = NewMethodSet(test.typ) 75 } 76 }) 77 } 78 }) 79 } 80 81 func mustInstantiate(tb testing.TB, orig Type, targs ...Type) Type { 82 inst, err := Instantiate(nil, orig, targs, true) 83 if err != nil { 84 tb.Fatal(err) 85 } 86 return inst 87 } 88 89 // Test that types do not expand infinitely, as in go.dev/issue/52715. 90 func TestFiniteTypeExpansion(t *testing.T) { 91 const src = ` 92 package p 93 94 type Tree[T any] struct { 95 *Node[T] 96 } 97 98 func (*Tree[R]) N(r R) R { return r } 99 100 type Node[T any] struct { 101 *Tree[T] 102 } 103 104 func (Node[Q]) M(Q) {} 105 106 type Inst = *Tree[int] 107 ` 108 109 fset := token.NewFileSet() 110 f := mustParse(fset, src) 111 pkg := NewPackage("p", f.Name.Name) 112 if err := NewChecker(nil, fset, pkg, nil).Files([]*ast.File{f}); err != nil { 113 t.Fatal(err) 114 } 115 116 firstFieldType := func(n *Named) *Named { 117 return n.Underlying().(*Struct).Field(0).Type().(*Pointer).Elem().(*Named) 118 } 119 120 Inst := pkg.Scope().Lookup("Inst").Type().(*Pointer).Elem().(*Named) 121 Node := firstFieldType(Inst) 122 Tree := firstFieldType(Node) 123 if !Identical(Inst, Tree) { 124 t.Fatalf("Not a cycle: got %v, want %v", Tree, Inst) 125 } 126 if Inst != Tree { 127 t.Errorf("Duplicate instances in cycle: %s (%p) -> %s (%p) -> %s (%p)", Inst, Inst, Node, Node, Tree, Tree) 128 } 129 }