Source file
src/go/types/named_test.go
1
2
3
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
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
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
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 := Unalias(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 }
130
131
132
133
134 func TestMethodOrdering(t *testing.T) {
135 const src = `
136 package p
137
138 type T struct{}
139
140 func (T) a() {}
141 func (T) c() {}
142 func (T) b() {}
143 `
144
145 var methods []string
146 for i := 0; i < 5; i++ {
147
148 pkg := mustTypecheck(src, nil, nil)
149 T := pkg.Scope().Lookup("T").Type().(*Named)
150
151
152 for _, name := range []string{"foo", "bar", "bal"} {
153 m := NewFunc(nopos, pkg, name, nil )
154 T.AddMethod(m)
155 }
156
157
158 if i == 0 {
159
160 methods = make([]string, T.NumMethods())
161 for j := range methods {
162 methods[j] = T.Method(j).Name()
163 }
164 } else {
165
166 if got := T.NumMethods(); got != len(methods) {
167 t.Errorf("got %d methods, want %d", got, len(methods))
168 continue
169 }
170 for j, m := range methods {
171 if got := T.Method(j).Name(); got != m {
172 t.Errorf("got method %s, want %s", got, m)
173 }
174 }
175 }
176 }
177 }
178
View as plain text