github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/go/internal/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  	"sort"
    21  	"strings"
    22  
    23  	"github.com/jhump/golang-x-tools/internal/typeparams"
    24  )
    25  
    26  type intReader struct {
    27  	*bytes.Reader
    28  	path string
    29  }
    30  
    31  func (r *intReader) int64() int64 {
    32  	i, err := binary.ReadVarint(r.Reader)
    33  	if err != nil {
    34  		errorf("import %q: read varint error: %v", r.path, err)
    35  	}
    36  	return i
    37  }
    38  
    39  func (r *intReader) uint64() uint64 {
    40  	i, err := binary.ReadUvarint(r.Reader)
    41  	if err != nil {
    42  		errorf("import %q: read varint error: %v", r.path, err)
    43  	}
    44  	return i
    45  }
    46  
    47  // Keep this in sync with constants in iexport.go.
    48  const (
    49  	iexportVersionGo1_11   = 0
    50  	iexportVersionPosCol   = 1
    51  	iexportVersionGo1_18   = 2
    52  	iexportVersionGenerics = 2
    53  )
    54  
    55  type ident struct {
    56  	pkg  string
    57  	name string
    58  }
    59  
    60  const predeclReserved = 32
    61  
    62  type itag uint64
    63  
    64  const (
    65  	// Types
    66  	definedType itag = iota
    67  	pointerType
    68  	sliceType
    69  	arrayType
    70  	chanType
    71  	mapType
    72  	signatureType
    73  	structType
    74  	interfaceType
    75  	typeParamType
    76  	instanceType
    77  	unionType
    78  )
    79  
    80  // IImportData imports a package from the serialized package data
    81  // and returns 0 and a reference to the package.
    82  // If the export data version is not recognized or the format is otherwise
    83  // compromised, an error is returned.
    84  func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
    85  	pkgs, err := iimportCommon(fset, imports, data, false, path)
    86  	if err != nil {
    87  		return 0, nil, err
    88  	}
    89  	return 0, pkgs[0], nil
    90  }
    91  
    92  // IImportBundle imports a set of packages from the serialized package bundle.
    93  func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
    94  	return iimportCommon(fset, imports, data, true, "")
    95  }
    96  
    97  func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string) (pkgs []*types.Package, err error) {
    98  	const currentVersion = 1
    99  	version := int64(-1)
   100  	if !debug {
   101  		defer func() {
   102  			if e := recover(); e != nil {
   103  				if version > currentVersion {
   104  					err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
   105  				} else {
   106  					err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
   107  				}
   108  			}
   109  		}()
   110  	}
   111  
   112  	r := &intReader{bytes.NewReader(data), path}
   113  
   114  	if bundle {
   115  		bundleVersion := r.uint64()
   116  		switch bundleVersion {
   117  		case bundleVersion:
   118  		default:
   119  			errorf("unknown bundle format version %d", bundleVersion)
   120  		}
   121  	}
   122  
   123  	version = int64(r.uint64())
   124  	switch version {
   125  	case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
   126  	default:
   127  		if version > iexportVersionGo1_18 {
   128  			errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
   129  		} else {
   130  			errorf("unknown iexport format version %d", version)
   131  		}
   132  	}
   133  
   134  	sLen := int64(r.uint64())
   135  	dLen := int64(r.uint64())
   136  
   137  	whence, _ := r.Seek(0, io.SeekCurrent)
   138  	stringData := data[whence : whence+sLen]
   139  	declData := data[whence+sLen : whence+sLen+dLen]
   140  	r.Seek(sLen+dLen, io.SeekCurrent)
   141  
   142  	p := iimporter{
   143  		version: int(version),
   144  		ipath:   path,
   145  
   146  		stringData:  stringData,
   147  		stringCache: make(map[uint64]string),
   148  		pkgCache:    make(map[uint64]*types.Package),
   149  
   150  		declData: declData,
   151  		pkgIndex: make(map[*types.Package]map[string]uint64),
   152  		typCache: make(map[uint64]types.Type),
   153  		// Separate map for typeparams, keyed by their package and unique
   154  		// name.
   155  		tparamIndex: make(map[ident]types.Type),
   156  
   157  		fake: fakeFileSet{
   158  			fset:  fset,
   159  			files: make(map[string]*fileInfo),
   160  		},
   161  	}
   162  	defer p.fake.setLines() // set lines for files in fset
   163  
   164  	for i, pt := range predeclared() {
   165  		p.typCache[uint64(i)] = pt
   166  	}
   167  
   168  	pkgList := make([]*types.Package, r.uint64())
   169  	for i := range pkgList {
   170  		pkgPathOff := r.uint64()
   171  		pkgPath := p.stringAt(pkgPathOff)
   172  		pkgName := p.stringAt(r.uint64())
   173  		_ = r.uint64() // package height; unused by go/types
   174  
   175  		if pkgPath == "" {
   176  			pkgPath = path
   177  		}
   178  		pkg := imports[pkgPath]
   179  		if pkg == nil {
   180  			pkg = types.NewPackage(pkgPath, pkgName)
   181  			imports[pkgPath] = pkg
   182  		} else if pkg.Name() != pkgName {
   183  			errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
   184  		}
   185  
   186  		p.pkgCache[pkgPathOff] = pkg
   187  
   188  		nameIndex := make(map[string]uint64)
   189  		for nSyms := r.uint64(); nSyms > 0; nSyms-- {
   190  			name := p.stringAt(r.uint64())
   191  			nameIndex[name] = r.uint64()
   192  		}
   193  
   194  		p.pkgIndex[pkg] = nameIndex
   195  		pkgList[i] = pkg
   196  	}
   197  
   198  	if bundle {
   199  		pkgs = make([]*types.Package, r.uint64())
   200  		for i := range pkgs {
   201  			pkg := p.pkgAt(r.uint64())
   202  			imps := make([]*types.Package, r.uint64())
   203  			for j := range imps {
   204  				imps[j] = p.pkgAt(r.uint64())
   205  			}
   206  			pkg.SetImports(imps)
   207  			pkgs[i] = pkg
   208  		}
   209  	} else {
   210  		if len(pkgList) == 0 {
   211  			errorf("no packages found for %s", path)
   212  			panic("unreachable")
   213  		}
   214  		pkgs = pkgList[:1]
   215  
   216  		// record all referenced packages as imports
   217  		list := append(([]*types.Package)(nil), pkgList[1:]...)
   218  		sort.Sort(byPath(list))
   219  		pkgs[0].SetImports(list)
   220  	}
   221  
   222  	for _, pkg := range pkgs {
   223  		if pkg.Complete() {
   224  			continue
   225  		}
   226  
   227  		names := make([]string, 0, len(p.pkgIndex[pkg]))
   228  		for name := range p.pkgIndex[pkg] {
   229  			names = append(names, name)
   230  		}
   231  		sort.Strings(names)
   232  		for _, name := range names {
   233  			p.doDecl(pkg, name)
   234  		}
   235  
   236  		// package was imported completely and without errors
   237  		pkg.MarkComplete()
   238  	}
   239  
   240  	for _, typ := range p.interfaceList {
   241  		typ.Complete()
   242  	}
   243  
   244  	return pkgs, nil
   245  }
   246  
   247  type iimporter struct {
   248  	version int
   249  	ipath   string
   250  
   251  	stringData  []byte
   252  	stringCache map[uint64]string
   253  	pkgCache    map[uint64]*types.Package
   254  
   255  	declData    []byte
   256  	pkgIndex    map[*types.Package]map[string]uint64
   257  	typCache    map[uint64]types.Type
   258  	tparamIndex map[ident]types.Type
   259  
   260  	fake          fakeFileSet
   261  	interfaceList []*types.Interface
   262  
   263  	indent int // for tracing support
   264  }
   265  
   266  func (p *iimporter) trace(format string, args ...interface{}) {
   267  	if !trace {
   268  		// Call sites should also be guarded, but having this check here allows
   269  		// easily enabling/disabling debug trace statements.
   270  		return
   271  	}
   272  	fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
   273  }
   274  
   275  func (p *iimporter) doDecl(pkg *types.Package, name string) {
   276  	if debug {
   277  		p.trace("import decl %s", name)
   278  		p.indent++
   279  		defer func() {
   280  			p.indent--
   281  			p.trace("=> %s", name)
   282  		}()
   283  	}
   284  	// See if we've already imported this declaration.
   285  	if obj := pkg.Scope().Lookup(name); obj != nil {
   286  		return
   287  	}
   288  
   289  	off, ok := p.pkgIndex[pkg][name]
   290  	if !ok {
   291  		errorf("%v.%v not in index", pkg, name)
   292  	}
   293  
   294  	r := &importReader{p: p, currPkg: pkg}
   295  	r.declReader.Reset(p.declData[off:])
   296  
   297  	r.obj(name)
   298  }
   299  
   300  func (p *iimporter) stringAt(off uint64) string {
   301  	if s, ok := p.stringCache[off]; ok {
   302  		return s
   303  	}
   304  
   305  	slen, n := binary.Uvarint(p.stringData[off:])
   306  	if n <= 0 {
   307  		errorf("varint failed")
   308  	}
   309  	spos := off + uint64(n)
   310  	s := string(p.stringData[spos : spos+slen])
   311  	p.stringCache[off] = s
   312  	return s
   313  }
   314  
   315  func (p *iimporter) pkgAt(off uint64) *types.Package {
   316  	if pkg, ok := p.pkgCache[off]; ok {
   317  		return pkg
   318  	}
   319  	path := p.stringAt(off)
   320  	errorf("missing package %q in %q", path, p.ipath)
   321  	return nil
   322  }
   323  
   324  func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
   325  	if t, ok := p.typCache[off]; ok && canReuse(base, t) {
   326  		return t
   327  	}
   328  
   329  	if off < predeclReserved {
   330  		errorf("predeclared type missing from cache: %v", off)
   331  	}
   332  
   333  	r := &importReader{p: p}
   334  	r.declReader.Reset(p.declData[off-predeclReserved:])
   335  	t := r.doType(base)
   336  
   337  	if canReuse(base, t) {
   338  		p.typCache[off] = t
   339  	}
   340  	return t
   341  }
   342  
   343  // canReuse reports whether the type rhs on the RHS of the declaration for def
   344  // may be re-used.
   345  //
   346  // Specifically, if def is non-nil and rhs is an interface type with methods, it
   347  // may not be re-used because we have a convention of setting the receiver type
   348  // for interface methods to def.
   349  func canReuse(def *types.Named, rhs types.Type) bool {
   350  	if def == nil {
   351  		return true
   352  	}
   353  	iface, _ := rhs.(*types.Interface)
   354  	if iface == nil {
   355  		return true
   356  	}
   357  	// Don't use iface.Empty() here as iface may not be complete.
   358  	return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
   359  }
   360  
   361  type importReader struct {
   362  	p          *iimporter
   363  	declReader bytes.Reader
   364  	currPkg    *types.Package
   365  	prevFile   string
   366  	prevLine   int64
   367  	prevColumn int64
   368  }
   369  
   370  func (r *importReader) obj(name string) {
   371  	tag := r.byte()
   372  	pos := r.pos()
   373  
   374  	switch tag {
   375  	case 'A':
   376  		typ := r.typ()
   377  
   378  		r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
   379  
   380  	case 'C':
   381  		typ, val := r.value()
   382  
   383  		r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
   384  
   385  	case 'F', 'G':
   386  		var tparams []*typeparams.TypeParam
   387  		if tag == 'G' {
   388  			tparams = r.tparamList()
   389  		}
   390  		sig := r.signature(nil, nil, tparams)
   391  		r.declare(types.NewFunc(pos, r.currPkg, name, sig))
   392  
   393  	case 'T', 'U':
   394  		// Types can be recursive. We need to setup a stub
   395  		// declaration before recursing.
   396  		obj := types.NewTypeName(pos, r.currPkg, name, nil)
   397  		named := types.NewNamed(obj, nil, nil)
   398  		// Declare obj before calling r.tparamList, so the new type name is recognized
   399  		// if used in the constraint of one of its own typeparams (see #48280).
   400  		r.declare(obj)
   401  		if tag == 'U' {
   402  			tparams := r.tparamList()
   403  			typeparams.SetForNamed(named, tparams)
   404  		}
   405  
   406  		underlying := r.p.typAt(r.uint64(), named).Underlying()
   407  		named.SetUnderlying(underlying)
   408  
   409  		if !isInterface(underlying) {
   410  			for n := r.uint64(); n > 0; n-- {
   411  				mpos := r.pos()
   412  				mname := r.ident()
   413  				recv := r.param()
   414  
   415  				// If the receiver has any targs, set those as the
   416  				// rparams of the method (since those are the
   417  				// typeparams being used in the method sig/body).
   418  				base := baseType(recv.Type())
   419  				assert(base != nil)
   420  				targs := typeparams.NamedTypeArgs(base)
   421  				var rparams []*typeparams.TypeParam
   422  				if targs.Len() > 0 {
   423  					rparams = make([]*typeparams.TypeParam, targs.Len())
   424  					for i := range rparams {
   425  						rparams[i] = targs.At(i).(*typeparams.TypeParam)
   426  					}
   427  				}
   428  				msig := r.signature(recv, rparams, nil)
   429  
   430  				named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
   431  			}
   432  		}
   433  
   434  	case 'P':
   435  		// We need to "declare" a typeparam in order to have a name that
   436  		// can be referenced recursively (if needed) in the type param's
   437  		// bound.
   438  		if r.p.version < iexportVersionGenerics {
   439  			errorf("unexpected type param type")
   440  		}
   441  		name0 := tparamName(name)
   442  		tn := types.NewTypeName(pos, r.currPkg, name0, nil)
   443  		t := typeparams.NewTypeParam(tn, nil)
   444  
   445  		// To handle recursive references to the typeparam within its
   446  		// bound, save the partial type in tparamIndex before reading the bounds.
   447  		id := ident{r.currPkg.Name(), name}
   448  		r.p.tparamIndex[id] = t
   449  		var implicit bool
   450  		if r.p.version >= iexportVersionGo1_18 {
   451  			implicit = r.bool()
   452  		}
   453  		constraint := r.typ()
   454  		if implicit {
   455  			iface, _ := constraint.(*types.Interface)
   456  			if iface == nil {
   457  				errorf("non-interface constraint marked implicit")
   458  			}
   459  			typeparams.MarkImplicit(iface)
   460  		}
   461  		typeparams.SetTypeParamConstraint(t, constraint)
   462  
   463  	case 'V':
   464  		typ := r.typ()
   465  
   466  		r.declare(types.NewVar(pos, r.currPkg, name, typ))
   467  
   468  	default:
   469  		errorf("unexpected tag: %v", tag)
   470  	}
   471  }
   472  
   473  func (r *importReader) declare(obj types.Object) {
   474  	obj.Pkg().Scope().Insert(obj)
   475  }
   476  
   477  func (r *importReader) value() (typ types.Type, val constant.Value) {
   478  	typ = r.typ()
   479  	if r.p.version >= iexportVersionGo1_18 {
   480  		// TODO: add support for using the kind.
   481  		_ = constant.Kind(r.int64())
   482  	}
   483  
   484  	switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
   485  	case types.IsBoolean:
   486  		val = constant.MakeBool(r.bool())
   487  
   488  	case types.IsString:
   489  		val = constant.MakeString(r.string())
   490  
   491  	case types.IsInteger:
   492  		val = r.mpint(b)
   493  
   494  	case types.IsFloat:
   495  		val = r.mpfloat(b)
   496  
   497  	case types.IsComplex:
   498  		re := r.mpfloat(b)
   499  		im := r.mpfloat(b)
   500  		val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   501  
   502  	default:
   503  		if b.Kind() == types.Invalid {
   504  			val = constant.MakeUnknown()
   505  			return
   506  		}
   507  		errorf("unexpected type %v", typ) // panics
   508  		panic("unreachable")
   509  	}
   510  
   511  	return
   512  }
   513  
   514  func intSize(b *types.Basic) (signed bool, maxBytes uint) {
   515  	if (b.Info() & types.IsUntyped) != 0 {
   516  		return true, 64
   517  	}
   518  
   519  	switch b.Kind() {
   520  	case types.Float32, types.Complex64:
   521  		return true, 3
   522  	case types.Float64, types.Complex128:
   523  		return true, 7
   524  	}
   525  
   526  	signed = (b.Info() & types.IsUnsigned) == 0
   527  	switch b.Kind() {
   528  	case types.Int8, types.Uint8:
   529  		maxBytes = 1
   530  	case types.Int16, types.Uint16:
   531  		maxBytes = 2
   532  	case types.Int32, types.Uint32:
   533  		maxBytes = 4
   534  	default:
   535  		maxBytes = 8
   536  	}
   537  
   538  	return
   539  }
   540  
   541  func (r *importReader) mpint(b *types.Basic) constant.Value {
   542  	signed, maxBytes := intSize(b)
   543  
   544  	maxSmall := 256 - maxBytes
   545  	if signed {
   546  		maxSmall = 256 - 2*maxBytes
   547  	}
   548  	if maxBytes == 1 {
   549  		maxSmall = 256
   550  	}
   551  
   552  	n, _ := r.declReader.ReadByte()
   553  	if uint(n) < maxSmall {
   554  		v := int64(n)
   555  		if signed {
   556  			v >>= 1
   557  			if n&1 != 0 {
   558  				v = ^v
   559  			}
   560  		}
   561  		return constant.MakeInt64(v)
   562  	}
   563  
   564  	v := -n
   565  	if signed {
   566  		v = -(n &^ 1) >> 1
   567  	}
   568  	if v < 1 || uint(v) > maxBytes {
   569  		errorf("weird decoding: %v, %v => %v", n, signed, v)
   570  	}
   571  
   572  	buf := make([]byte, v)
   573  	io.ReadFull(&r.declReader, buf)
   574  
   575  	// convert to little endian
   576  	// TODO(gri) go/constant should have a more direct conversion function
   577  	//           (e.g., once it supports a big.Float based implementation)
   578  	for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
   579  		buf[i], buf[j] = buf[j], buf[i]
   580  	}
   581  
   582  	x := constant.MakeFromBytes(buf)
   583  	if signed && n&1 != 0 {
   584  		x = constant.UnaryOp(token.SUB, x, 0)
   585  	}
   586  	return x
   587  }
   588  
   589  func (r *importReader) mpfloat(b *types.Basic) constant.Value {
   590  	x := r.mpint(b)
   591  	if constant.Sign(x) == 0 {
   592  		return x
   593  	}
   594  
   595  	exp := r.int64()
   596  	switch {
   597  	case exp > 0:
   598  		x = constant.Shift(x, token.SHL, uint(exp))
   599  		// Ensure that the imported Kind is Float, else this constant may run into
   600  		// bitsize limits on overlarge integers. Eventually we can instead adopt
   601  		// the approach of CL 288632, but that CL relies on go/constant APIs that
   602  		// were introduced in go1.13.
   603  		//
   604  		// TODO(rFindley): sync the logic here with tip Go once we no longer
   605  		// support go1.12.
   606  		x = constant.ToFloat(x)
   607  	case exp < 0:
   608  		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
   609  		x = constant.BinaryOp(x, token.QUO, d)
   610  	}
   611  	return x
   612  }
   613  
   614  func (r *importReader) ident() string {
   615  	return r.string()
   616  }
   617  
   618  func (r *importReader) qualifiedIdent() (*types.Package, string) {
   619  	name := r.string()
   620  	pkg := r.pkg()
   621  	return pkg, name
   622  }
   623  
   624  func (r *importReader) pos() token.Pos {
   625  	if r.p.version >= iexportVersionPosCol {
   626  		r.posv1()
   627  	} else {
   628  		r.posv0()
   629  	}
   630  
   631  	if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
   632  		return token.NoPos
   633  	}
   634  	return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
   635  }
   636  
   637  func (r *importReader) posv0() {
   638  	delta := r.int64()
   639  	if delta != deltaNewFile {
   640  		r.prevLine += delta
   641  	} else if l := r.int64(); l == -1 {
   642  		r.prevLine += deltaNewFile
   643  	} else {
   644  		r.prevFile = r.string()
   645  		r.prevLine = l
   646  	}
   647  }
   648  
   649  func (r *importReader) posv1() {
   650  	delta := r.int64()
   651  	r.prevColumn += delta >> 1
   652  	if delta&1 != 0 {
   653  		delta = r.int64()
   654  		r.prevLine += delta >> 1
   655  		if delta&1 != 0 {
   656  			r.prevFile = r.string()
   657  		}
   658  	}
   659  }
   660  
   661  func (r *importReader) typ() types.Type {
   662  	return r.p.typAt(r.uint64(), nil)
   663  }
   664  
   665  func isInterface(t types.Type) bool {
   666  	_, ok := t.(*types.Interface)
   667  	return ok
   668  }
   669  
   670  func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
   671  func (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }
   672  
   673  func (r *importReader) doType(base *types.Named) (res types.Type) {
   674  	k := r.kind()
   675  	if debug {
   676  		r.p.trace("importing type %d (base: %s)", k, base)
   677  		r.p.indent++
   678  		defer func() {
   679  			r.p.indent--
   680  			r.p.trace("=> %s", res)
   681  		}()
   682  	}
   683  	switch k {
   684  	default:
   685  		errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
   686  		return nil
   687  
   688  	case definedType:
   689  		pkg, name := r.qualifiedIdent()
   690  		r.p.doDecl(pkg, name)
   691  		return pkg.Scope().Lookup(name).(*types.TypeName).Type()
   692  	case pointerType:
   693  		return types.NewPointer(r.typ())
   694  	case sliceType:
   695  		return types.NewSlice(r.typ())
   696  	case arrayType:
   697  		n := r.uint64()
   698  		return types.NewArray(r.typ(), int64(n))
   699  	case chanType:
   700  		dir := chanDir(int(r.uint64()))
   701  		return types.NewChan(dir, r.typ())
   702  	case mapType:
   703  		return types.NewMap(r.typ(), r.typ())
   704  	case signatureType:
   705  		r.currPkg = r.pkg()
   706  		return r.signature(nil, nil, nil)
   707  
   708  	case structType:
   709  		r.currPkg = r.pkg()
   710  
   711  		fields := make([]*types.Var, r.uint64())
   712  		tags := make([]string, len(fields))
   713  		for i := range fields {
   714  			fpos := r.pos()
   715  			fname := r.ident()
   716  			ftyp := r.typ()
   717  			emb := r.bool()
   718  			tag := r.string()
   719  
   720  			fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
   721  			tags[i] = tag
   722  		}
   723  		return types.NewStruct(fields, tags)
   724  
   725  	case interfaceType:
   726  		r.currPkg = r.pkg()
   727  
   728  		embeddeds := make([]types.Type, r.uint64())
   729  		for i := range embeddeds {
   730  			_ = r.pos()
   731  			embeddeds[i] = r.typ()
   732  		}
   733  
   734  		methods := make([]*types.Func, r.uint64())
   735  		for i := range methods {
   736  			mpos := r.pos()
   737  			mname := r.ident()
   738  
   739  			// TODO(mdempsky): Matches bimport.go, but I
   740  			// don't agree with this.
   741  			var recv *types.Var
   742  			if base != nil {
   743  				recv = types.NewVar(token.NoPos, r.currPkg, "", base)
   744  			}
   745  
   746  			msig := r.signature(recv, nil, nil)
   747  			methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
   748  		}
   749  
   750  		typ := newInterface(methods, embeddeds)
   751  		r.p.interfaceList = append(r.p.interfaceList, typ)
   752  		return typ
   753  
   754  	case typeParamType:
   755  		if r.p.version < iexportVersionGenerics {
   756  			errorf("unexpected type param type")
   757  		}
   758  		pkg, name := r.qualifiedIdent()
   759  		id := ident{pkg.Name(), name}
   760  		if t, ok := r.p.tparamIndex[id]; ok {
   761  			// We're already in the process of importing this typeparam.
   762  			return t
   763  		}
   764  		// Otherwise, import the definition of the typeparam now.
   765  		r.p.doDecl(pkg, name)
   766  		return r.p.tparamIndex[id]
   767  
   768  	case instanceType:
   769  		if r.p.version < iexportVersionGenerics {
   770  			errorf("unexpected instantiation type")
   771  		}
   772  		// pos does not matter for instances: they are positioned on the original
   773  		// type.
   774  		_ = r.pos()
   775  		len := r.uint64()
   776  		targs := make([]types.Type, len)
   777  		for i := range targs {
   778  			targs[i] = r.typ()
   779  		}
   780  		baseType := r.typ()
   781  		// The imported instantiated type doesn't include any methods, so
   782  		// we must always use the methods of the base (orig) type.
   783  		// TODO provide a non-nil *Environment
   784  		t, _ := typeparams.Instantiate(nil, baseType, targs, false)
   785  		return t
   786  
   787  	case unionType:
   788  		if r.p.version < iexportVersionGenerics {
   789  			errorf("unexpected instantiation type")
   790  		}
   791  		terms := make([]*typeparams.Term, r.uint64())
   792  		for i := range terms {
   793  			terms[i] = typeparams.NewTerm(r.bool(), r.typ())
   794  		}
   795  		return typeparams.NewUnion(terms)
   796  	}
   797  }
   798  
   799  func (r *importReader) kind() itag {
   800  	return itag(r.uint64())
   801  }
   802  
   803  func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature {
   804  	params := r.paramList()
   805  	results := r.paramList()
   806  	variadic := params.Len() > 0 && r.bool()
   807  	return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic)
   808  }
   809  
   810  func (r *importReader) tparamList() []*typeparams.TypeParam {
   811  	n := r.uint64()
   812  	if n == 0 {
   813  		return nil
   814  	}
   815  	xs := make([]*typeparams.TypeParam, n)
   816  	for i := range xs {
   817  		// Note: the standard library importer is tolerant of nil types here,
   818  		// though would panic in SetTypeParams.
   819  		xs[i] = r.typ().(*typeparams.TypeParam)
   820  	}
   821  	return xs
   822  }
   823  
   824  func (r *importReader) paramList() *types.Tuple {
   825  	xs := make([]*types.Var, r.uint64())
   826  	for i := range xs {
   827  		xs[i] = r.param()
   828  	}
   829  	return types.NewTuple(xs...)
   830  }
   831  
   832  func (r *importReader) param() *types.Var {
   833  	pos := r.pos()
   834  	name := r.ident()
   835  	typ := r.typ()
   836  	return types.NewParam(pos, r.currPkg, name, typ)
   837  }
   838  
   839  func (r *importReader) bool() bool {
   840  	return r.uint64() != 0
   841  }
   842  
   843  func (r *importReader) int64() int64 {
   844  	n, err := binary.ReadVarint(&r.declReader)
   845  	if err != nil {
   846  		errorf("readVarint: %v", err)
   847  	}
   848  	return n
   849  }
   850  
   851  func (r *importReader) uint64() uint64 {
   852  	n, err := binary.ReadUvarint(&r.declReader)
   853  	if err != nil {
   854  		errorf("readUvarint: %v", err)
   855  	}
   856  	return n
   857  }
   858  
   859  func (r *importReader) byte() byte {
   860  	x, err := r.declReader.ReadByte()
   861  	if err != nil {
   862  		errorf("declReader.ReadByte: %v", err)
   863  	}
   864  	return x
   865  }
   866  
   867  func baseType(typ types.Type) *types.Named {
   868  	// pointer receivers are never types.Named types
   869  	if p, _ := typ.(*types.Pointer); p != nil {
   870  		typ = p.Elem()
   871  	}
   872  	// receiver base types are always (possibly generic) types.Named types
   873  	n, _ := typ.(*types.Named)
   874  	return n
   875  }