cuelang.org/go@v0.10.1/internal/golangorgx/tools/gcimporter/iimport.go (about)

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