iimport.go raw
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 iexport.go for the export data format.
7
8 package gcimporter
9
10 import (
11 "bytes"
12 "encoding/binary"
13 "fmt"
14 "go/constant"
15 "go/token"
16 "go/types"
17 "io"
18 "math/big"
19 "slices"
20 "sort"
21 "strings"
22
23 "golang.org/x/tools/go/types/objectpath"
24 "golang.org/x/tools/internal/aliases"
25 "golang.org/x/tools/internal/typesinternal"
26 )
27
28 type intReader struct {
29 *bytes.Reader
30 path string
31 }
32
33 func (r *intReader) int64() int64 {
34 i, err := binary.ReadVarint(r.Reader)
35 if err != nil {
36 errorf("import %q: read varint error: %v", r.path, err)
37 }
38 return i
39 }
40
41 func (r *intReader) uint64() uint64 {
42 i, err := binary.ReadUvarint(r.Reader)
43 if err != nil {
44 errorf("import %q: read varint error: %v", r.path, err)
45 }
46 return i
47 }
48
49 // Keep this in sync with constants in iexport.go.
50 const (
51 iexportVersionGo1_11 = 0
52 iexportVersionPosCol = 1
53 iexportVersionGo1_18 = 2
54 iexportVersionGenerics = 2
55 iexportVersion = iexportVersionGenerics
56
57 iexportVersionCurrent = 2
58 )
59
60 type ident struct {
61 pkg *types.Package
62 name string
63 }
64
65 const predeclReserved = 32
66
67 type itag uint64
68
69 const (
70 // Types
71 definedType itag = iota
72 pointerType
73 sliceType
74 arrayType
75 chanType
76 mapType
77 signatureType
78 structType
79 interfaceType
80 typeParamType
81 instanceType
82 unionType
83 aliasType
84 )
85
86 // Object tags
87 const (
88 varTag = 'V'
89 funcTag = 'F'
90 genericFuncTag = 'G'
91 constTag = 'C'
92 aliasTag = 'A'
93 genericAliasTag = 'B'
94 typeParamTag = 'P'
95 typeTag = 'T'
96 genericTypeTag = 'U'
97 )
98
99 // IImportData imports a package from the serialized package data
100 // and returns 0 and a reference to the package.
101 // If the export data version is not recognized or the format is otherwise
102 // compromised, an error is returned.
103 func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
104 pkgs, err := iimportCommon(fset, GetPackagesFromMap(imports), data, false, path, false, nil)
105 if err != nil {
106 return 0, nil, err
107 }
108 return 0, pkgs[0], nil
109 }
110
111 // IImportBundle imports a set of packages from the serialized package bundle.
112 func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
113 return iimportCommon(fset, GetPackagesFromMap(imports), data, true, "", false, nil)
114 }
115
116 // A GetPackagesFunc function obtains the non-nil symbols for a set of
117 // packages, creating and recursively importing them as needed. An
118 // implementation should store each package symbol is in the Pkg
119 // field of the items array.
120 //
121 // Any error causes importing to fail. This can be used to quickly read
122 // the import manifest of an export data file without fully decoding it.
123 type GetPackagesFunc = func(items []GetPackagesItem) error
124
125 // A GetPackagesItem is a request from the importer for the package
126 // symbol of the specified name and path.
127 type GetPackagesItem struct {
128 Name, Path string
129 Pkg *types.Package // to be filled in by GetPackagesFunc call
130
131 // private importer state
132 pathOffset uint64
133 nameIndex map[string]uint64
134 }
135
136 // GetPackagesFromMap returns a GetPackagesFunc that retrieves
137 // packages from the given map of package path to package.
138 //
139 // The returned function may mutate m: each requested package that is not
140 // found is created with types.NewPackage and inserted into m.
141 func GetPackagesFromMap(m map[string]*types.Package) GetPackagesFunc {
142 return func(items []GetPackagesItem) error {
143 for i, item := range items {
144 pkg, ok := m[item.Path]
145 if !ok {
146 pkg = types.NewPackage(item.Path, item.Name)
147 m[item.Path] = pkg
148 }
149 items[i].Pkg = pkg
150 }
151 return nil
152 }
153 }
154
155 func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, bundle bool, path string, shallow bool, reportf ReportFunc) (pkgs []*types.Package, err error) {
156 const currentVersion = iexportVersionCurrent
157 version := int64(-1)
158 if !debug {
159 defer func() {
160 if e := recover(); e != nil {
161 if bundle {
162 err = fmt.Errorf("%v", e)
163 } else if version > currentVersion {
164 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
165 } else {
166 err = fmt.Errorf("internal error while importing %q (%v); please report an issue", path, e)
167 }
168 }
169 }()
170 }
171
172 r := &intReader{bytes.NewReader(data), path}
173
174 if bundle {
175 if v := r.uint64(); v != bundleVersion {
176 errorf("unknown bundle format version %d", v)
177 }
178 }
179
180 version = int64(r.uint64())
181 switch version {
182 case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
183 default:
184 if version > iexportVersionGo1_18 {
185 errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
186 } else {
187 errorf("unknown iexport format version %d", version)
188 }
189 }
190
191 sLen := int64(r.uint64())
192 var fLen int64
193 var fileOffset []uint64
194 if shallow {
195 // Shallow mode uses a different position encoding.
196 fLen = int64(r.uint64())
197 fileOffset = make([]uint64, r.uint64())
198 for i := range fileOffset {
199 fileOffset[i] = r.uint64()
200 }
201 }
202 dLen := int64(r.uint64())
203
204 whence, _ := r.Seek(0, io.SeekCurrent)
205 stringData := data[whence : whence+sLen]
206 fileData := data[whence+sLen : whence+sLen+fLen]
207 declData := data[whence+sLen+fLen : whence+sLen+fLen+dLen]
208 r.Seek(sLen+fLen+dLen, io.SeekCurrent)
209
210 p := iimporter{
211 version: int(version),
212 ipath: path,
213 aliases: aliases.Enabled(),
214 shallow: shallow,
215 reportf: reportf,
216
217 stringData: stringData,
218 stringCache: make(map[uint64]string),
219 fileOffset: fileOffset,
220 fileData: fileData,
221 fileCache: make([]*token.File, len(fileOffset)),
222 pkgCache: make(map[uint64]*types.Package),
223
224 declData: declData,
225 pkgIndex: make(map[*types.Package]map[string]uint64),
226 typCache: make(map[uint64]types.Type),
227 // Separate map for typeparams, keyed by their package and unique
228 // name.
229 tparamIndex: make(map[ident]types.Type),
230
231 fake: fakeFileSet{
232 fset: fset,
233 files: make(map[string]*fileInfo),
234 },
235 }
236 defer p.fake.setLines() // set lines for files in fset
237
238 for i, pt := range predeclared() {
239 p.typCache[uint64(i)] = pt
240 }
241
242 // Gather the relevant packages from the manifest.
243 items := make([]GetPackagesItem, r.uint64())
244 uniquePkgPaths := make(map[string]bool)
245 for i := range items {
246 pkgPathOff := r.uint64()
247 pkgPath := p.stringAt(pkgPathOff)
248 pkgName := p.stringAt(r.uint64())
249 _ = r.uint64() // package height; unused by go/types
250
251 if pkgPath == "" {
252 pkgPath = path
253 }
254 items[i].Name = pkgName
255 items[i].Path = pkgPath
256 items[i].pathOffset = pkgPathOff
257
258 // Read index for package.
259 nameIndex := make(map[string]uint64)
260 nSyms := r.uint64()
261 // In shallow mode, only the current package (i=0) has an index.
262 assert(!(shallow && i > 0 && nSyms != 0))
263 for ; nSyms > 0; nSyms-- {
264 name := p.stringAt(r.uint64())
265 nameIndex[name] = r.uint64()
266 }
267
268 items[i].nameIndex = nameIndex
269
270 uniquePkgPaths[pkgPath] = true
271 }
272 // Debugging #63822; hypothesis: there are duplicate PkgPaths.
273 if len(uniquePkgPaths) != len(items) {
274 reportf("found duplicate PkgPaths while reading export data manifest: %v", items)
275 }
276
277 // Request packages all at once from the client,
278 // enabling a parallel implementation.
279 if err := getPackages(items); err != nil {
280 return nil, err // don't wrap this error
281 }
282
283 // Check the results and complete the index.
284 pkgList := make([]*types.Package, len(items))
285 for i, item := range items {
286 pkg := item.Pkg
287 if pkg == nil {
288 errorf("internal error: getPackages returned nil package for %q", item.Path)
289 } else if pkg.Path() != item.Path {
290 errorf("internal error: getPackages returned wrong path %q, want %q", pkg.Path(), item.Path)
291 } else if pkg.Name() != item.Name {
292 errorf("internal error: getPackages returned wrong name %s for package %q, want %s", pkg.Name(), item.Path, item.Name)
293 }
294 p.pkgCache[item.pathOffset] = pkg
295 p.pkgIndex[pkg] = item.nameIndex
296 pkgList[i] = pkg
297 }
298
299 if bundle {
300 pkgs = make([]*types.Package, r.uint64())
301 for i := range pkgs {
302 pkg := p.pkgAt(r.uint64())
303 imps := make([]*types.Package, r.uint64())
304 for j := range imps {
305 imps[j] = p.pkgAt(r.uint64())
306 }
307 pkg.SetImports(imps)
308 pkgs[i] = pkg
309 }
310 } else {
311 if len(pkgList) == 0 {
312 errorf("no packages found for %s", path)
313 panic("unreachable")
314 }
315 pkgs = pkgList[:1]
316
317 // record all referenced packages as imports
318 list := slices.Clone(pkgList[1:])
319 sort.Sort(byPath(list))
320 pkgs[0].SetImports(list)
321 }
322
323 for _, pkg := range pkgs {
324 if pkg.Complete() {
325 continue
326 }
327
328 names := make([]string, 0, len(p.pkgIndex[pkg]))
329 for name := range p.pkgIndex[pkg] {
330 names = append(names, name)
331 }
332 sort.Strings(names)
333 for _, name := range names {
334 p.doDecl(pkg, name)
335 }
336
337 // package was imported completely and without errors
338 pkg.MarkComplete()
339 }
340
341 // SetConstraint can't be called if the constraint type is not yet complete.
342 // When type params are created in the typeParamTag case of (*importReader).obj(),
343 // the associated constraint type may not be complete due to recursion.
344 // Therefore, we defer calling SetConstraint there, and call it here instead
345 // after all types are complete.
346 for _, d := range p.later {
347 d.t.SetConstraint(d.constraint)
348 }
349
350 for _, typ := range p.interfaceList {
351 typ.Complete()
352 }
353
354 // Workaround for golang/go#61561. See the doc for instanceList for details.
355 for _, typ := range p.instanceList {
356 if iface, _ := typ.Underlying().(*types.Interface); iface != nil {
357 iface.Complete()
358 }
359 }
360
361 return pkgs, nil
362 }
363
364 type setConstraintArgs struct {
365 t *types.TypeParam
366 constraint types.Type
367 }
368
369 type iimporter struct {
370 version int
371 ipath string
372
373 aliases bool
374 shallow bool
375 reportf ReportFunc // if non-nil, used to report bugs
376
377 stringData []byte
378 stringCache map[uint64]string
379 fileOffset []uint64 // fileOffset[i] is offset in fileData for info about file encoded as i
380 fileData []byte
381 fileCache []*token.File // memoized decoding of file encoded as i
382 pkgCache map[uint64]*types.Package
383
384 declData []byte
385 pkgIndex map[*types.Package]map[string]uint64
386 typCache map[uint64]types.Type
387 tparamIndex map[ident]types.Type
388
389 fake fakeFileSet
390 interfaceList []*types.Interface
391
392 // Workaround for the go/types bug golang/go#61561: instances produced during
393 // instantiation may contain incomplete interfaces. Here we only complete the
394 // underlying type of the instance, which is the most common case but doesn't
395 // handle parameterized interface literals defined deeper in the type.
396 instanceList []types.Type // instances for later completion (see golang/go#61561)
397
398 // Arguments for calls to SetConstraint that are deferred due to recursive types
399 later []setConstraintArgs
400
401 indent int // for tracing support
402 }
403
404 func (p *iimporter) trace(format string, args ...any) {
405 if !trace {
406 // Call sites should also be guarded, but having this check here allows
407 // easily enabling/disabling debug trace statements.
408 return
409 }
410 fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
411 }
412
413 func (p *iimporter) doDecl(pkg *types.Package, name string) {
414 if debug {
415 p.trace("import decl %s", name)
416 p.indent++
417 defer func() {
418 p.indent--
419 p.trace("=> %s", name)
420 }()
421 }
422 // See if we've already imported this declaration.
423 if obj := pkg.Scope().Lookup(name); obj != nil {
424 return
425 }
426
427 off, ok := p.pkgIndex[pkg][name]
428 if !ok {
429 // In deep mode, the index should be complete. In shallow
430 // mode, we should have already recursively loaded necessary
431 // dependencies so the above Lookup succeeds.
432 errorf("%v.%v not in index", pkg, name)
433 }
434
435 r := &importReader{p: p}
436 r.declReader.Reset(p.declData[off:])
437
438 r.obj(pkg, name)
439 }
440
441 func (p *iimporter) stringAt(off uint64) string {
442 if s, ok := p.stringCache[off]; ok {
443 return s
444 }
445
446 slen, n := binary.Uvarint(p.stringData[off:])
447 if n <= 0 {
448 errorf("varint failed")
449 }
450 spos := off + uint64(n)
451 s := string(p.stringData[spos : spos+slen])
452 p.stringCache[off] = s
453 return s
454 }
455
456 func (p *iimporter) fileAt(index uint64) *token.File {
457 file := p.fileCache[index]
458 if file == nil {
459 off := p.fileOffset[index]
460 file = p.decodeFile(intReader{bytes.NewReader(p.fileData[off:]), p.ipath})
461 p.fileCache[index] = file
462 }
463 return file
464 }
465
466 func (p *iimporter) decodeFile(rd intReader) *token.File {
467 filename := p.stringAt(rd.uint64())
468 size := int(rd.uint64())
469 file := p.fake.fset.AddFile(filename, -1, size)
470
471 // SetLines requires a nondecreasing sequence.
472 // Because it is common for clients to derive the interval
473 // [start, start+len(name)] from a start position, and we
474 // want to ensure that the end offset is on the same line,
475 // we fill in the gaps of the sparse encoding with values
476 // that strictly increase by the largest possible amount.
477 // This allows us to avoid having to record the actual end
478 // offset of each needed line.
479
480 lines := make([]int, int(rd.uint64()))
481 var index, offset int
482 for i, n := 0, int(rd.uint64()); i < n; i++ {
483 index += int(rd.uint64())
484 offset += int(rd.uint64())
485 lines[index] = offset
486
487 // Ensure monotonicity between points.
488 for j := index - 1; j > 0 && lines[j] == 0; j-- {
489 lines[j] = lines[j+1] - 1
490 }
491 }
492
493 // Ensure monotonicity after last point.
494 for j := len(lines) - 1; j > 0 && lines[j] == 0; j-- {
495 size--
496 lines[j] = size
497 }
498
499 if !file.SetLines(lines) {
500 errorf("SetLines failed: %d", lines) // can't happen
501 }
502 return file
503 }
504
505 func (p *iimporter) pkgAt(off uint64) *types.Package {
506 if pkg, ok := p.pkgCache[off]; ok {
507 return pkg
508 }
509 path := p.stringAt(off)
510 errorf("missing package %q in %q", path, p.ipath)
511 return nil
512 }
513
514 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
515 if t, ok := p.typCache[off]; ok && canReuse(base, t) {
516 return t
517 }
518
519 if off < predeclReserved {
520 errorf("predeclared type missing from cache: %v", off)
521 }
522
523 r := &importReader{p: p}
524 r.declReader.Reset(p.declData[off-predeclReserved:])
525 t := r.doType(base)
526
527 if canReuse(base, t) {
528 p.typCache[off] = t
529 }
530 return t
531 }
532
533 // canReuse reports whether the type rhs on the RHS of the declaration for def
534 // may be re-used.
535 //
536 // Specifically, if def is non-nil and rhs is an interface type with methods, it
537 // may not be re-used because we have a convention of setting the receiver type
538 // for interface methods to def.
539 func canReuse(def *types.Named, rhs types.Type) bool {
540 if def == nil {
541 return true
542 }
543 iface, _ := types.Unalias(rhs).(*types.Interface)
544 if iface == nil {
545 return true
546 }
547 // Don't use iface.Empty() here as iface may not be complete.
548 return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
549 }
550
551 type importReader struct {
552 p *iimporter
553 declReader bytes.Reader
554 prevFile string
555 prevLine int64
556 prevColumn int64
557 }
558
559 // markBlack is redefined in iimport_go123.go, to work around golang/go#69912.
560 //
561 // If TypeNames are not marked black (in the sense of go/types cycle
562 // detection), they may be mutated when dot-imported. Fix this by punching a
563 // hole through the type, when compiling with Go 1.23. (The bug has been fixed
564 // for 1.24, but the fix was not worth back-porting).
565 var markBlack = func(name *types.TypeName) {}
566
567 // obj decodes and declares the package-level object denoted by (pkg, name).
568 func (r *importReader) obj(pkg *types.Package, name string) {
569 tag := r.byte()
570 pos := r.pos()
571
572 switch tag {
573 case aliasTag, genericAliasTag:
574 var tparams []*types.TypeParam
575 if tag == genericAliasTag {
576 tparams = r.tparamList()
577 }
578 typ := r.typ()
579 obj := aliases.NewAlias(r.p.aliases, pos, pkg, name, typ, tparams)
580 markBlack(obj) // workaround for golang/go#69912
581 r.declare(obj)
582
583 case constTag:
584 typ, val := r.value()
585
586 r.declare(types.NewConst(pos, pkg, name, typ, val))
587
588 case funcTag, genericFuncTag:
589 var tparams []*types.TypeParam
590 if tag == genericFuncTag {
591 tparams = r.tparamList()
592 }
593 sig := r.signature(pkg, nil, nil, tparams)
594 r.declare(types.NewFunc(pos, pkg, name, sig))
595
596 case typeTag, genericTypeTag:
597 // Types can be recursive. We need to setup a stub
598 // declaration before recursing.
599 obj := types.NewTypeName(pos, pkg, name, nil)
600 named := types.NewNamed(obj, nil, nil)
601
602 markBlack(obj) // workaround for golang/go#69912
603
604 // Declare obj before calling r.tparamList, so the new type name is recognized
605 // if used in the constraint of one of its own typeparams (see #48280).
606 r.declare(obj)
607 if tag == genericTypeTag {
608 tparams := r.tparamList()
609 named.SetTypeParams(tparams)
610 }
611
612 underlying := r.p.typAt(r.uint64(), named).Underlying()
613 named.SetUnderlying(underlying)
614
615 if !isInterface(underlying) {
616 for n := r.uint64(); n > 0; n-- {
617 mpos := r.pos()
618 mname := r.ident()
619 recv := r.param(pkg)
620
621 // If the receiver has any targs, set those as the
622 // rparams of the method (since those are the
623 // typeparams being used in the method sig/body).
624 _, recvNamed := typesinternal.ReceiverNamed(recv)
625 targs := recvNamed.TypeArgs()
626 var rparams []*types.TypeParam
627 if targs.Len() > 0 {
628 rparams = make([]*types.TypeParam, targs.Len())
629 for i := range rparams {
630 rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)
631 }
632 }
633 msig := r.signature(pkg, recv, rparams, nil)
634
635 named.AddMethod(types.NewFunc(mpos, pkg, mname, msig))
636 }
637 }
638
639 case typeParamTag:
640 // We need to "declare" a typeparam in order to have a name that
641 // can be referenced recursively (if needed) in the type param's
642 // bound.
643 if r.p.version < iexportVersionGenerics {
644 errorf("unexpected type param type")
645 }
646 name0 := tparamName(name)
647 tn := types.NewTypeName(pos, pkg, name0, nil)
648 t := types.NewTypeParam(tn, nil)
649
650 // To handle recursive references to the typeparam within its
651 // bound, save the partial type in tparamIndex before reading the bounds.
652 id := ident{pkg, name}
653 r.p.tparamIndex[id] = t
654 var implicit bool
655 if r.p.version >= iexportVersionGo1_18 {
656 implicit = r.bool()
657 }
658 constraint := r.typ()
659 if implicit {
660 iface, _ := types.Unalias(constraint).(*types.Interface)
661 if iface == nil {
662 errorf("non-interface constraint marked implicit")
663 }
664 iface.MarkImplicit()
665 }
666 // The constraint type may not be complete, if we
667 // are in the middle of a type recursion involving type
668 // constraints. So, we defer SetConstraint until we have
669 // completely set up all types in ImportData.
670 r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
671
672 case varTag:
673 typ := r.typ()
674
675 v := types.NewVar(pos, pkg, name, typ)
676 typesinternal.SetVarKind(v, typesinternal.PackageVar)
677 r.declare(v)
678
679 default:
680 errorf("unexpected tag: %v", tag)
681 }
682 }
683
684 func (r *importReader) declare(obj types.Object) {
685 obj.Pkg().Scope().Insert(obj)
686 }
687
688 func (r *importReader) value() (typ types.Type, val constant.Value) {
689 typ = r.typ()
690 if r.p.version >= iexportVersionGo1_18 {
691 // TODO: add support for using the kind.
692 _ = constant.Kind(r.int64())
693 }
694
695 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
696 case types.IsBoolean:
697 val = constant.MakeBool(r.bool())
698
699 case types.IsString:
700 val = constant.MakeString(r.string())
701
702 case types.IsInteger:
703 var x big.Int
704 r.mpint(&x, b)
705 val = constant.Make(&x)
706
707 case types.IsFloat:
708 val = r.mpfloat(b)
709
710 case types.IsComplex:
711 re := r.mpfloat(b)
712 im := r.mpfloat(b)
713 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
714
715 default:
716 if b.Kind() == types.Invalid {
717 val = constant.MakeUnknown()
718 return
719 }
720 errorf("unexpected type %v", typ) // panics
721 panic("unreachable")
722 }
723
724 return
725 }
726
727 func intSize(b *types.Basic) (signed bool, maxBytes uint) {
728 if (b.Info() & types.IsUntyped) != 0 {
729 return true, 64
730 }
731
732 switch b.Kind() {
733 case types.Float32, types.Complex64:
734 return true, 3
735 case types.Float64, types.Complex128:
736 return true, 7
737 }
738
739 signed = (b.Info() & types.IsUnsigned) == 0
740 switch b.Kind() {
741 case types.Int8, types.Uint8:
742 maxBytes = 1
743 case types.Int16, types.Uint16:
744 maxBytes = 2
745 case types.Int32, types.Uint32:
746 maxBytes = 4
747 default:
748 maxBytes = 8
749 }
750
751 return
752 }
753
754 func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
755 signed, maxBytes := intSize(typ)
756
757 maxSmall := 256 - maxBytes
758 if signed {
759 maxSmall = 256 - 2*maxBytes
760 }
761 if maxBytes == 1 {
762 maxSmall = 256
763 }
764
765 n, _ := r.declReader.ReadByte()
766 if uint(n) < maxSmall {
767 v := int64(n)
768 if signed {
769 v >>= 1
770 if n&1 != 0 {
771 v = ^v
772 }
773 }
774 x.SetInt64(v)
775 return
776 }
777
778 v := -n
779 if signed {
780 v = -(n &^ 1) >> 1
781 }
782 if v < 1 || uint(v) > maxBytes {
783 errorf("weird decoding: %v, %v => %v", n, signed, v)
784 }
785 b := make([]byte, v)
786 io.ReadFull(&r.declReader, b)
787 x.SetBytes(b)
788 if signed && n&1 != 0 {
789 x.Neg(x)
790 }
791 }
792
793 func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
794 var mant big.Int
795 r.mpint(&mant, typ)
796 var f big.Float
797 f.SetInt(&mant)
798 if f.Sign() != 0 {
799 f.SetMantExp(&f, int(r.int64()))
800 }
801 return constant.Make(&f)
802 }
803
804 func (r *importReader) ident() string {
805 return r.string()
806 }
807
808 func (r *importReader) qualifiedIdent() (*types.Package, string) {
809 name := r.string()
810 pkg := r.pkg()
811 return pkg, name
812 }
813
814 func (r *importReader) pos() token.Pos {
815 if r.p.shallow {
816 // precise offsets are encoded only in shallow mode
817 return r.posv2()
818 }
819 if r.p.version >= iexportVersionPosCol {
820 r.posv1()
821 } else {
822 r.posv0()
823 }
824
825 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
826 return token.NoPos
827 }
828 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
829 }
830
831 func (r *importReader) posv0() {
832 delta := r.int64()
833 if delta != deltaNewFile {
834 r.prevLine += delta
835 } else if l := r.int64(); l == -1 {
836 r.prevLine += deltaNewFile
837 } else {
838 r.prevFile = r.string()
839 r.prevLine = l
840 }
841 }
842
843 func (r *importReader) posv1() {
844 delta := r.int64()
845 r.prevColumn += delta >> 1
846 if delta&1 != 0 {
847 delta = r.int64()
848 r.prevLine += delta >> 1
849 if delta&1 != 0 {
850 r.prevFile = r.string()
851 }
852 }
853 }
854
855 func (r *importReader) posv2() token.Pos {
856 file := r.uint64()
857 if file == 0 {
858 return token.NoPos
859 }
860 tf := r.p.fileAt(file - 1)
861 return tf.Pos(int(r.uint64()))
862 }
863
864 func (r *importReader) typ() types.Type {
865 return r.p.typAt(r.uint64(), nil)
866 }
867
868 func isInterface(t types.Type) bool {
869 _, ok := types.Unalias(t).(*types.Interface)
870 return ok
871 }
872
873 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
874 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
875
876 func (r *importReader) doType(base *types.Named) (res types.Type) {
877 k := r.kind()
878 if debug {
879 r.p.trace("importing type %d (base: %v)", k, base)
880 r.p.indent++
881 defer func() {
882 r.p.indent--
883 r.p.trace("=> %s", res)
884 }()
885 }
886 switch k {
887 default:
888 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
889 return nil
890
891 case aliasType, definedType:
892 pkg, name := r.qualifiedIdent()
893 r.p.doDecl(pkg, name)
894 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
895 case pointerType:
896 return types.NewPointer(r.typ())
897 case sliceType:
898 return types.NewSlice(r.typ())
899 case arrayType:
900 n := r.uint64()
901 return types.NewArray(r.typ(), int64(n))
902 case chanType:
903 dir := chanDir(int(r.uint64()))
904 return types.NewChan(dir, r.typ())
905 case mapType:
906 return types.NewMap(r.typ(), r.typ())
907 case signatureType:
908 paramPkg := r.pkg()
909 return r.signature(paramPkg, nil, nil, nil)
910
911 case structType:
912 fieldPkg := r.pkg()
913
914 fields := make([]*types.Var, r.uint64())
915 tags := make([]string, len(fields))
916 for i := range fields {
917 var field *types.Var
918 if r.p.shallow {
919 field, _ = r.objectPathObject().(*types.Var)
920 }
921
922 fpos := r.pos()
923 fname := r.ident()
924 ftyp := r.typ()
925 emb := r.bool()
926 tag := r.string()
927
928 // Either this is not a shallow import, the field is local, or the
929 // encoded objectPath failed to produce an object (a bug).
930 //
931 // Even in this last, buggy case, fall back on creating a new field. As
932 // discussed in iexport.go, this is not correct, but mostly works and is
933 // preferable to failing (for now at least).
934 if field == nil {
935 field = types.NewField(fpos, fieldPkg, fname, ftyp, emb)
936 }
937
938 fields[i] = field
939 tags[i] = tag
940 }
941 return types.NewStruct(fields, tags)
942
943 case interfaceType:
944 methodPkg := r.pkg() // qualifies methods and their param/result vars
945
946 embeddeds := make([]types.Type, r.uint64())
947 for i := range embeddeds {
948 _ = r.pos()
949 embeddeds[i] = r.typ()
950 }
951
952 methods := make([]*types.Func, r.uint64())
953 for i := range methods {
954 var method *types.Func
955 if r.p.shallow {
956 method, _ = r.objectPathObject().(*types.Func)
957 }
958
959 mpos := r.pos()
960 mname := r.ident()
961
962 // TODO(mdempsky): Matches bimport.go, but I
963 // don't agree with this.
964 var recv *types.Var
965 if base != nil {
966 recv = types.NewVar(token.NoPos, methodPkg, "", base)
967 }
968 msig := r.signature(methodPkg, recv, nil, nil)
969
970 if method == nil {
971 method = types.NewFunc(mpos, methodPkg, mname, msig)
972 }
973 methods[i] = method
974 }
975
976 typ := types.NewInterfaceType(methods, embeddeds)
977 r.p.interfaceList = append(r.p.interfaceList, typ)
978 return typ
979
980 case typeParamType:
981 if r.p.version < iexportVersionGenerics {
982 errorf("unexpected type param type")
983 }
984 pkg, name := r.qualifiedIdent()
985 id := ident{pkg, name}
986 if t, ok := r.p.tparamIndex[id]; ok {
987 // We're already in the process of importing this typeparam.
988 return t
989 }
990 // Otherwise, import the definition of the typeparam now.
991 r.p.doDecl(pkg, name)
992 return r.p.tparamIndex[id]
993
994 case instanceType:
995 if r.p.version < iexportVersionGenerics {
996 errorf("unexpected instantiation type")
997 }
998 // pos does not matter for instances: they are positioned on the original
999 // type.
1000 _ = r.pos()
1001 len := r.uint64()
1002 targs := make([]types.Type, len)
1003 for i := range targs {
1004 targs[i] = r.typ()
1005 }
1006 baseType := r.typ()
1007 // The imported instantiated type doesn't include any methods, so
1008 // we must always use the methods of the base (orig) type.
1009 // TODO provide a non-nil *Environment
1010 t, _ := types.Instantiate(nil, baseType, targs, false)
1011
1012 // Workaround for golang/go#61561. See the doc for instanceList for details.
1013 r.p.instanceList = append(r.p.instanceList, t)
1014 return t
1015
1016 case unionType:
1017 if r.p.version < iexportVersionGenerics {
1018 errorf("unexpected instantiation type")
1019 }
1020 terms := make([]*types.Term, r.uint64())
1021 for i := range terms {
1022 terms[i] = types.NewTerm(r.bool(), r.typ())
1023 }
1024 return types.NewUnion(terms)
1025 }
1026 }
1027
1028 func (r *importReader) kind() itag {
1029 return itag(r.uint64())
1030 }
1031
1032 // objectPathObject is the inverse of exportWriter.objectPath.
1033 //
1034 // In shallow mode, certain fields and methods may need to be looked up in an
1035 // imported package. See the doc for exportWriter.objectPath for a full
1036 // explanation.
1037 func (r *importReader) objectPathObject() types.Object {
1038 objPath := objectpath.Path(r.string())
1039 if objPath == "" {
1040 return nil
1041 }
1042 pkg := r.pkg()
1043 obj, err := objectpath.Object(pkg, objPath)
1044 if err != nil {
1045 if r.p.reportf != nil {
1046 r.p.reportf("failed to find object for objectPath %q: %v", objPath, err)
1047 }
1048 }
1049 return obj
1050 }
1051
1052 func (r *importReader) signature(paramPkg *types.Package, recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {
1053 params := r.paramList(paramPkg)
1054 results := r.paramList(paramPkg)
1055 variadic := params.Len() > 0 && r.bool()
1056 return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
1057 }
1058
1059 func (r *importReader) tparamList() []*types.TypeParam {
1060 n := r.uint64()
1061 if n == 0 {
1062 return nil
1063 }
1064 xs := make([]*types.TypeParam, n)
1065 for i := range xs {
1066 // Note: the standard library importer is tolerant of nil types here,
1067 // though would panic in SetTypeParams.
1068 xs[i] = types.Unalias(r.typ()).(*types.TypeParam)
1069 }
1070 return xs
1071 }
1072
1073 func (r *importReader) paramList(pkg *types.Package) *types.Tuple {
1074 xs := make([]*types.Var, r.uint64())
1075 for i := range xs {
1076 xs[i] = r.param(pkg)
1077 }
1078 return types.NewTuple(xs...)
1079 }
1080
1081 func (r *importReader) param(pkg *types.Package) *types.Var {
1082 pos := r.pos()
1083 name := r.ident()
1084 typ := r.typ()
1085 return types.NewParam(pos, pkg, name, typ)
1086 }
1087
1088 func (r *importReader) bool() bool {
1089 return r.uint64() != 0
1090 }
1091
1092 func (r *importReader) int64() int64 {
1093 n, err := binary.ReadVarint(&r.declReader)
1094 if err != nil {
1095 errorf("readVarint: %v", err)
1096 }
1097 return n
1098 }
1099
1100 func (r *importReader) uint64() uint64 {
1101 n, err := binary.ReadUvarint(&r.declReader)
1102 if err != nil {
1103 errorf("readUvarint: %v", err)
1104 }
1105 return n
1106 }
1107
1108 func (r *importReader) byte() byte {
1109 x, err := r.declReader.ReadByte()
1110 if err != nil {
1111 errorf("declReader.ReadByte: %v", err)
1112 }
1113 return x
1114 }
1115
1116 type byPath []*types.Package
1117
1118 func (a byPath) Len() int { return len(a) }
1119 func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
1120 func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }
1121