Source file src/cmd/vendor/golang.org/x/tools/internal/gcimporter/iimport.go

     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() }
  1123  

View as plain text