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