...

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

Documentation: golang.org/x/tools/internal/gcimporter

     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  	"golang.org/x/tools/internal/aliases"
    26  	"golang.org/x/tools/internal/typesinternal"
    27  )
    28  
    29  type intReader struct {
    30  	*bytes.Reader
    31  	path string
    32  }
    33  
    34  func (r *intReader) int64() int64 {
    35  	i, err := binary.ReadVarint(r.Reader)
    36  	if err != nil {
    37  		errorf("import %q: read varint error: %v", r.path, err)
    38  	}
    39  	return i
    40  }
    41  
    42  func (r *intReader) uint64() uint64 {
    43  	i, err := binary.ReadUvarint(r.Reader)
    44  	if err != nil {
    45  		errorf("import %q: read varint error: %v", r.path, err)
    46  	}
    47  	return i
    48  }
    49  
    50  // Keep this in sync with constants in iexport.go.
    51  const (
    52  	iexportVersionGo1_11   = 0
    53  	iexportVersionPosCol   = 1
    54  	iexportVersionGo1_18   = 2
    55  	iexportVersionGenerics = 2
    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 := append(([]*types.Package)(nil), 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 ...interface{}) {
   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, currPkg: pkg}
   436  	r.declReader.Reset(p.declData[off:])
   437  
   438  	r.obj(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, _ := aliases.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  	currPkg    *types.Package
   555  	prevFile   string
   556  	prevLine   int64
   557  	prevColumn int64
   558  }
   559  
   560  func (r *importReader) obj(name string) {
   561  	tag := r.byte()
   562  	pos := r.pos()
   563  
   564  	switch tag {
   565  	case aliasTag:
   566  		typ := r.typ()
   567  		// TODO(adonovan): support generic aliases:
   568  		// if tag == genericAliasTag {
   569  		// 	tparams := r.tparamList()
   570  		// 	alias.SetTypeParams(tparams)
   571  		// }
   572  		r.declare(aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ))
   573  
   574  	case constTag:
   575  		typ, val := r.value()
   576  
   577  		r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
   578  
   579  	case funcTag, genericFuncTag:
   580  		var tparams []*types.TypeParam
   581  		if tag == genericFuncTag {
   582  			tparams = r.tparamList()
   583  		}
   584  		sig := r.signature(nil, nil, tparams)
   585  		r.declare(types.NewFunc(pos, r.currPkg, name, sig))
   586  
   587  	case typeTag, genericTypeTag:
   588  		// Types can be recursive. We need to setup a stub
   589  		// declaration before recursing.
   590  		obj := types.NewTypeName(pos, r.currPkg, name, nil)
   591  		named := types.NewNamed(obj, nil, nil)
   592  		// Declare obj before calling r.tparamList, so the new type name is recognized
   593  		// if used in the constraint of one of its own typeparams (see #48280).
   594  		r.declare(obj)
   595  		if tag == genericTypeTag {
   596  			tparams := r.tparamList()
   597  			named.SetTypeParams(tparams)
   598  		}
   599  
   600  		underlying := r.p.typAt(r.uint64(), named).Underlying()
   601  		named.SetUnderlying(underlying)
   602  
   603  		if !isInterface(underlying) {
   604  			for n := r.uint64(); n > 0; n-- {
   605  				mpos := r.pos()
   606  				mname := r.ident()
   607  				recv := r.param()
   608  
   609  				// If the receiver has any targs, set those as the
   610  				// rparams of the method (since those are the
   611  				// typeparams being used in the method sig/body).
   612  				_, recvNamed := typesinternal.ReceiverNamed(recv)
   613  				targs := recvNamed.TypeArgs()
   614  				var rparams []*types.TypeParam
   615  				if targs.Len() > 0 {
   616  					rparams = make([]*types.TypeParam, targs.Len())
   617  					for i := range rparams {
   618  						rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam)
   619  					}
   620  				}
   621  				msig := r.signature(recv, rparams, nil)
   622  
   623  				named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
   624  			}
   625  		}
   626  
   627  	case typeParamTag:
   628  		// We need to "declare" a typeparam in order to have a name that
   629  		// can be referenced recursively (if needed) in the type param's
   630  		// bound.
   631  		if r.p.version < iexportVersionGenerics {
   632  			errorf("unexpected type param type")
   633  		}
   634  		name0 := tparamName(name)
   635  		tn := types.NewTypeName(pos, r.currPkg, name0, nil)
   636  		t := types.NewTypeParam(tn, nil)
   637  
   638  		// To handle recursive references to the typeparam within its
   639  		// bound, save the partial type in tparamIndex before reading the bounds.
   640  		id := ident{r.currPkg, name}
   641  		r.p.tparamIndex[id] = t
   642  		var implicit bool
   643  		if r.p.version >= iexportVersionGo1_18 {
   644  			implicit = r.bool()
   645  		}
   646  		constraint := r.typ()
   647  		if implicit {
   648  			iface, _ := aliases.Unalias(constraint).(*types.Interface)
   649  			if iface == nil {
   650  				errorf("non-interface constraint marked implicit")
   651  			}
   652  			iface.MarkImplicit()
   653  		}
   654  		// The constraint type may not be complete, if we
   655  		// are in the middle of a type recursion involving type
   656  		// constraints. So, we defer SetConstraint until we have
   657  		// completely set up all types in ImportData.
   658  		r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
   659  
   660  	case varTag:
   661  		typ := r.typ()
   662  
   663  		r.declare(types.NewVar(pos, r.currPkg, name, typ))
   664  
   665  	default:
   666  		errorf("unexpected tag: %v", tag)
   667  	}
   668  }
   669  
   670  func (r *importReader) declare(obj types.Object) {
   671  	obj.Pkg().Scope().Insert(obj)
   672  }
   673  
   674  func (r *importReader) value() (typ types.Type, val constant.Value) {
   675  	typ = r.typ()
   676  	if r.p.version >= iexportVersionGo1_18 {
   677  		// TODO: add support for using the kind.
   678  		_ = constant.Kind(r.int64())
   679  	}
   680  
   681  	switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
   682  	case types.IsBoolean:
   683  		val = constant.MakeBool(r.bool())
   684  
   685  	case types.IsString:
   686  		val = constant.MakeString(r.string())
   687  
   688  	case types.IsInteger:
   689  		var x big.Int
   690  		r.mpint(&x, b)
   691  		val = constant.Make(&x)
   692  
   693  	case types.IsFloat:
   694  		val = r.mpfloat(b)
   695  
   696  	case types.IsComplex:
   697  		re := r.mpfloat(b)
   698  		im := r.mpfloat(b)
   699  		val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   700  
   701  	default:
   702  		if b.Kind() == types.Invalid {
   703  			val = constant.MakeUnknown()
   704  			return
   705  		}
   706  		errorf("unexpected type %v", typ) // panics
   707  		panic("unreachable")
   708  	}
   709  
   710  	return
   711  }
   712  
   713  func intSize(b *types.Basic) (signed bool, maxBytes uint) {
   714  	if (b.Info() & types.IsUntyped) != 0 {
   715  		return true, 64
   716  	}
   717  
   718  	switch b.Kind() {
   719  	case types.Float32, types.Complex64:
   720  		return true, 3
   721  	case types.Float64, types.Complex128:
   722  		return true, 7
   723  	}
   724  
   725  	signed = (b.Info() & types.IsUnsigned) == 0
   726  	switch b.Kind() {
   727  	case types.Int8, types.Uint8:
   728  		maxBytes = 1
   729  	case types.Int16, types.Uint16:
   730  		maxBytes = 2
   731  	case types.Int32, types.Uint32:
   732  		maxBytes = 4
   733  	default:
   734  		maxBytes = 8
   735  	}
   736  
   737  	return
   738  }
   739  
   740  func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
   741  	signed, maxBytes := intSize(typ)
   742  
   743  	maxSmall := 256 - maxBytes
   744  	if signed {
   745  		maxSmall = 256 - 2*maxBytes
   746  	}
   747  	if maxBytes == 1 {
   748  		maxSmall = 256
   749  	}
   750  
   751  	n, _ := r.declReader.ReadByte()
   752  	if uint(n) < maxSmall {
   753  		v := int64(n)
   754  		if signed {
   755  			v >>= 1
   756  			if n&1 != 0 {
   757  				v = ^v
   758  			}
   759  		}
   760  		x.SetInt64(v)
   761  		return
   762  	}
   763  
   764  	v := -n
   765  	if signed {
   766  		v = -(n &^ 1) >> 1
   767  	}
   768  	if v < 1 || uint(v) > maxBytes {
   769  		errorf("weird decoding: %v, %v => %v", n, signed, v)
   770  	}
   771  	b := make([]byte, v)
   772  	io.ReadFull(&r.declReader, b)
   773  	x.SetBytes(b)
   774  	if signed && n&1 != 0 {
   775  		x.Neg(x)
   776  	}
   777  }
   778  
   779  func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
   780  	var mant big.Int
   781  	r.mpint(&mant, typ)
   782  	var f big.Float
   783  	f.SetInt(&mant)
   784  	if f.Sign() != 0 {
   785  		f.SetMantExp(&f, int(r.int64()))
   786  	}
   787  	return constant.Make(&f)
   788  }
   789  
   790  func (r *importReader) ident() string {
   791  	return r.string()
   792  }
   793  
   794  func (r *importReader) qualifiedIdent() (*types.Package, string) {
   795  	name := r.string()
   796  	pkg := r.pkg()
   797  	return pkg, name
   798  }
   799  
   800  func (r *importReader) pos() token.Pos {
   801  	if r.p.shallow {
   802  		// precise offsets are encoded only in shallow mode
   803  		return r.posv2()
   804  	}
   805  	if r.p.version >= iexportVersionPosCol {
   806  		r.posv1()
   807  	} else {
   808  		r.posv0()
   809  	}
   810  
   811  	if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
   812  		return token.NoPos
   813  	}
   814  	return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
   815  }
   816  
   817  func (r *importReader) posv0() {
   818  	delta := r.int64()
   819  	if delta != deltaNewFile {
   820  		r.prevLine += delta
   821  	} else if l := r.int64(); l == -1 {
   822  		r.prevLine += deltaNewFile
   823  	} else {
   824  		r.prevFile = r.string()
   825  		r.prevLine = l
   826  	}
   827  }
   828  
   829  func (r *importReader) posv1() {
   830  	delta := r.int64()
   831  	r.prevColumn += delta >> 1
   832  	if delta&1 != 0 {
   833  		delta = r.int64()
   834  		r.prevLine += delta >> 1
   835  		if delta&1 != 0 {
   836  			r.prevFile = r.string()
   837  		}
   838  	}
   839  }
   840  
   841  func (r *importReader) posv2() token.Pos {
   842  	file := r.uint64()
   843  	if file == 0 {
   844  		return token.NoPos
   845  	}
   846  	tf := r.p.fileAt(file - 1)
   847  	return tf.Pos(int(r.uint64()))
   848  }
   849  
   850  func (r *importReader) typ() types.Type {
   851  	return r.p.typAt(r.uint64(), nil)
   852  }
   853  
   854  func isInterface(t types.Type) bool {
   855  	_, ok := aliases.Unalias(t).(*types.Interface)
   856  	return ok
   857  }
   858  
   859  func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
   860  func (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }
   861  
   862  func (r *importReader) doType(base *types.Named) (res types.Type) {
   863  	k := r.kind()
   864  	if debug {
   865  		r.p.trace("importing type %d (base: %s)", k, base)
   866  		r.p.indent++
   867  		defer func() {
   868  			r.p.indent--
   869  			r.p.trace("=> %s", res)
   870  		}()
   871  	}
   872  	switch k {
   873  	default:
   874  		errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
   875  		return nil
   876  
   877  	case aliasType, definedType:
   878  		pkg, name := r.qualifiedIdent()
   879  		r.p.doDecl(pkg, name)
   880  		return pkg.Scope().Lookup(name).(*types.TypeName).Type()
   881  	case pointerType:
   882  		return types.NewPointer(r.typ())
   883  	case sliceType:
   884  		return types.NewSlice(r.typ())
   885  	case arrayType:
   886  		n := r.uint64()
   887  		return types.NewArray(r.typ(), int64(n))
   888  	case chanType:
   889  		dir := chanDir(int(r.uint64()))
   890  		return types.NewChan(dir, r.typ())
   891  	case mapType:
   892  		return types.NewMap(r.typ(), r.typ())
   893  	case signatureType:
   894  		r.currPkg = r.pkg()
   895  		return r.signature(nil, nil, nil)
   896  
   897  	case structType:
   898  		r.currPkg = r.pkg()
   899  
   900  		fields := make([]*types.Var, r.uint64())
   901  		tags := make([]string, len(fields))
   902  		for i := range fields {
   903  			var field *types.Var
   904  			if r.p.shallow {
   905  				field, _ = r.objectPathObject().(*types.Var)
   906  			}
   907  
   908  			fpos := r.pos()
   909  			fname := r.ident()
   910  			ftyp := r.typ()
   911  			emb := r.bool()
   912  			tag := r.string()
   913  
   914  			// Either this is not a shallow import, the field is local, or the
   915  			// encoded objectPath failed to produce an object (a bug).
   916  			//
   917  			// Even in this last, buggy case, fall back on creating a new field. As
   918  			// discussed in iexport.go, this is not correct, but mostly works and is
   919  			// preferable to failing (for now at least).
   920  			if field == nil {
   921  				field = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
   922  			}
   923  
   924  			fields[i] = field
   925  			tags[i] = tag
   926  		}
   927  		return types.NewStruct(fields, tags)
   928  
   929  	case interfaceType:
   930  		r.currPkg = r.pkg()
   931  
   932  		embeddeds := make([]types.Type, r.uint64())
   933  		for i := range embeddeds {
   934  			_ = r.pos()
   935  			embeddeds[i] = r.typ()
   936  		}
   937  
   938  		methods := make([]*types.Func, r.uint64())
   939  		for i := range methods {
   940  			var method *types.Func
   941  			if r.p.shallow {
   942  				method, _ = r.objectPathObject().(*types.Func)
   943  			}
   944  
   945  			mpos := r.pos()
   946  			mname := r.ident()
   947  
   948  			// TODO(mdempsky): Matches bimport.go, but I
   949  			// don't agree with this.
   950  			var recv *types.Var
   951  			if base != nil {
   952  				recv = types.NewVar(token.NoPos, r.currPkg, "", base)
   953  			}
   954  			msig := r.signature(recv, nil, nil)
   955  
   956  			if method == nil {
   957  				method = types.NewFunc(mpos, r.currPkg, mname, msig)
   958  			}
   959  			methods[i] = method
   960  		}
   961  
   962  		typ := newInterface(methods, embeddeds)
   963  		r.p.interfaceList = append(r.p.interfaceList, typ)
   964  		return typ
   965  
   966  	case typeParamType:
   967  		if r.p.version < iexportVersionGenerics {
   968  			errorf("unexpected type param type")
   969  		}
   970  		pkg, name := r.qualifiedIdent()
   971  		id := ident{pkg, name}
   972  		if t, ok := r.p.tparamIndex[id]; ok {
   973  			// We're already in the process of importing this typeparam.
   974  			return t
   975  		}
   976  		// Otherwise, import the definition of the typeparam now.
   977  		r.p.doDecl(pkg, name)
   978  		return r.p.tparamIndex[id]
   979  
   980  	case instanceType:
   981  		if r.p.version < iexportVersionGenerics {
   982  			errorf("unexpected instantiation type")
   983  		}
   984  		// pos does not matter for instances: they are positioned on the original
   985  		// type.
   986  		_ = r.pos()
   987  		len := r.uint64()
   988  		targs := make([]types.Type, len)
   989  		for i := range targs {
   990  			targs[i] = r.typ()
   991  		}
   992  		baseType := r.typ()
   993  		// The imported instantiated type doesn't include any methods, so
   994  		// we must always use the methods of the base (orig) type.
   995  		// TODO provide a non-nil *Environment
   996  		t, _ := types.Instantiate(nil, baseType, targs, false)
   997  
   998  		// Workaround for golang/go#61561. See the doc for instanceList for details.
   999  		r.p.instanceList = append(r.p.instanceList, t)
  1000  		return t
  1001  
  1002  	case unionType:
  1003  		if r.p.version < iexportVersionGenerics {
  1004  			errorf("unexpected instantiation type")
  1005  		}
  1006  		terms := make([]*types.Term, r.uint64())
  1007  		for i := range terms {
  1008  			terms[i] = types.NewTerm(r.bool(), r.typ())
  1009  		}
  1010  		return types.NewUnion(terms)
  1011  	}
  1012  }
  1013  
  1014  func (r *importReader) kind() itag {
  1015  	return itag(r.uint64())
  1016  }
  1017  
  1018  // objectPathObject is the inverse of exportWriter.objectPath.
  1019  //
  1020  // In shallow mode, certain fields and methods may need to be looked up in an
  1021  // imported package. See the doc for exportWriter.objectPath for a full
  1022  // explanation.
  1023  func (r *importReader) objectPathObject() types.Object {
  1024  	objPath := objectpath.Path(r.string())
  1025  	if objPath == "" {
  1026  		return nil
  1027  	}
  1028  	pkg := r.pkg()
  1029  	obj, err := objectpath.Object(pkg, objPath)
  1030  	if err != nil {
  1031  		if r.p.reportf != nil {
  1032  			r.p.reportf("failed to find object for objectPath %q: %v", objPath, err)
  1033  		}
  1034  	}
  1035  	return obj
  1036  }
  1037  
  1038  func (r *importReader) signature(recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {
  1039  	params := r.paramList()
  1040  	results := r.paramList()
  1041  	variadic := params.Len() > 0 && r.bool()
  1042  	return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
  1043  }
  1044  
  1045  func (r *importReader) tparamList() []*types.TypeParam {
  1046  	n := r.uint64()
  1047  	if n == 0 {
  1048  		return nil
  1049  	}
  1050  	xs := make([]*types.TypeParam, n)
  1051  	for i := range xs {
  1052  		// Note: the standard library importer is tolerant of nil types here,
  1053  		// though would panic in SetTypeParams.
  1054  		xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam)
  1055  	}
  1056  	return xs
  1057  }
  1058  
  1059  func (r *importReader) paramList() *types.Tuple {
  1060  	xs := make([]*types.Var, r.uint64())
  1061  	for i := range xs {
  1062  		xs[i] = r.param()
  1063  	}
  1064  	return types.NewTuple(xs...)
  1065  }
  1066  
  1067  func (r *importReader) param() *types.Var {
  1068  	pos := r.pos()
  1069  	name := r.ident()
  1070  	typ := r.typ()
  1071  	return types.NewParam(pos, r.currPkg, name, typ)
  1072  }
  1073  
  1074  func (r *importReader) bool() bool {
  1075  	return r.uint64() != 0
  1076  }
  1077  
  1078  func (r *importReader) int64() int64 {
  1079  	n, err := binary.ReadVarint(&r.declReader)
  1080  	if err != nil {
  1081  		errorf("readVarint: %v", err)
  1082  	}
  1083  	return n
  1084  }
  1085  
  1086  func (r *importReader) uint64() uint64 {
  1087  	n, err := binary.ReadUvarint(&r.declReader)
  1088  	if err != nil {
  1089  		errorf("readUvarint: %v", err)
  1090  	}
  1091  	return n
  1092  }
  1093  
  1094  func (r *importReader) byte() byte {
  1095  	x, err := r.declReader.ReadByte()
  1096  	if err != nil {
  1097  		errorf("declReader.ReadByte: %v", err)
  1098  	}
  1099  	return x
  1100  }
  1101  

View as plain text