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