1 | // Copyright 2021 The Go Authors. All rights reserved. |
---|---|
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. |
4 | |
5 | // Derived from go/internal/gcimporter/ureader.go |
6 | |
7 | //go:build go1.18 |
8 | // +build go1.18 |
9 | |
10 | package gcimporter |
11 | |
12 | import ( |
13 | "go/token" |
14 | "go/types" |
15 | "strings" |
16 | |
17 | "golang.org/x/tools/internal/pkgbits" |
18 | ) |
19 | |
20 | // A pkgReader holds the shared state for reading a unified IR package |
21 | // description. |
22 | type pkgReader struct { |
23 | pkgbits.PkgDecoder |
24 | |
25 | fake fakeFileSet |
26 | |
27 | ctxt *types.Context |
28 | imports map[string]*types.Package // previously imported packages, indexed by path |
29 | |
30 | // lazily initialized arrays corresponding to the unified IR |
31 | // PosBase, Pkg, and Type sections, respectively. |
32 | posBases []string // position bases (i.e., file names) |
33 | pkgs []*types.Package |
34 | typs []types.Type |
35 | |
36 | // laterFns holds functions that need to be invoked at the end of |
37 | // import reading. |
38 | laterFns []func() |
39 | // laterFors is used in case of 'type A B' to ensure that B is processed before A. |
40 | laterFors map[types.Type]int |
41 | |
42 | // ifaces holds a list of constructed Interfaces, which need to have |
43 | // Complete called after importing is done. |
44 | ifaces []*types.Interface |
45 | } |
46 | |
47 | // later adds a function to be invoked at the end of import reading. |
48 | func (pr *pkgReader) later(fn func()) { |
49 | pr.laterFns = append(pr.laterFns, fn) |
50 | } |
51 | |
52 | // See cmd/compile/internal/noder.derivedInfo. |
53 | type derivedInfo struct { |
54 | idx pkgbits.Index |
55 | needed bool |
56 | } |
57 | |
58 | // See cmd/compile/internal/noder.typeInfo. |
59 | type typeInfo struct { |
60 | idx pkgbits.Index |
61 | derived bool |
62 | } |
63 | |
64 | func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { |
65 | s := string(data) |
66 | s = s[:strings.LastIndex(s, "\n$$\n")] |
67 | input := pkgbits.NewPkgDecoder(path, s) |
68 | pkg = readUnifiedPackage(fset, nil, imports, input) |
69 | return |
70 | } |
71 | |
72 | // laterFor adds a function to be invoked at the end of import reading, and records the type that function is finishing. |
73 | func (pr *pkgReader) laterFor(t types.Type, fn func()) { |
74 | if pr.laterFors == nil { |
75 | pr.laterFors = make(map[types.Type]int) |
76 | } |
77 | pr.laterFors[t] = len(pr.laterFns) |
78 | pr.laterFns = append(pr.laterFns, fn) |
79 | } |
80 | |
81 | // readUnifiedPackage reads a package description from the given |
82 | // unified IR export data decoder. |
83 | func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package { |
84 | pr := pkgReader{ |
85 | PkgDecoder: input, |
86 | |
87 | fake: fakeFileSet{ |
88 | fset: fset, |
89 | files: make(map[string]*fileInfo), |
90 | }, |
91 | |
92 | ctxt: ctxt, |
93 | imports: imports, |
94 | |
95 | posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)), |
96 | pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)), |
97 | typs: make([]types.Type, input.NumElems(pkgbits.RelocType)), |
98 | } |
99 | defer pr.fake.setLines() |
100 | |
101 | r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) |
102 | pkg := r.pkg() |
103 | r.Bool() // has init |
104 | |
105 | for i, n := 0, r.Len(); i < n; i++ { |
106 | // As if r.obj(), but avoiding the Scope.Lookup call, |
107 | // to avoid eager loading of imports. |
108 | r.Sync(pkgbits.SyncObject) |
109 | assert(!r.Bool()) |
110 | r.p.objIdx(r.Reloc(pkgbits.RelocObj)) |
111 | assert(r.Len() == 0) |
112 | } |
113 | |
114 | r.Sync(pkgbits.SyncEOF) |
115 | |
116 | for _, fn := range pr.laterFns { |
117 | fn() |
118 | } |
119 | |
120 | for _, iface := range pr.ifaces { |
121 | iface.Complete() |
122 | } |
123 | |
124 | pkg.MarkComplete() |
125 | return pkg |
126 | } |
127 | |
128 | // A reader holds the state for reading a single unified IR element |
129 | // within a package. |
130 | type reader struct { |
131 | pkgbits.Decoder |
132 | |
133 | p *pkgReader |
134 | |
135 | dict *readerDict |
136 | } |
137 | |
138 | // A readerDict holds the state for type parameters that parameterize |
139 | // the current unified IR element. |
140 | type readerDict struct { |
141 | // bounds is a slice of typeInfos corresponding to the underlying |
142 | // bounds of the element's type parameters. |
143 | bounds []typeInfo |
144 | |
145 | // tparams is a slice of the constructed TypeParams for the element. |
146 | tparams []*types.TypeParam |
147 | |
148 | // devived is a slice of types derived from tparams, which may be |
149 | // instantiated while reading the current element. |
150 | derived []derivedInfo |
151 | derivedTypes []types.Type // lazily instantiated from derived |
152 | } |
153 | |
154 | func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { |
155 | return &reader{ |
156 | Decoder: pr.NewDecoder(k, idx, marker), |
157 | p: pr, |
158 | } |
159 | } |
160 | |
161 | func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { |
162 | return &reader{ |
163 | Decoder: pr.TempDecoder(k, idx, marker), |
164 | p: pr, |
165 | } |
166 | } |
167 | |
168 | func (pr *pkgReader) retireReader(r *reader) { |
169 | pr.RetireDecoder(&r.Decoder) |
170 | } |
171 | |
172 | // @@@ Positions |
173 | |
174 | func (r *reader) pos() token.Pos { |
175 | r.Sync(pkgbits.SyncPos) |
176 | if !r.Bool() { |
177 | return token.NoPos |
178 | } |
179 | |
180 | // TODO(mdempsky): Delta encoding. |
181 | posBase := r.posBase() |
182 | line := r.Uint() |
183 | col := r.Uint() |
184 | return r.p.fake.pos(posBase, int(line), int(col)) |
185 | } |
186 | |
187 | func (r *reader) posBase() string { |
188 | return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase)) |
189 | } |
190 | |
191 | func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string { |
192 | if b := pr.posBases[idx]; b != "" { |
193 | return b |
194 | } |
195 | |
196 | var filename string |
197 | { |
198 | r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) |
199 | |
200 | // Within types2, position bases have a lot more details (e.g., |
201 | // keeping track of where //line directives appeared exactly). |
202 | // |
203 | // For go/types, we just track the file name. |
204 | |
205 | filename = r.String() |
206 | |
207 | if r.Bool() { // file base |
208 | // Was: "b = token.NewTrimmedFileBase(filename, true)" |
209 | } else { // line base |
210 | pos := r.pos() |
211 | line := r.Uint() |
212 | col := r.Uint() |
213 | |
214 | // Was: "b = token.NewLineBase(pos, filename, true, line, col)" |
215 | _, _, _ = pos, line, col |
216 | } |
217 | pr.retireReader(r) |
218 | } |
219 | b := filename |
220 | pr.posBases[idx] = b |
221 | return b |
222 | } |
223 | |
224 | // @@@ Packages |
225 | |
226 | func (r *reader) pkg() *types.Package { |
227 | r.Sync(pkgbits.SyncPkg) |
228 | return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) |
229 | } |
230 | |
231 | func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package { |
232 | // TODO(mdempsky): Consider using some non-nil pointer to indicate |
233 | // the universe scope, so we don't need to keep re-reading it. |
234 | if pkg := pr.pkgs[idx]; pkg != nil { |
235 | return pkg |
236 | } |
237 | |
238 | pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() |
239 | pr.pkgs[idx] = pkg |
240 | return pkg |
241 | } |
242 | |
243 | func (r *reader) doPkg() *types.Package { |
244 | path := r.String() |
245 | switch path { |
246 | case "": |
247 | path = r.p.PkgPath() |
248 | case "builtin": |
249 | return nil // universe |
250 | case "unsafe": |
251 | return types.Unsafe |
252 | } |
253 | |
254 | if pkg := r.p.imports[path]; pkg != nil { |
255 | return pkg |
256 | } |
257 | |
258 | name := r.String() |
259 | |
260 | pkg := types.NewPackage(path, name) |
261 | r.p.imports[path] = pkg |
262 | |
263 | imports := make([]*types.Package, r.Len()) |
264 | for i := range imports { |
265 | imports[i] = r.pkg() |
266 | } |
267 | pkg.SetImports(flattenImports(imports)) |
268 | |
269 | return pkg |
270 | } |
271 | |
272 | // flattenImports returns the transitive closure of all imported |
273 | // packages rooted from pkgs. |
274 | func flattenImports(pkgs []*types.Package) []*types.Package { |
275 | var res []*types.Package |
276 | seen := make(map[*types.Package]struct{}) |
277 | for _, pkg := range pkgs { |
278 | if _, ok := seen[pkg]; ok { |
279 | continue |
280 | } |
281 | seen[pkg] = struct{}{} |
282 | res = append(res, pkg) |
283 | |
284 | // pkg.Imports() is already flattened. |
285 | for _, pkg := range pkg.Imports() { |
286 | if _, ok := seen[pkg]; ok { |
287 | continue |
288 | } |
289 | seen[pkg] = struct{}{} |
290 | res = append(res, pkg) |
291 | } |
292 | } |
293 | return res |
294 | } |
295 | |
296 | // @@@ Types |
297 | |
298 | func (r *reader) typ() types.Type { |
299 | return r.p.typIdx(r.typInfo(), r.dict) |
300 | } |
301 | |
302 | func (r *reader) typInfo() typeInfo { |
303 | r.Sync(pkgbits.SyncType) |
304 | if r.Bool() { |
305 | return typeInfo{idx: pkgbits.Index(r.Len()), derived: true} |
306 | } |
307 | return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} |
308 | } |
309 | |
310 | func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type { |
311 | idx := info.idx |
312 | var where *types.Type |
313 | if info.derived { |
314 | where = &dict.derivedTypes[idx] |
315 | idx = dict.derived[idx].idx |
316 | } else { |
317 | where = &pr.typs[idx] |
318 | } |
319 | |
320 | if typ := *where; typ != nil { |
321 | return typ |
322 | } |
323 | |
324 | var typ types.Type |
325 | { |
326 | r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) |
327 | r.dict = dict |
328 | |
329 | typ = r.doTyp() |
330 | assert(typ != nil) |
331 | pr.retireReader(r) |
332 | } |
333 | // See comment in pkgReader.typIdx explaining how this happens. |
334 | if prev := *where; prev != nil { |
335 | return prev |
336 | } |
337 | |
338 | *where = typ |
339 | return typ |
340 | } |
341 | |
342 | func (r *reader) doTyp() (res types.Type) { |
343 | switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag { |
344 | default: |
345 | errorf("unhandled type tag: %v", tag) |
346 | panic("unreachable") |
347 | |
348 | case pkgbits.TypeBasic: |
349 | return types.Typ[r.Len()] |
350 | |
351 | case pkgbits.TypeNamed: |
352 | obj, targs := r.obj() |
353 | name := obj.(*types.TypeName) |
354 | if len(targs) != 0 { |
355 | t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false) |
356 | return t |
357 | } |
358 | return name.Type() |
359 | |
360 | case pkgbits.TypeTypeParam: |
361 | return r.dict.tparams[r.Len()] |
362 | |
363 | case pkgbits.TypeArray: |
364 | len := int64(r.Uint64()) |
365 | return types.NewArray(r.typ(), len) |
366 | case pkgbits.TypeChan: |
367 | dir := types.ChanDir(r.Len()) |
368 | return types.NewChan(dir, r.typ()) |
369 | case pkgbits.TypeMap: |
370 | return types.NewMap(r.typ(), r.typ()) |
371 | case pkgbits.TypePointer: |
372 | return types.NewPointer(r.typ()) |
373 | case pkgbits.TypeSignature: |
374 | return r.signature(nil, nil, nil) |
375 | case pkgbits.TypeSlice: |
376 | return types.NewSlice(r.typ()) |
377 | case pkgbits.TypeStruct: |
378 | return r.structType() |
379 | case pkgbits.TypeInterface: |
380 | return r.interfaceType() |
381 | case pkgbits.TypeUnion: |
382 | return r.unionType() |
383 | } |
384 | } |
385 | |
386 | func (r *reader) structType() *types.Struct { |
387 | fields := make([]*types.Var, r.Len()) |
388 | var tags []string |
389 | for i := range fields { |
390 | pos := r.pos() |
391 | pkg, name := r.selector() |
392 | ftyp := r.typ() |
393 | tag := r.String() |
394 | embedded := r.Bool() |
395 | |
396 | fields[i] = types.NewField(pos, pkg, name, ftyp, embedded) |
397 | if tag != "" { |
398 | for len(tags) < i { |
399 | tags = append(tags, "") |
400 | } |
401 | tags = append(tags, tag) |
402 | } |
403 | } |
404 | return types.NewStruct(fields, tags) |
405 | } |
406 | |
407 | func (r *reader) unionType() *types.Union { |
408 | terms := make([]*types.Term, r.Len()) |
409 | for i := range terms { |
410 | terms[i] = types.NewTerm(r.Bool(), r.typ()) |
411 | } |
412 | return types.NewUnion(terms) |
413 | } |
414 | |
415 | func (r *reader) interfaceType() *types.Interface { |
416 | methods := make([]*types.Func, r.Len()) |
417 | embeddeds := make([]types.Type, r.Len()) |
418 | implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool() |
419 | |
420 | for i := range methods { |
421 | pos := r.pos() |
422 | pkg, name := r.selector() |
423 | mtyp := r.signature(nil, nil, nil) |
424 | methods[i] = types.NewFunc(pos, pkg, name, mtyp) |
425 | } |
426 | |
427 | for i := range embeddeds { |
428 | embeddeds[i] = r.typ() |
429 | } |
430 | |
431 | iface := types.NewInterfaceType(methods, embeddeds) |
432 | if implicit { |
433 | iface.MarkImplicit() |
434 | } |
435 | |
436 | // We need to call iface.Complete(), but if there are any embedded |
437 | // defined types, then we may not have set their underlying |
438 | // interface type yet. So we need to defer calling Complete until |
439 | // after we've called SetUnderlying everywhere. |
440 | // |
441 | // TODO(mdempsky): After CL 424876 lands, it should be safe to call |
442 | // iface.Complete() immediately. |
443 | r.p.ifaces = append(r.p.ifaces, iface) |
444 | |
445 | return iface |
446 | } |
447 | |
448 | func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature { |
449 | r.Sync(pkgbits.SyncSignature) |
450 | |
451 | params := r.params() |
452 | results := r.params() |
453 | variadic := r.Bool() |
454 | |
455 | return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic) |
456 | } |
457 | |
458 | func (r *reader) params() *types.Tuple { |
459 | r.Sync(pkgbits.SyncParams) |
460 | |
461 | params := make([]*types.Var, r.Len()) |
462 | for i := range params { |
463 | params[i] = r.param() |
464 | } |
465 | |
466 | return types.NewTuple(params...) |
467 | } |
468 | |
469 | func (r *reader) param() *types.Var { |
470 | r.Sync(pkgbits.SyncParam) |
471 | |
472 | pos := r.pos() |
473 | pkg, name := r.localIdent() |
474 | typ := r.typ() |
475 | |
476 | return types.NewParam(pos, pkg, name, typ) |
477 | } |
478 | |
479 | // @@@ Objects |
480 | |
481 | func (r *reader) obj() (types.Object, []types.Type) { |
482 | r.Sync(pkgbits.SyncObject) |
483 | |
484 | assert(!r.Bool()) |
485 | |
486 | pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj)) |
487 | obj := pkgScope(pkg).Lookup(name) |
488 | |
489 | targs := make([]types.Type, r.Len()) |
490 | for i := range targs { |
491 | targs[i] = r.typ() |
492 | } |
493 | |
494 | return obj, targs |
495 | } |
496 | |
497 | func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { |
498 | |
499 | var objPkg *types.Package |
500 | var objName string |
501 | var tag pkgbits.CodeObj |
502 | { |
503 | rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) |
504 | |
505 | objPkg, objName = rname.qualifiedIdent() |
506 | assert(objName != "") |
507 | |
508 | tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) |
509 | pr.retireReader(rname) |
510 | } |
511 | |
512 | if tag == pkgbits.ObjStub { |
513 | assert(objPkg == nil || objPkg == types.Unsafe) |
514 | return objPkg, objName |
515 | } |
516 | |
517 | // Ignore local types promoted to global scope (#55110). |
518 | if _, suffix := splitVargenSuffix(objName); suffix != "" { |
519 | return objPkg, objName |
520 | } |
521 | |
522 | if objPkg.Scope().Lookup(objName) == nil { |
523 | dict := pr.objDictIdx(idx) |
524 | |
525 | r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) |
526 | r.dict = dict |
527 | |
528 | declare := func(obj types.Object) { |
529 | objPkg.Scope().Insert(obj) |
530 | } |
531 | |
532 | switch tag { |
533 | default: |
534 | panic("weird") |
535 | |
536 | case pkgbits.ObjAlias: |
537 | pos := r.pos() |
538 | typ := r.typ() |
539 | declare(types.NewTypeName(pos, objPkg, objName, typ)) |
540 | |
541 | case pkgbits.ObjConst: |
542 | pos := r.pos() |
543 | typ := r.typ() |
544 | val := r.Value() |
545 | declare(types.NewConst(pos, objPkg, objName, typ, val)) |
546 | |
547 | case pkgbits.ObjFunc: |
548 | pos := r.pos() |
549 | tparams := r.typeParamNames() |
550 | sig := r.signature(nil, nil, tparams) |
551 | declare(types.NewFunc(pos, objPkg, objName, sig)) |
552 | |
553 | case pkgbits.ObjType: |
554 | pos := r.pos() |
555 | |
556 | obj := types.NewTypeName(pos, objPkg, objName, nil) |
557 | named := types.NewNamed(obj, nil, nil) |
558 | declare(obj) |
559 | |
560 | named.SetTypeParams(r.typeParamNames()) |
561 | |
562 | setUnderlying := func(underlying types.Type) { |
563 | // If the underlying type is an interface, we need to |
564 | // duplicate its methods so we can replace the receiver |
565 | // parameter's type (#49906). |
566 | if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { |
567 | methods := make([]*types.Func, iface.NumExplicitMethods()) |
568 | for i := range methods { |
569 | fn := iface.ExplicitMethod(i) |
570 | sig := fn.Type().(*types.Signature) |
571 | |
572 | recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named) |
573 | methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic())) |
574 | } |
575 | |
576 | embeds := make([]types.Type, iface.NumEmbeddeds()) |
577 | for i := range embeds { |
578 | embeds[i] = iface.EmbeddedType(i) |
579 | } |
580 | |
581 | newIface := types.NewInterfaceType(methods, embeds) |
582 | r.p.ifaces = append(r.p.ifaces, newIface) |
583 | underlying = newIface |
584 | } |
585 | |
586 | named.SetUnderlying(underlying) |
587 | } |
588 | |
589 | // Since go.dev/cl/455279, we can assume rhs.Underlying() will |
590 | // always be non-nil. However, to temporarily support users of |
591 | // older snapshot releases, we continue to fallback to the old |
592 | // behavior for now. |
593 | // |
594 | // TODO(mdempsky): Remove fallback code and simplify after |
595 | // allowing time for snapshot users to upgrade. |
596 | rhs := r.typ() |
597 | if underlying := rhs.Underlying(); underlying != nil { |
598 | setUnderlying(underlying) |
599 | } else { |
600 | pk := r.p |
601 | pk.laterFor(named, func() { |
602 | // First be sure that the rhs is initialized, if it needs to be initialized. |
603 | delete(pk.laterFors, named) // prevent cycles |
604 | if i, ok := pk.laterFors[rhs]; ok { |
605 | f := pk.laterFns[i] |
606 | pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op |
607 | f() // initialize RHS |
608 | } |
609 | setUnderlying(rhs.Underlying()) |
610 | }) |
611 | } |
612 | |
613 | for i, n := 0, r.Len(); i < n; i++ { |
614 | named.AddMethod(r.method()) |
615 | } |
616 | |
617 | case pkgbits.ObjVar: |
618 | pos := r.pos() |
619 | typ := r.typ() |
620 | declare(types.NewVar(pos, objPkg, objName, typ)) |
621 | } |
622 | } |
623 | |
624 | return objPkg, objName |
625 | } |
626 | |
627 | func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { |
628 | |
629 | var dict readerDict |
630 | |
631 | { |
632 | r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) |
633 | if implicits := r.Len(); implicits != 0 { |
634 | errorf("unexpected object with %v implicit type parameter(s)", implicits) |
635 | } |
636 | |
637 | dict.bounds = make([]typeInfo, r.Len()) |
638 | for i := range dict.bounds { |
639 | dict.bounds[i] = r.typInfo() |
640 | } |
641 | |
642 | dict.derived = make([]derivedInfo, r.Len()) |
643 | dict.derivedTypes = make([]types.Type, len(dict.derived)) |
644 | for i := range dict.derived { |
645 | dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} |
646 | } |
647 | |
648 | pr.retireReader(r) |
649 | } |
650 | // function references follow, but reader doesn't need those |
651 | |
652 | return &dict |
653 | } |
654 | |
655 | func (r *reader) typeParamNames() []*types.TypeParam { |
656 | r.Sync(pkgbits.SyncTypeParamNames) |
657 | |
658 | // Note: This code assumes it only processes objects without |
659 | // implement type parameters. This is currently fine, because |
660 | // reader is only used to read in exported declarations, which are |
661 | // always package scoped. |
662 | |
663 | if len(r.dict.bounds) == 0 { |
664 | return nil |
665 | } |
666 | |
667 | // Careful: Type parameter lists may have cycles. To allow for this, |
668 | // we construct the type parameter list in two passes: first we |
669 | // create all the TypeNames and TypeParams, then we construct and |
670 | // set the bound type. |
671 | |
672 | r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds)) |
673 | for i := range r.dict.bounds { |
674 | pos := r.pos() |
675 | pkg, name := r.localIdent() |
676 | |
677 | tname := types.NewTypeName(pos, pkg, name, nil) |
678 | r.dict.tparams[i] = types.NewTypeParam(tname, nil) |
679 | } |
680 | |
681 | typs := make([]types.Type, len(r.dict.bounds)) |
682 | for i, bound := range r.dict.bounds { |
683 | typs[i] = r.p.typIdx(bound, r.dict) |
684 | } |
685 | |
686 | // TODO(mdempsky): This is subtle, elaborate further. |
687 | // |
688 | // We have to save tparams outside of the closure, because |
689 | // typeParamNames() can be called multiple times with the same |
690 | // dictionary instance. |
691 | // |
692 | // Also, this needs to happen later to make sure SetUnderlying has |
693 | // been called. |
694 | // |
695 | // TODO(mdempsky): Is it safe to have a single "later" slice or do |
696 | // we need to have multiple passes? See comments on CL 386002 and |
697 | // go.dev/issue/52104. |
698 | tparams := r.dict.tparams |
699 | r.p.later(func() { |
700 | for i, typ := range typs { |
701 | tparams[i].SetConstraint(typ) |
702 | } |
703 | }) |
704 | |
705 | return r.dict.tparams |
706 | } |
707 | |
708 | func (r *reader) method() *types.Func { |
709 | r.Sync(pkgbits.SyncMethod) |
710 | pos := r.pos() |
711 | pkg, name := r.selector() |
712 | |
713 | rparams := r.typeParamNames() |
714 | sig := r.signature(r.param(), rparams, nil) |
715 | |
716 | _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. |
717 | return types.NewFunc(pos, pkg, name, sig) |
718 | } |
719 | |
720 | func (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) } |
721 | func (r *reader) localIdent() (*types.Package, string) { return r.ident(pkgbits.SyncLocalIdent) } |
722 | func (r *reader) selector() (*types.Package, string) { return r.ident(pkgbits.SyncSelector) } |
723 | |
724 | func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) { |
725 | r.Sync(marker) |
726 | return r.pkg(), r.String() |
727 | } |
728 | |
729 | // pkgScope returns pkg.Scope(). |
730 | // If pkg is nil, it returns types.Universe instead. |
731 | // |
732 | // TODO(mdempsky): Remove after x/tools can depend on Go 1.19. |
733 | func pkgScope(pkg *types.Package) *types.Scope { |
734 | if pkg != nil { |
735 | return pkg.Scope() |
736 | } |
737 | return types.Universe |
738 | } |
739 |
Members