1
2
3
4
5 package types2
6
7 import (
8 "cmd/compile/internal/syntax"
9 . "internal/types/errors"
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 syntax.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 err := check.newError(InvalidInstanceCycle)
141 obj0 := check.mono.vertices[v].obj
142 err.addf(obj0, "instantiation cycle:")
143
144 qf := RelativeTo(check.pkg)
145 for _, v := range stack {
146 edge := check.mono.edges[check.mono.vertices[v].pre]
147 obj := check.mono.vertices[edge.dst].obj
148
149 switch obj.Type().(type) {
150 default:
151 panic("unexpected type")
152 case *Named:
153 err.addf(atPos(edge.pos), "%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf))
154 case *TypeParam:
155 err.addf(atPos(edge.pos), "%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf))
156 }
157 }
158 err.report()
159 }
160
161
162
163 func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) {
164 if w.canon == nil {
165 w.canon = make(map[*TypeParam]*TypeParam)
166 }
167 w.canon[mpar] = tpar
168 }
169
170
171
172 func (w *monoGraph) recordInstance(pkg *Package, pos syntax.Pos, tparams []*TypeParam, targs []Type, xlist []syntax.Expr) {
173 for i, tpar := range tparams {
174 pos := pos
175 if i < len(xlist) {
176 pos = startPos(xlist[i])
177 }
178 w.assign(pkg, pos, tpar, targs[i])
179 }
180 }
181
182
183 func (w *monoGraph) assign(pkg *Package, pos syntax.Pos, tpar *TypeParam, targ Type) {
184
185
186
187
188
189
190
191
192 if tpar.Obj().Pkg() != pkg {
193 return
194 }
195
196
197 flow := func(src int, typ Type) {
198 weight := 1
199 if typ == targ {
200 weight = 0
201 }
202
203 w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ)
204 }
205
206
207
208 var do func(typ Type)
209 do = func(typ Type) {
210 switch typ := Unalias(typ).(type) {
211 default:
212 panic("unexpected type")
213
214 case *TypeParam:
215 assert(typ.Obj().Pkg() == pkg)
216 flow(w.typeParamVertex(typ), typ)
217
218 case *Named:
219 if src := w.localNamedVertex(pkg, typ.Origin()); src >= 0 {
220 flow(src, typ)
221 }
222
223 targs := typ.TypeArgs()
224 for i := 0; i < targs.Len(); i++ {
225 do(targs.At(i))
226 }
227
228 case *Array:
229 do(typ.Elem())
230 case *Basic:
231
232 case *Chan:
233 do(typ.Elem())
234 case *Map:
235 do(typ.Key())
236 do(typ.Elem())
237 case *Pointer:
238 do(typ.Elem())
239 case *Slice:
240 do(typ.Elem())
241
242 case *Interface:
243 for i := 0; i < typ.NumMethods(); i++ {
244 do(typ.Method(i).Type())
245 }
246 case *Signature:
247 tuple := func(tup *Tuple) {
248 for i := 0; i < tup.Len(); i++ {
249 do(tup.At(i).Type())
250 }
251 }
252 tuple(typ.Params())
253 tuple(typ.Results())
254 case *Struct:
255 for i := 0; i < typ.NumFields(); i++ {
256 do(typ.Field(i).Type())
257 }
258 }
259 }
260 do(targ)
261 }
262
263
264
265 func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int {
266 obj := named.Obj()
267 if obj.Pkg() != pkg {
268 return -1
269 }
270
271 root := pkg.Scope()
272 if obj.Parent() == root {
273 return -1
274 }
275
276 if idx, ok := w.nameIdx[obj]; ok {
277 return idx
278 }
279
280 idx := -1
281
282
283
284 for scope := obj.Parent(); scope != root; scope = scope.Parent() {
285 for _, elem := range scope.elems {
286 if elem, ok := elem.(*TypeName); ok && !elem.IsAlias() && cmpPos(elem.Pos(), obj.Pos()) < 0 {
287 if tpar, ok := elem.Type().(*TypeParam); ok {
288 if idx < 0 {
289 idx = len(w.vertices)
290 w.vertices = append(w.vertices, monoVertex{obj: obj})
291 }
292
293 w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar)
294 }
295 }
296 }
297 }
298
299 if w.nameIdx == nil {
300 w.nameIdx = make(map[*TypeName]int)
301 }
302 w.nameIdx[obj] = idx
303 return idx
304 }
305
306
307 func (w *monoGraph) typeParamVertex(tpar *TypeParam) int {
308 if x, ok := w.canon[tpar]; ok {
309 tpar = x
310 }
311
312 obj := tpar.Obj()
313
314 if idx, ok := w.nameIdx[obj]; ok {
315 return idx
316 }
317
318 if w.nameIdx == nil {
319 w.nameIdx = make(map[*TypeName]int)
320 }
321
322 idx := len(w.vertices)
323 w.vertices = append(w.vertices, monoVertex{obj: obj})
324 w.nameIdx[obj] = idx
325 return idx
326 }
327
328 func (w *monoGraph) addEdge(dst, src, weight int, pos syntax.Pos, typ Type) {
329
330 w.edges = append(w.edges, monoEdge{
331 dst: dst,
332 src: src,
333 weight: weight,
334
335 pos: pos,
336 typ: typ,
337 })
338 }
339
View as plain text