Source file
src/go/types/mono.go
1
2
3
4
5 package types
6
7 import (
8 "go/ast"
9 "go/token"
10 . "internal/types/errors"
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
52 type monoGraph struct {
53 vertices []monoVertex
54 edges []monoEdge
55
56
57
58 canon map[*TypeParam]*TypeParam
59
60
61
62 nameIdx map[*TypeName]int
63 }
64
65 type monoVertex struct {
66 weight int
67 pre int
68 len int
69
70
71
72 obj *TypeName
73 }
74
75 type monoEdge struct {
76 dst, src int
77 weight int
78
79 pos token.Pos
80 typ Type
81 }
82
83 func (check *Checker) monomorph() {
84
85
86
87
88
89
90 again := true
91 for again {
92 again = false
93
94 for i, edge := range check.mono.edges {
95 src := &check.mono.vertices[edge.src]
96 dst := &check.mono.vertices[edge.dst]
97
98
99
100 w := src.weight + edge.weight
101 if w <= dst.weight {
102 continue
103 }
104
105 dst.pre = i
106 dst.len = src.len + 1
107 if dst.len == len(check.mono.vertices) {
108 check.reportInstanceLoop(edge.dst)
109 return
110 }
111
112 dst.weight = w
113 again = true
114 }
115 }
116 }
117
118 func (check *Checker) reportInstanceLoop(v int) {
119 var stack []int
120 seen := make([]bool, len(check.mono.vertices))
121
122
123
124
125
126 for !seen[v] {
127 stack = append(stack, v)
128 seen[v] = true
129 v = check.mono.edges[check.mono.vertices[v].pre].src
130 }
131
132
133
134
135 for stack[0] != v {
136 stack = stack[1:]
137 }
138
139
140
141 obj0 := check.mono.vertices[v].obj
142 check.error(obj0, InvalidInstanceCycle, "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 check.errorf(atPos(edge.pos), InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf))
154 case *TypeParam:
155 check.errorf(atPos(edge.pos), InvalidInstanceCycle, "\t%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf))
156 }
157 }
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 token.Pos, tparams []*TypeParam, targs []Type, xlist []ast.Expr) {
172 for i, tpar := range tparams {
173 pos := pos
174 if i < len(xlist) {
175 pos = xlist[i].Pos()
176 }
177 w.assign(pkg, pos, tpar, targs[i])
178 }
179 }
180
181
182 func (w *monoGraph) assign(pkg *Package, pos token.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 := Unalias(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() && cmpPos(elem.Pos(), 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 token.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