Source file
src/go/types/mono.go
1
2
3
4
5 package types
6
7 import (
8 "go/ast"
9 "go/token"
10 )
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 type monoGraph struct {
52 vertices []monoVertex
53 edges []monoEdge
54
55
56
57 canon map[*TypeParam]*TypeParam
58
59
60
61 nameIdx map[*TypeName]int
62 }
63
64 type monoVertex struct {
65 weight int
66 pre int
67 len int
68
69
70
71 obj *TypeName
72 }
73
74 type monoEdge struct {
75 dst, src int
76 weight int
77
78 pos token.Pos
79 typ Type
80 }
81
82 func (check *Checker) monomorph() {
83
84
85
86
87
88
89 again := true
90 for again {
91 again = false
92
93 for i, edge := range check.mono.edges {
94 src := &check.mono.vertices[edge.src]
95 dst := &check.mono.vertices[edge.dst]
96
97
98
99 w := src.weight + edge.weight
100 if w <= dst.weight {
101 continue
102 }
103
104 dst.pre = i
105 dst.len = src.len + 1
106 if dst.len == len(check.mono.vertices) {
107 check.reportInstanceLoop(edge.dst)
108 return
109 }
110
111 dst.weight = w
112 again = true
113 }
114 }
115 }
116
117 func (check *Checker) reportInstanceLoop(v int) {
118 var stack []int
119 seen := make([]bool, len(check.mono.vertices))
120
121
122
123
124
125 for !seen[v] {
126 stack = append(stack, v)
127 seen[v] = true
128 v = check.mono.edges[check.mono.vertices[v].pre].src
129 }
130
131
132
133
134 for stack[0] != v {
135 stack = stack[1:]
136 }
137
138
139
140 obj0 := check.mono.vertices[v].obj
141 check.errorf(obj0, _InvalidInstanceCycle, "instantiation cycle:")
142
143 qf := RelativeTo(check.pkg)
144 for _, v := range stack {
145 edge := check.mono.edges[check.mono.vertices[v].pre]
146 obj := check.mono.vertices[edge.dst].obj
147
148 switch obj.Type().(type) {
149 default:
150 panic("unexpected type")
151 case *Named:
152 check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf))
153 case *TypeParam:
154 check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf))
155 }
156 }
157 }
158
159
160
161 func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) {
162 if w.canon == nil {
163 w.canon = make(map[*TypeParam]*TypeParam)
164 }
165 w.canon[mpar] = tpar
166 }
167
168
169
170 func (w *monoGraph) recordInstance(pkg *Package, pos token.Pos, tparams []*TypeParam, targs []Type, xlist []ast.Expr) {
171 for i, tpar := range tparams {
172 pos := pos
173 if i < len(xlist) {
174 pos = xlist[i].Pos()
175 }
176 w.assign(pkg, pos, tpar, targs[i])
177 }
178 }
179
180
181 func (w *monoGraph) assign(pkg *Package, pos token.Pos, tpar *TypeParam, targ Type) {
182
183
184
185
186
187
188
189
190 if tpar.Obj().Pkg() != pkg {
191 return
192 }
193
194
195 flow := func(src int, typ Type) {
196 weight := 1
197 if typ == targ {
198 weight = 0
199 }
200
201 w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ)
202 }
203
204
205
206 var do func(typ Type)
207 do = func(typ Type) {
208 switch typ := typ.(type) {
209 default:
210 panic("unexpected type")
211
212 case *TypeParam:
213 assert(typ.Obj().Pkg() == pkg)
214 flow(w.typeParamVertex(typ), typ)
215
216 case *Named:
217 if src := w.localNamedVertex(pkg, typ.Origin()); src >= 0 {
218 flow(src, typ)
219 }
220
221 targs := typ.TypeArgs()
222 for i := 0; i < targs.Len(); i++ {
223 do(targs.At(i))
224 }
225
226 case *Array:
227 do(typ.Elem())
228 case *Basic:
229
230 case *Chan:
231 do(typ.Elem())
232 case *Map:
233 do(typ.Key())
234 do(typ.Elem())
235 case *Pointer:
236 do(typ.Elem())
237 case *Slice:
238 do(typ.Elem())
239
240 case *Interface:
241 for i := 0; i < typ.NumMethods(); i++ {
242 do(typ.Method(i).Type())
243 }
244 case *Signature:
245 tuple := func(tup *Tuple) {
246 for i := 0; i < tup.Len(); i++ {
247 do(tup.At(i).Type())
248 }
249 }
250 tuple(typ.Params())
251 tuple(typ.Results())
252 case *Struct:
253 for i := 0; i < typ.NumFields(); i++ {
254 do(typ.Field(i).Type())
255 }
256 }
257 }
258 do(targ)
259 }
260
261
262
263 func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int {
264 obj := named.Obj()
265 if obj.Pkg() != pkg {
266 return -1
267 }
268
269 root := pkg.Scope()
270 if obj.Parent() == root {
271 return -1
272 }
273
274 if idx, ok := w.nameIdx[obj]; ok {
275 return idx
276 }
277
278 idx := -1
279
280
281
282 for scope := obj.Parent(); scope != root; scope = scope.Parent() {
283 for _, elem := range scope.elems {
284 if elem, ok := elem.(*TypeName); ok && !elem.IsAlias() && elem.Pos() < obj.Pos() {
285 if tpar, ok := elem.Type().(*TypeParam); ok {
286 if idx < 0 {
287 idx = len(w.vertices)
288 w.vertices = append(w.vertices, monoVertex{obj: obj})
289 }
290
291 w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar)
292 }
293 }
294 }
295 }
296
297 if w.nameIdx == nil {
298 w.nameIdx = make(map[*TypeName]int)
299 }
300 w.nameIdx[obj] = idx
301 return idx
302 }
303
304
305 func (w *monoGraph) typeParamVertex(tpar *TypeParam) int {
306 if x, ok := w.canon[tpar]; ok {
307 tpar = x
308 }
309
310 obj := tpar.Obj()
311
312 if idx, ok := w.nameIdx[obj]; ok {
313 return idx
314 }
315
316 if w.nameIdx == nil {
317 w.nameIdx = make(map[*TypeName]int)
318 }
319
320 idx := len(w.vertices)
321 w.vertices = append(w.vertices, monoVertex{obj: obj})
322 w.nameIdx[obj] = idx
323 return idx
324 }
325
326 func (w *monoGraph) addEdge(dst, src, weight int, pos token.Pos, typ Type) {
327
328 w.edges = append(w.edges, monoEdge{
329 dst: dst,
330 src: src,
331 weight: weight,
332
333 pos: pos,
334 typ: typ,
335 })
336 }
337
View as plain text