1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 )
12
13 type substMap map[*TypeParam]Type
14
15
16
17 func makeSubstMap(tpars []*TypeParam, targs []Type) substMap {
18 assert(len(tpars) == len(targs))
19 proj := make(substMap, len(tpars))
20 for i, tpar := range tpars {
21 proj[tpar] = targs[i]
22 }
23 return proj
24 }
25
26
27
28 func makeRenameMap(from, to []*TypeParam) substMap {
29 assert(len(from) == len(to))
30 proj := make(substMap, len(from))
31 for i, tpar := range from {
32 proj[tpar] = to[i]
33 }
34 return proj
35 }
36
37 func (m substMap) empty() bool {
38 return len(m) == 0
39 }
40
41 func (m substMap) lookup(tpar *TypeParam) Type {
42 if t := m[tpar]; t != nil {
43 return t
44 }
45 return tpar
46 }
47
48
49
50
51
52
53
54
55 func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, expanding *Named, ctxt *Context) Type {
56 assert(expanding != nil || ctxt != nil)
57
58 if smap.empty() {
59 return typ
60 }
61
62
63 switch t := typ.(type) {
64 case *Basic:
65 return typ
66 case *TypeParam:
67 return smap.lookup(t)
68 }
69
70
71 subst := subster{
72 pos: pos,
73 smap: smap,
74 check: check,
75 expanding: expanding,
76 ctxt: ctxt,
77 }
78 return subst.typ(typ)
79 }
80
81 type subster struct {
82 pos syntax.Pos
83 smap substMap
84 check *Checker
85 expanding *Named
86 ctxt *Context
87 }
88
89 func (subst *subster) typ(typ Type) Type {
90 switch t := typ.(type) {
91 case nil:
92
93 panic("nil typ")
94
95 case *Basic:
96
97
98 case *Alias:
99 rhs := subst.typ(t.fromRHS)
100 if rhs != t.fromRHS {
101
102
103
104
105
106 panic("unreachable for unparameterized aliases")
107
108 }
109
110 case *Array:
111 elem := subst.typOrNil(t.elem)
112 if elem != t.elem {
113 return &Array{len: t.len, elem: elem}
114 }
115
116 case *Slice:
117 elem := subst.typOrNil(t.elem)
118 if elem != t.elem {
119 return &Slice{elem: elem}
120 }
121
122 case *Struct:
123 if fields, copied := subst.varList(t.fields); copied {
124 s := &Struct{fields: fields, tags: t.tags}
125 s.markComplete()
126 return s
127 }
128
129 case *Pointer:
130 base := subst.typ(t.base)
131 if base != t.base {
132 return &Pointer{base: base}
133 }
134
135 case *Tuple:
136 return subst.tuple(t)
137
138 case *Signature:
139
140
141
142
143
144
145
146
147
148
149
150
151
152 recv := t.recv
153
154 params := subst.tuple(t.params)
155 results := subst.tuple(t.results)
156 if params != t.params || results != t.results {
157 return &Signature{
158 rparams: t.rparams,
159
160 tparams: t.tparams,
161
162 recv: recv,
163 params: params,
164 results: results,
165 variadic: t.variadic,
166 }
167 }
168
169 case *Union:
170 terms, copied := subst.termlist(t.terms)
171 if copied {
172
173
174
175 return &Union{terms}
176 }
177
178 case *Interface:
179 methods, mcopied := subst.funcList(t.methods)
180 embeddeds, ecopied := subst.typeList(t.embeddeds)
181 if mcopied || ecopied {
182 iface := subst.check.newInterface()
183 iface.embeddeds = embeddeds
184 iface.embedPos = t.embedPos
185 iface.implicit = t.implicit
186 assert(t.complete)
187 iface.complete = t.complete
188
189
190
191
192
193
194
195
196
197
198
199
200
201 iface.methods, _ = replaceRecvType(methods, t, iface)
202
203
204 if subst.check == nil {
205 iface.typeSet()
206 }
207 return iface
208 }
209
210 case *Map:
211 key := subst.typ(t.key)
212 elem := subst.typ(t.elem)
213 if key != t.key || elem != t.elem {
214 return &Map{key: key, elem: elem}
215 }
216
217 case *Chan:
218 elem := subst.typ(t.elem)
219 if elem != t.elem {
220 return &Chan{dir: t.dir, elem: elem}
221 }
222
223 case *Named:
224
225 dump := func(string, ...interface{}) {}
226 if subst.check != nil && subst.check.conf.Trace {
227 subst.check.indent++
228 defer func() {
229 subst.check.indent--
230 }()
231 dump = func(format string, args ...interface{}) {
232 subst.check.trace(subst.pos, format, args...)
233 }
234 }
235
236
237
238
239
240
241 orig := t.Origin()
242 n := orig.TypeParams().Len()
243 if n == 0 {
244 dump(">>> %s is not parameterized", t)
245 return t
246 }
247
248 var newTArgs []Type
249 if t.TypeArgs().Len() != n {
250 return Typ[Invalid]
251 }
252
253
254 dump(">>> %s already instantiated", t)
255
256
257
258 for i, targ := range t.TypeArgs().list() {
259 dump(">>> %d targ = %s", i, targ)
260 new_targ := subst.typ(targ)
261 if new_targ != targ {
262 dump(">>> substituted %d targ %s => %s", i, targ, new_targ)
263 if newTArgs == nil {
264 newTArgs = make([]Type, n)
265 copy(newTArgs, t.TypeArgs().list())
266 }
267 newTArgs[i] = new_targ
268 }
269 }
270
271 if newTArgs == nil {
272 dump(">>> nothing to substitute in %s", t)
273 return t
274 }
275
276
277
278
279
280 return subst.check.instance(subst.pos, orig, newTArgs, subst.expanding, subst.ctxt)
281
282 case *TypeParam:
283 return subst.smap.lookup(t)
284
285 default:
286 unreachable()
287 }
288
289 return typ
290 }
291
292
293
294
295 func (subst *subster) typOrNil(typ Type) Type {
296 if typ == nil {
297 return Typ[Invalid]
298 }
299 return subst.typ(typ)
300 }
301
302 func (subst *subster) var_(v *Var) *Var {
303 if v != nil {
304 if typ := subst.typ(v.typ); typ != v.typ {
305 return substVar(v, typ)
306 }
307 }
308 return v
309 }
310
311 func substVar(v *Var, typ Type) *Var {
312 copy := *v
313 copy.typ = typ
314 copy.origin = v.Origin()
315 return ©
316 }
317
318 func (subst *subster) tuple(t *Tuple) *Tuple {
319 if t != nil {
320 if vars, copied := subst.varList(t.vars); copied {
321 return &Tuple{vars: vars}
322 }
323 }
324 return t
325 }
326
327 func (subst *subster) varList(in []*Var) (out []*Var, copied bool) {
328 out = in
329 for i, v := range in {
330 if w := subst.var_(v); w != v {
331 if !copied {
332
333
334 new := make([]*Var, len(in))
335 copy(new, out)
336 out = new
337 copied = true
338 }
339 out[i] = w
340 }
341 }
342 return
343 }
344
345 func (subst *subster) func_(f *Func) *Func {
346 if f != nil {
347 if typ := subst.typ(f.typ); typ != f.typ {
348 return substFunc(f, typ)
349 }
350 }
351 return f
352 }
353
354 func substFunc(f *Func, typ Type) *Func {
355 copy := *f
356 copy.typ = typ
357 copy.origin = f.Origin()
358 return ©
359 }
360
361 func (subst *subster) funcList(in []*Func) (out []*Func, copied bool) {
362 out = in
363 for i, f := range in {
364 if g := subst.func_(f); g != f {
365 if !copied {
366
367
368 new := make([]*Func, len(in))
369 copy(new, out)
370 out = new
371 copied = true
372 }
373 out[i] = g
374 }
375 }
376 return
377 }
378
379 func (subst *subster) typeList(in []Type) (out []Type, copied bool) {
380 out = in
381 for i, t := range in {
382 if u := subst.typ(t); u != t {
383 if !copied {
384
385
386 new := make([]Type, len(in))
387 copy(new, out)
388 out = new
389 copied = true
390 }
391 out[i] = u
392 }
393 }
394 return
395 }
396
397 func (subst *subster) termlist(in []*Term) (out []*Term, copied bool) {
398 out = in
399 for i, t := range in {
400 if u := subst.typ(t.typ); u != t.typ {
401 if !copied {
402
403
404 new := make([]*Term, len(in))
405 copy(new, out)
406 out = new
407 copied = true
408 }
409 out[i] = NewTerm(t.tilde, u)
410 }
411 }
412 return
413 }
414
415
416
417
418
419
420
421 func replaceRecvType(in []*Func, old, new Type) (out []*Func, copied bool) {
422 out = in
423 for i, method := range in {
424 sig := method.Type().(*Signature)
425 if sig.recv != nil && sig.recv.Type() == old {
426 if !copied {
427
428
429
430 out = make([]*Func, len(in))
431 copy(out, in)
432 copied = true
433 }
434 newsig := *sig
435 newsig.recv = substVar(sig.recv, new)
436 out[i] = substFunc(method, &newsig)
437 }
438 }
439 return
440 }
441
View as plain text