Source file src/go/internal/gcimporter/iimport.go

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

View as plain text