src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

iimport.go (29147B)


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