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