1 | // Copyright 2018 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 | // Indexed package import. |
6 | // See cmd/compile/internal/gc/iexport.go for the export data format. |
7 | |
8 | // This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go. |
9 | |
10 | package gcimporter |
11 | |
12 | import ( |
13 | "bytes" |
14 | "encoding/binary" |
15 | "fmt" |
16 | "go/constant" |
17 | "go/token" |
18 | "go/types" |
19 | "io" |
20 | "math/big" |
21 | "sort" |
22 | "strings" |
23 | |
24 | "golang.org/x/tools/internal/typeparams" |
25 | ) |
26 | |
27 | type intReader struct { |
28 | *bytes.Reader |
29 | path string |
30 | } |
31 | |
32 | func (r *intReader) int64() int64 { |
33 | i, err := binary.ReadVarint(r.Reader) |
34 | if err != nil { |
35 | errorf("import %q: read varint error: %v", r.path, err) |
36 | } |
37 | return i |
38 | } |
39 | |
40 | func (r *intReader) uint64() uint64 { |
41 | i, err := binary.ReadUvarint(r.Reader) |
42 | if err != nil { |
43 | errorf("import %q: read varint error: %v", r.path, err) |
44 | } |
45 | return i |
46 | } |
47 | |
48 | // Keep this in sync with constants in iexport.go. |
49 | const ( |
50 | iexportVersionGo1_11 = 0 |
51 | iexportVersionPosCol = 1 |
52 | iexportVersionGo1_18 = 2 |
53 | iexportVersionGenerics = 2 |
54 | |
55 | iexportVersionCurrent = 2 |
56 | ) |
57 | |
58 | type ident struct { |
59 | pkg *types.Package |
60 | name string |
61 | } |
62 | |
63 | const predeclReserved = 32 |
64 | |
65 | type itag uint64 |
66 | |
67 | const ( |
68 | // Types |
69 | definedType itag = iota |
70 | pointerType |
71 | sliceType |
72 | arrayType |
73 | chanType |
74 | mapType |
75 | signatureType |
76 | structType |
77 | interfaceType |
78 | typeParamType |
79 | instanceType |
80 | unionType |
81 | ) |
82 | |
83 | // IImportData imports a package from the serialized package data |
84 | // and returns 0 and a reference to the package. |
85 | // If the export data version is not recognized or the format is otherwise |
86 | // compromised, an error is returned. |
87 | func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) { |
88 | pkgs, err := iimportCommon(fset, imports, data, false, path, nil) |
89 | if err != nil { |
90 | return 0, nil, err |
91 | } |
92 | return 0, pkgs[0], nil |
93 | } |
94 | |
95 | // IImportBundle imports a set of packages from the serialized package bundle. |
96 | func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) { |
97 | return iimportCommon(fset, imports, data, true, "", nil) |
98 | } |
99 | |
100 | func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) { |
101 | const currentVersion = iexportVersionCurrent |
102 | version := int64(-1) |
103 | if !debug { |
104 | defer func() { |
105 | if e := recover(); e != nil { |
106 | if bundle { |
107 | err = fmt.Errorf("%v", e) |
108 | } else if version > currentVersion { |
109 | err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) |
110 | } else { |
111 | err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) |
112 | } |
113 | } |
114 | }() |
115 | } |
116 | |
117 | r := &intReader{bytes.NewReader(data), path} |
118 | |
119 | if bundle { |
120 | bundleVersion := r.uint64() |
121 | switch bundleVersion { |
122 | case bundleVersion: |
123 | default: |
124 | errorf("unknown bundle format version %d", bundleVersion) |
125 | } |
126 | } |
127 | |
128 | version = int64(r.uint64()) |
129 | switch version { |
130 | case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: |
131 | default: |
132 | if version > iexportVersionGo1_18 { |
133 | errorf("unstable iexport format version %d, just rebuild compiler and std library", version) |
134 | } else { |
135 | errorf("unknown iexport format version %d", version) |
136 | } |
137 | } |
138 | |
139 | sLen := int64(r.uint64()) |
140 | dLen := int64(r.uint64()) |
141 | |
142 | whence, _ := r.Seek(0, io.SeekCurrent) |
143 | stringData := data[whence : whence+sLen] |
144 | declData := data[whence+sLen : whence+sLen+dLen] |
145 | r.Seek(sLen+dLen, io.SeekCurrent) |
146 | |
147 | p := iimporter{ |
148 | version: int(version), |
149 | ipath: path, |
150 | insert: insert, |
151 | |
152 | stringData: stringData, |
153 | stringCache: make(map[uint64]string), |
154 | pkgCache: make(map[uint64]*types.Package), |
155 | |
156 | declData: declData, |
157 | pkgIndex: make(map[*types.Package]map[string]uint64), |
158 | typCache: make(map[uint64]types.Type), |
159 | // Separate map for typeparams, keyed by their package and unique |
160 | // name. |
161 | tparamIndex: make(map[ident]types.Type), |
162 | |
163 | fake: fakeFileSet{ |
164 | fset: fset, |
165 | files: make(map[string]*fileInfo), |
166 | }, |
167 | } |
168 | defer p.fake.setLines() // set lines for files in fset |
169 | |
170 | for i, pt := range predeclared() { |
171 | p.typCache[uint64(i)] = pt |
172 | } |
173 | |
174 | pkgList := make([]*types.Package, r.uint64()) |
175 | for i := range pkgList { |
176 | pkgPathOff := r.uint64() |
177 | pkgPath := p.stringAt(pkgPathOff) |
178 | pkgName := p.stringAt(r.uint64()) |
179 | _ = r.uint64() // package height; unused by go/types |
180 | |
181 | if pkgPath == "" { |
182 | pkgPath = path |
183 | } |
184 | pkg := imports[pkgPath] |
185 | if pkg == nil { |
186 | pkg = types.NewPackage(pkgPath, pkgName) |
187 | imports[pkgPath] = pkg |
188 | } else if pkg.Name() != pkgName { |
189 | errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) |
190 | } |
191 | if i == 0 && !bundle { |
192 | p.localpkg = pkg |
193 | } |
194 | |
195 | p.pkgCache[pkgPathOff] = pkg |
196 | |
197 | // Read index for package. |
198 | nameIndex := make(map[string]uint64) |
199 | nSyms := r.uint64() |
200 | // In shallow mode we don't expect an index for other packages. |
201 | assert(nSyms == 0 || p.localpkg == pkg || p.insert == nil) |
202 | for ; nSyms > 0; nSyms-- { |
203 | name := p.stringAt(r.uint64()) |
204 | nameIndex[name] = r.uint64() |
205 | } |
206 | |
207 | p.pkgIndex[pkg] = nameIndex |
208 | pkgList[i] = pkg |
209 | } |
210 | |
211 | if bundle { |
212 | pkgs = make([]*types.Package, r.uint64()) |
213 | for i := range pkgs { |
214 | pkg := p.pkgAt(r.uint64()) |
215 | imps := make([]*types.Package, r.uint64()) |
216 | for j := range imps { |
217 | imps[j] = p.pkgAt(r.uint64()) |
218 | } |
219 | pkg.SetImports(imps) |
220 | pkgs[i] = pkg |
221 | } |
222 | } else { |
223 | if len(pkgList) == 0 { |
224 | errorf("no packages found for %s", path) |
225 | panic("unreachable") |
226 | } |
227 | pkgs = pkgList[:1] |
228 | |
229 | // record all referenced packages as imports |
230 | list := append(([]*types.Package)(nil), pkgList[1:]...) |
231 | sort.Sort(byPath(list)) |
232 | pkgs[0].SetImports(list) |
233 | } |
234 | |
235 | for _, pkg := range pkgs { |
236 | if pkg.Complete() { |
237 | continue |
238 | } |
239 | |
240 | names := make([]string, 0, len(p.pkgIndex[pkg])) |
241 | for name := range p.pkgIndex[pkg] { |
242 | names = append(names, name) |
243 | } |
244 | sort.Strings(names) |
245 | for _, name := range names { |
246 | p.doDecl(pkg, name) |
247 | } |
248 | |
249 | // package was imported completely and without errors |
250 | pkg.MarkComplete() |
251 | } |
252 | |
253 | // SetConstraint can't be called if the constraint type is not yet complete. |
254 | // When type params are created in the 'P' case of (*importReader).obj(), |
255 | // the associated constraint type may not be complete due to recursion. |
256 | // Therefore, we defer calling SetConstraint there, and call it here instead |
257 | // after all types are complete. |
258 | for _, d := range p.later { |
259 | typeparams.SetTypeParamConstraint(d.t, d.constraint) |
260 | } |
261 | |
262 | for _, typ := range p.interfaceList { |
263 | typ.Complete() |
264 | } |
265 | |
266 | return pkgs, nil |
267 | } |
268 | |
269 | type setConstraintArgs struct { |
270 | t *typeparams.TypeParam |
271 | constraint types.Type |
272 | } |
273 | |
274 | type iimporter struct { |
275 | version int |
276 | ipath string |
277 | |
278 | localpkg *types.Package |
279 | insert func(pkg *types.Package, name string) // "shallow" mode only |
280 | |
281 | stringData []byte |
282 | stringCache map[uint64]string |
283 | pkgCache map[uint64]*types.Package |
284 | |
285 | declData []byte |
286 | pkgIndex map[*types.Package]map[string]uint64 |
287 | typCache map[uint64]types.Type |
288 | tparamIndex map[ident]types.Type |
289 | |
290 | fake fakeFileSet |
291 | interfaceList []*types.Interface |
292 | |
293 | // Arguments for calls to SetConstraint that are deferred due to recursive types |
294 | later []setConstraintArgs |
295 | |
296 | indent int // for tracing support |
297 | } |
298 | |
299 | func (p *iimporter) trace(format string, args ...interface{}) { |
300 | if !trace { |
301 | // Call sites should also be guarded, but having this check here allows |
302 | // easily enabling/disabling debug trace statements. |
303 | return |
304 | } |
305 | fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...) |
306 | } |
307 | |
308 | func (p *iimporter) doDecl(pkg *types.Package, name string) { |
309 | if debug { |
310 | p.trace("import decl %s", name) |
311 | p.indent++ |
312 | defer func() { |
313 | p.indent-- |
314 | p.trace("=> %s", name) |
315 | }() |
316 | } |
317 | // See if we've already imported this declaration. |
318 | if obj := pkg.Scope().Lookup(name); obj != nil { |
319 | return |
320 | } |
321 | |
322 | off, ok := p.pkgIndex[pkg][name] |
323 | if !ok { |
324 | // In "shallow" mode, call back to the application to |
325 | // find the object and insert it into the package scope. |
326 | if p.insert != nil { |
327 | assert(pkg != p.localpkg) |
328 | p.insert(pkg, name) // "can't fail" |
329 | return |
330 | } |
331 | errorf("%v.%v not in index", pkg, name) |
332 | } |
333 | |
334 | r := &importReader{p: p, currPkg: pkg} |
335 | r.declReader.Reset(p.declData[off:]) |
336 | |
337 | r.obj(name) |
338 | } |
339 | |
340 | func (p *iimporter) stringAt(off uint64) string { |
341 | if s, ok := p.stringCache[off]; ok { |
342 | return s |
343 | } |
344 | |
345 | slen, n := binary.Uvarint(p.stringData[off:]) |
346 | if n <= 0 { |
347 | errorf("varint failed") |
348 | } |
349 | spos := off + uint64(n) |
350 | s := string(p.stringData[spos : spos+slen]) |
351 | p.stringCache[off] = s |
352 | return s |
353 | } |
354 | |
355 | func (p *iimporter) pkgAt(off uint64) *types.Package { |
356 | if pkg, ok := p.pkgCache[off]; ok { |
357 | return pkg |
358 | } |
359 | path := p.stringAt(off) |
360 | errorf("missing package %q in %q", path, p.ipath) |
361 | return nil |
362 | } |
363 | |
364 | func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { |
365 | if t, ok := p.typCache[off]; ok && canReuse(base, t) { |
366 | return t |
367 | } |
368 | |
369 | if off < predeclReserved { |
370 | errorf("predeclared type missing from cache: %v", off) |
371 | } |
372 | |
373 | r := &importReader{p: p} |
374 | r.declReader.Reset(p.declData[off-predeclReserved:]) |
375 | t := r.doType(base) |
376 | |
377 | if canReuse(base, t) { |
378 | p.typCache[off] = t |
379 | } |
380 | return t |
381 | } |
382 | |
383 | // canReuse reports whether the type rhs on the RHS of the declaration for def |
384 | // may be re-used. |
385 | // |
386 | // Specifically, if def is non-nil and rhs is an interface type with methods, it |
387 | // may not be re-used because we have a convention of setting the receiver type |
388 | // for interface methods to def. |
389 | func canReuse(def *types.Named, rhs types.Type) bool { |
390 | if def == nil { |
391 | return true |
392 | } |
393 | iface, _ := rhs.(*types.Interface) |
394 | if iface == nil { |
395 | return true |
396 | } |
397 | // Don't use iface.Empty() here as iface may not be complete. |
398 | return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0 |
399 | } |
400 | |
401 | type importReader struct { |
402 | p *iimporter |
403 | declReader bytes.Reader |
404 | currPkg *types.Package |
405 | prevFile string |
406 | prevLine int64 |
407 | prevColumn int64 |
408 | } |
409 | |
410 | func (r *importReader) obj(name string) { |
411 | tag := r.byte() |
412 | pos := r.pos() |
413 | |
414 | switch tag { |
415 | case 'A': |
416 | typ := r.typ() |
417 | |
418 | r.declare(types.NewTypeName(pos, r.currPkg, name, typ)) |
419 | |
420 | case 'C': |
421 | typ, val := r.value() |
422 | |
423 | r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) |
424 | |
425 | case 'F', 'G': |
426 | var tparams []*typeparams.TypeParam |
427 | if tag == 'G' { |
428 | tparams = r.tparamList() |
429 | } |
430 | sig := r.signature(nil, nil, tparams) |
431 | r.declare(types.NewFunc(pos, r.currPkg, name, sig)) |
432 | |
433 | case 'T', 'U': |
434 | // Types can be recursive. We need to setup a stub |
435 | // declaration before recursing. |
436 | obj := types.NewTypeName(pos, r.currPkg, name, nil) |
437 | named := types.NewNamed(obj, nil, nil) |
438 | // Declare obj before calling r.tparamList, so the new type name is recognized |
439 | // if used in the constraint of one of its own typeparams (see #48280). |
440 | r.declare(obj) |
441 | if tag == 'U' { |
442 | tparams := r.tparamList() |
443 | typeparams.SetForNamed(named, tparams) |
444 | } |
445 | |
446 | underlying := r.p.typAt(r.uint64(), named).Underlying() |
447 | named.SetUnderlying(underlying) |
448 | |
449 | if !isInterface(underlying) { |
450 | for n := r.uint64(); n > 0; n-- { |
451 | mpos := r.pos() |
452 | mname := r.ident() |
453 | recv := r.param() |
454 | |
455 | // If the receiver has any targs, set those as the |
456 | // rparams of the method (since those are the |
457 | // typeparams being used in the method sig/body). |
458 | base := baseType(recv.Type()) |
459 | assert(base != nil) |
460 | targs := typeparams.NamedTypeArgs(base) |
461 | var rparams []*typeparams.TypeParam |
462 | if targs.Len() > 0 { |
463 | rparams = make([]*typeparams.TypeParam, targs.Len()) |
464 | for i := range rparams { |
465 | rparams[i] = targs.At(i).(*typeparams.TypeParam) |
466 | } |
467 | } |
468 | msig := r.signature(recv, rparams, nil) |
469 | |
470 | named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) |
471 | } |
472 | } |
473 | |
474 | case 'P': |
475 | // We need to "declare" a typeparam in order to have a name that |
476 | // can be referenced recursively (if needed) in the type param's |
477 | // bound. |
478 | if r.p.version < iexportVersionGenerics { |
479 | errorf("unexpected type param type") |
480 | } |
481 | name0 := tparamName(name) |
482 | tn := types.NewTypeName(pos, r.currPkg, name0, nil) |
483 | t := typeparams.NewTypeParam(tn, nil) |
484 | |
485 | // To handle recursive references to the typeparam within its |
486 | // bound, save the partial type in tparamIndex before reading the bounds. |
487 | id := ident{r.currPkg, name} |
488 | r.p.tparamIndex[id] = t |
489 | var implicit bool |
490 | if r.p.version >= iexportVersionGo1_18 { |
491 | implicit = r.bool() |
492 | } |
493 | constraint := r.typ() |
494 | if implicit { |
495 | iface, _ := constraint.(*types.Interface) |
496 | if iface == nil { |
497 | errorf("non-interface constraint marked implicit") |
498 | } |
499 | typeparams.MarkImplicit(iface) |
500 | } |
501 | // The constraint type may not be complete, if we |
502 | // are in the middle of a type recursion involving type |
503 | // constraints. So, we defer SetConstraint until we have |
504 | // completely set up all types in ImportData. |
505 | r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) |
506 | |
507 | case 'V': |
508 | typ := r.typ() |
509 | |
510 | r.declare(types.NewVar(pos, r.currPkg, name, typ)) |
511 | |
512 | default: |
513 | errorf("unexpected tag: %v", tag) |
514 | } |
515 | } |
516 | |
517 | func (r *importReader) declare(obj types.Object) { |
518 | obj.Pkg().Scope().Insert(obj) |
519 | } |
520 | |
521 | func (r *importReader) value() (typ types.Type, val constant.Value) { |
522 | typ = r.typ() |
523 | if r.p.version >= iexportVersionGo1_18 { |
524 | // TODO: add support for using the kind. |
525 | _ = constant.Kind(r.int64()) |
526 | } |
527 | |
528 | switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType { |
529 | case types.IsBoolean: |
530 | val = constant.MakeBool(r.bool()) |
531 | |
532 | case types.IsString: |
533 | val = constant.MakeString(r.string()) |
534 | |
535 | case types.IsInteger: |
536 | var x big.Int |
537 | r.mpint(&x, b) |
538 | val = constant.Make(&x) |
539 | |
540 | case types.IsFloat: |
541 | val = r.mpfloat(b) |
542 | |
543 | case types.IsComplex: |
544 | re := r.mpfloat(b) |
545 | im := r.mpfloat(b) |
546 | val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) |
547 | |
548 | default: |
549 | if b.Kind() == types.Invalid { |
550 | val = constant.MakeUnknown() |
551 | return |
552 | } |
553 | errorf("unexpected type %v", typ) // panics |
554 | panic("unreachable") |
555 | } |
556 | |
557 | return |
558 | } |
559 | |
560 | func intSize(b *types.Basic) (signed bool, maxBytes uint) { |
561 | if (b.Info() & types.IsUntyped) != 0 { |
562 | return true, 64 |
563 | } |
564 | |
565 | switch b.Kind() { |
566 | case types.Float32, types.Complex64: |
567 | return true, 3 |
568 | case types.Float64, types.Complex128: |
569 | return true, 7 |
570 | } |
571 | |
572 | signed = (b.Info() & types.IsUnsigned) == 0 |
573 | switch b.Kind() { |
574 | case types.Int8, types.Uint8: |
575 | maxBytes = 1 |
576 | case types.Int16, types.Uint16: |
577 | maxBytes = 2 |
578 | case types.Int32, types.Uint32: |
579 | maxBytes = 4 |
580 | default: |
581 | maxBytes = 8 |
582 | } |
583 | |
584 | return |
585 | } |
586 | |
587 | func (r *importReader) mpint(x *big.Int, typ *types.Basic) { |
588 | signed, maxBytes := intSize(typ) |
589 | |
590 | maxSmall := 256 - maxBytes |
591 | if signed { |
592 | maxSmall = 256 - 2*maxBytes |
593 | } |
594 | if maxBytes == 1 { |
595 | maxSmall = 256 |
596 | } |
597 | |
598 | n, _ := r.declReader.ReadByte() |
599 | if uint(n) < maxSmall { |
600 | v := int64(n) |
601 | if signed { |
602 | v >>= 1 |
603 | if n&1 != 0 { |
604 | v = ^v |
605 | } |
606 | } |
607 | x.SetInt64(v) |
608 | return |
609 | } |
610 | |
611 | v := -n |
612 | if signed { |
613 | v = -(n &^ 1) >> 1 |
614 | } |
615 | if v < 1 || uint(v) > maxBytes { |
616 | errorf("weird decoding: %v, %v => %v", n, signed, v) |
617 | } |
618 | b := make([]byte, v) |
619 | io.ReadFull(&r.declReader, b) |
620 | x.SetBytes(b) |
621 | if signed && n&1 != 0 { |
622 | x.Neg(x) |
623 | } |
624 | } |
625 | |
626 | func (r *importReader) mpfloat(typ *types.Basic) constant.Value { |
627 | var mant big.Int |
628 | r.mpint(&mant, typ) |
629 | var f big.Float |
630 | f.SetInt(&mant) |
631 | if f.Sign() != 0 { |
632 | f.SetMantExp(&f, int(r.int64())) |
633 | } |
634 | return constant.Make(&f) |
635 | } |
636 | |
637 | func (r *importReader) ident() string { |
638 | return r.string() |
639 | } |
640 | |
641 | func (r *importReader) qualifiedIdent() (*types.Package, string) { |
642 | name := r.string() |
643 | pkg := r.pkg() |
644 | return pkg, name |
645 | } |
646 | |
647 | func (r *importReader) pos() token.Pos { |
648 | if r.p.version >= iexportVersionPosCol { |
649 | r.posv1() |
650 | } else { |
651 | r.posv0() |
652 | } |
653 | |
654 | if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 { |
655 | return token.NoPos |
656 | } |
657 | return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn)) |
658 | } |
659 | |
660 | func (r *importReader) posv0() { |
661 | delta := r.int64() |
662 | if delta != deltaNewFile { |
663 | r.prevLine += delta |
664 | } else if l := r.int64(); l == -1 { |
665 | r.prevLine += deltaNewFile |
666 | } else { |
667 | r.prevFile = r.string() |
668 | r.prevLine = l |
669 | } |
670 | } |
671 | |
672 | func (r *importReader) posv1() { |
673 | delta := r.int64() |
674 | r.prevColumn += delta >> 1 |
675 | if delta&1 != 0 { |
676 | delta = r.int64() |
677 | r.prevLine += delta >> 1 |
678 | if delta&1 != 0 { |
679 | r.prevFile = r.string() |
680 | } |
681 | } |
682 | } |
683 | |
684 | func (r *importReader) typ() types.Type { |
685 | return r.p.typAt(r.uint64(), nil) |
686 | } |
687 | |
688 | func isInterface(t types.Type) bool { |
689 | _, ok := t.(*types.Interface) |
690 | return ok |
691 | } |
692 | |
693 | func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) } |
694 | func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } |
695 | |
696 | func (r *importReader) doType(base *types.Named) (res types.Type) { |
697 | k := r.kind() |
698 | if debug { |
699 | r.p.trace("importing type %d (base: %s)", k, base) |
700 | r.p.indent++ |
701 | defer func() { |
702 | r.p.indent-- |
703 | r.p.trace("=> %s", res) |
704 | }() |
705 | } |
706 | switch k { |
707 | default: |
708 | errorf("unexpected kind tag in %q: %v", r.p.ipath, k) |
709 | return nil |
710 | |
711 | case definedType: |
712 | pkg, name := r.qualifiedIdent() |
713 | r.p.doDecl(pkg, name) |
714 | return pkg.Scope().Lookup(name).(*types.TypeName).Type() |
715 | case pointerType: |
716 | return types.NewPointer(r.typ()) |
717 | case sliceType: |
718 | return types.NewSlice(r.typ()) |
719 | case arrayType: |
720 | n := r.uint64() |
721 | return types.NewArray(r.typ(), int64(n)) |
722 | case chanType: |
723 | dir := chanDir(int(r.uint64())) |
724 | return types.NewChan(dir, r.typ()) |
725 | case mapType: |
726 | return types.NewMap(r.typ(), r.typ()) |
727 | case signatureType: |
728 | r.currPkg = r.pkg() |
729 | return r.signature(nil, nil, nil) |
730 | |
731 | case structType: |
732 | r.currPkg = r.pkg() |
733 | |
734 | fields := make([]*types.Var, r.uint64()) |
735 | tags := make([]string, len(fields)) |
736 | for i := range fields { |
737 | fpos := r.pos() |
738 | fname := r.ident() |
739 | ftyp := r.typ() |
740 | emb := r.bool() |
741 | tag := r.string() |
742 | |
743 | fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb) |
744 | tags[i] = tag |
745 | } |
746 | return types.NewStruct(fields, tags) |
747 | |
748 | case interfaceType: |
749 | r.currPkg = r.pkg() |
750 | |
751 | embeddeds := make([]types.Type, r.uint64()) |
752 | for i := range embeddeds { |
753 | _ = r.pos() |
754 | embeddeds[i] = r.typ() |
755 | } |
756 | |
757 | methods := make([]*types.Func, r.uint64()) |
758 | for i := range methods { |
759 | mpos := r.pos() |
760 | mname := r.ident() |
761 | |
762 | // TODO(mdempsky): Matches bimport.go, but I |
763 | // don't agree with this. |
764 | var recv *types.Var |
765 | if base != nil { |
766 | recv = types.NewVar(token.NoPos, r.currPkg, "", base) |
767 | } |
768 | |
769 | msig := r.signature(recv, nil, nil) |
770 | methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) |
771 | } |
772 | |
773 | typ := newInterface(methods, embeddeds) |
774 | r.p.interfaceList = append(r.p.interfaceList, typ) |
775 | return typ |
776 | |
777 | case typeParamType: |
778 | if r.p.version < iexportVersionGenerics { |
779 | errorf("unexpected type param type") |
780 | } |
781 | pkg, name := r.qualifiedIdent() |
782 | id := ident{pkg, name} |
783 | if t, ok := r.p.tparamIndex[id]; ok { |
784 | // We're already in the process of importing this typeparam. |
785 | return t |
786 | } |
787 | // Otherwise, import the definition of the typeparam now. |
788 | r.p.doDecl(pkg, name) |
789 | return r.p.tparamIndex[id] |
790 | |
791 | case instanceType: |
792 | if r.p.version < iexportVersionGenerics { |
793 | errorf("unexpected instantiation type") |
794 | } |
795 | // pos does not matter for instances: they are positioned on the original |
796 | // type. |
797 | _ = r.pos() |
798 | len := r.uint64() |
799 | targs := make([]types.Type, len) |
800 | for i := range targs { |
801 | targs[i] = r.typ() |
802 | } |
803 | baseType := r.typ() |
804 | // The imported instantiated type doesn't include any methods, so |
805 | // we must always use the methods of the base (orig) type. |
806 | // TODO provide a non-nil *Environment |
807 | t, _ := typeparams.Instantiate(nil, baseType, targs, false) |
808 | return t |
809 | |
810 | case unionType: |
811 | if r.p.version < iexportVersionGenerics { |
812 | errorf("unexpected instantiation type") |
813 | } |
814 | terms := make([]*typeparams.Term, r.uint64()) |
815 | for i := range terms { |
816 | terms[i] = typeparams.NewTerm(r.bool(), r.typ()) |
817 | } |
818 | return typeparams.NewUnion(terms) |
819 | } |
820 | } |
821 | |
822 | func (r *importReader) kind() itag { |
823 | return itag(r.uint64()) |
824 | } |
825 | |
826 | func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature { |
827 | params := r.paramList() |
828 | results := r.paramList() |
829 | variadic := params.Len() > 0 && r.bool() |
830 | return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic) |
831 | } |
832 | |
833 | func (r *importReader) tparamList() []*typeparams.TypeParam { |
834 | n := r.uint64() |
835 | if n == 0 { |
836 | return nil |
837 | } |
838 | xs := make([]*typeparams.TypeParam, n) |
839 | for i := range xs { |
840 | // Note: the standard library importer is tolerant of nil types here, |
841 | // though would panic in SetTypeParams. |
842 | xs[i] = r.typ().(*typeparams.TypeParam) |
843 | } |
844 | return xs |
845 | } |
846 | |
847 | func (r *importReader) paramList() *types.Tuple { |
848 | xs := make([]*types.Var, r.uint64()) |
849 | for i := range xs { |
850 | xs[i] = r.param() |
851 | } |
852 | return types.NewTuple(xs...) |
853 | } |
854 | |
855 | func (r *importReader) param() *types.Var { |
856 | pos := r.pos() |
857 | name := r.ident() |
858 | typ := r.typ() |
859 | return types.NewParam(pos, r.currPkg, name, typ) |
860 | } |
861 | |
862 | func (r *importReader) bool() bool { |
863 | return r.uint64() != 0 |
864 | } |
865 | |
866 | func (r *importReader) int64() int64 { |
867 | n, err := binary.ReadVarint(&r.declReader) |
868 | if err != nil { |
869 | errorf("readVarint: %v", err) |
870 | } |
871 | return n |
872 | } |
873 | |
874 | func (r *importReader) uint64() uint64 { |
875 | n, err := binary.ReadUvarint(&r.declReader) |
876 | if err != nil { |
877 | errorf("readUvarint: %v", err) |
878 | } |
879 | return n |
880 | } |
881 | |
882 | func (r *importReader) byte() byte { |
883 | x, err := r.declReader.ReadByte() |
884 | if err != nil { |
885 | errorf("declReader.ReadByte: %v", err) |
886 | } |
887 | return x |
888 | } |
889 | |
890 | func baseType(typ types.Type) *types.Named { |
891 | // pointer receivers are never types.Named types |
892 | if p, _ := typ.(*types.Pointer); p != nil { |
893 | typ = p.Elem() |
894 | } |
895 | // receiver base types are always (possibly generic) types.Named types |
896 | n, _ := typ.(*types.Named) |
897 | return n |
898 | } |
899 |
Members