...

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

Documentation: go/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  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  	"slices"
    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  	slices.Sort(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  	slices.SortFunc(list, func(a, b *types.Package) int {
   209  		return strings.Compare(a.Path(), b.Path())
   210  	})
   211  	localpkg.SetImports(list)
   212  
   213  	// package was imported completely and without errors
   214  	localpkg.MarkComplete()
   215  	return localpkg, nil
   216  }
   217  
   218  type setConstraintArgs struct {
   219  	t          *types.TypeParam
   220  	constraint types.Type
   221  }
   222  
   223  type iimporter struct {
   224  	exportVersion int64
   225  	ipath         string
   226  	version       int
   227  
   228  	stringData  []byte
   229  	stringCache map[uint64]string
   230  	pkgCache    map[uint64]*types.Package
   231  
   232  	declData    []byte
   233  	pkgIndex    map[*types.Package]map[string]uint64
   234  	typCache    map[uint64]types.Type
   235  	tparamIndex map[ident]*types.TypeParam
   236  
   237  	fake          fakeFileSet
   238  	interfaceList []*types.Interface
   239  
   240  	// Arguments for calls to SetConstraint that are deferred due to recursive types
   241  	later []setConstraintArgs
   242  }
   243  
   244  func (p *iimporter) doDecl(pkg *types.Package, name string) {
   245  	// See if we've already imported this declaration.
   246  	if obj := pkg.Scope().Lookup(name); obj != nil {
   247  		return
   248  	}
   249  
   250  	off, ok := p.pkgIndex[pkg][name]
   251  	if !ok {
   252  		errorf("%v.%v not in index", pkg, name)
   253  	}
   254  
   255  	r := &importReader{p: p, currPkg: pkg}
   256  	r.declReader.Reset(p.declData[off:])
   257  
   258  	r.obj(name)
   259  }
   260  
   261  func (p *iimporter) stringAt(off uint64) string {
   262  	if s, ok := p.stringCache[off]; ok {
   263  		return s
   264  	}
   265  
   266  	slen, n := binary.Uvarint(p.stringData[off:])
   267  	if n <= 0 {
   268  		errorf("varint failed")
   269  	}
   270  	spos := off + uint64(n)
   271  	s := string(p.stringData[spos : spos+slen])
   272  	p.stringCache[off] = s
   273  	return s
   274  }
   275  
   276  func (p *iimporter) pkgAt(off uint64) *types.Package {
   277  	if pkg, ok := p.pkgCache[off]; ok {
   278  		return pkg
   279  	}
   280  	path := p.stringAt(off)
   281  	errorf("missing package %q in %q", path, p.ipath)
   282  	return nil
   283  }
   284  
   285  func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
   286  	if t, ok := p.typCache[off]; ok && canReuse(base, t) {
   287  		return t
   288  	}
   289  
   290  	if off < predeclReserved {
   291  		errorf("predeclared type missing from cache: %v", off)
   292  	}
   293  
   294  	r := &importReader{p: p}
   295  	r.declReader.Reset(p.declData[off-predeclReserved:])
   296  	t := r.doType(base)
   297  
   298  	if canReuse(base, t) {
   299  		p.typCache[off] = t
   300  	}
   301  	return t
   302  }
   303  
   304  // canReuse reports whether the type rhs on the RHS of the declaration for def
   305  // may be re-used.
   306  //
   307  // Specifically, if def is non-nil and rhs is an interface type with methods, it
   308  // may not be re-used because we have a convention of setting the receiver type
   309  // for interface methods to def.
   310  func canReuse(def *types.Named, rhs types.Type) bool {
   311  	if def == nil {
   312  		return true
   313  	}
   314  	iface, _ := rhs.(*types.Interface)
   315  	if iface == nil {
   316  		return true
   317  	}
   318  	// Don't use iface.Empty() here as iface may not be complete.
   319  	return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
   320  }
   321  
   322  type importReader struct {
   323  	p          *iimporter
   324  	declReader bytes.Reader
   325  	currPkg    *types.Package
   326  	prevFile   string
   327  	prevLine   int64
   328  	prevColumn int64
   329  }
   330  
   331  func (r *importReader) obj(name string) {
   332  	tag := r.byte()
   333  	pos := r.pos()
   334  
   335  	switch tag {
   336  	case 'A':
   337  		typ := r.typ()
   338  
   339  		r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
   340  
   341  	case 'C':
   342  		typ, val := r.value()
   343  
   344  		r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
   345  
   346  	case 'F', 'G':
   347  		var tparams []*types.TypeParam
   348  		if tag == 'G' {
   349  			tparams = r.tparamList()
   350  		}
   351  		sig := r.signature(nil, nil, tparams)
   352  		r.declare(types.NewFunc(pos, r.currPkg, name, sig))
   353  
   354  	case 'T', 'U':
   355  		// Types can be recursive. We need to setup a stub
   356  		// declaration before recurring.
   357  		obj := types.NewTypeName(pos, r.currPkg, name, nil)
   358  		named := types.NewNamed(obj, nil, nil)
   359  		// Declare obj before calling r.tparamList, so the new type name is recognized
   360  		// if used in the constraint of one of its own typeparams (see #48280).
   361  		r.declare(obj)
   362  		if tag == 'U' {
   363  			tparams := r.tparamList()
   364  			named.SetTypeParams(tparams)
   365  		}
   366  
   367  		underlying := r.p.typAt(r.uint64(), named).Underlying()
   368  		named.SetUnderlying(underlying)
   369  
   370  		if !isInterface(underlying) {
   371  			for n := r.uint64(); n > 0; n-- {
   372  				mpos := r.pos()
   373  				mname := r.ident()
   374  				recv := r.param()
   375  
   376  				// If the receiver has any targs, set those as the
   377  				// rparams of the method (since those are the
   378  				// typeparams being used in the method sig/body).
   379  				targs := baseType(recv.Type()).TypeArgs()
   380  				var rparams []*types.TypeParam
   381  				if targs.Len() > 0 {
   382  					rparams = make([]*types.TypeParam, targs.Len())
   383  					for i := range rparams {
   384  						rparams[i], _ = targs.At(i).(*types.TypeParam)
   385  					}
   386  				}
   387  				msig := r.signature(recv, rparams, nil)
   388  
   389  				named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
   390  			}
   391  		}
   392  
   393  	case 'P':
   394  		// We need to "declare" a typeparam in order to have a name that
   395  		// can be referenced recursively (if needed) in the type param's
   396  		// bound.
   397  		if r.p.exportVersion < iexportVersionGenerics {
   398  			errorf("unexpected type param type")
   399  		}
   400  		// Remove the "path" from the type param name that makes it unique,
   401  		// and revert any unique name used for blank typeparams.
   402  		name0 := tparamName(name)
   403  		tn := types.NewTypeName(pos, r.currPkg, name0, nil)
   404  		t := types.NewTypeParam(tn, nil)
   405  		// To handle recursive references to the typeparam within its
   406  		// bound, save the partial type in tparamIndex before reading the bounds.
   407  		id := ident{r.currPkg, name}
   408  		r.p.tparamIndex[id] = t
   409  
   410  		var implicit bool
   411  		if r.p.exportVersion >= iexportVersionGo1_18 {
   412  			implicit = r.bool()
   413  		}
   414  		constraint := r.typ()
   415  		if implicit {
   416  			iface, _ := constraint.(*types.Interface)
   417  			if iface == nil {
   418  				errorf("non-interface constraint marked implicit")
   419  			}
   420  			iface.MarkImplicit()
   421  		}
   422  		// The constraint type may not be complete, if we
   423  		// are in the middle of a type recursion involving type
   424  		// constraints. So, we defer SetConstraint until we have
   425  		// completely set up all types in ImportData.
   426  		r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
   427  
   428  	case 'V':
   429  		typ := r.typ()
   430  
   431  		r.declare(types.NewVar(pos, r.currPkg, name, typ))
   432  
   433  	default:
   434  		errorf("unexpected tag: %v", tag)
   435  	}
   436  }
   437  
   438  func (r *importReader) declare(obj types.Object) {
   439  	obj.Pkg().Scope().Insert(obj)
   440  }
   441  
   442  func (r *importReader) value() (typ types.Type, val constant.Value) {
   443  	typ = r.typ()
   444  	if r.p.exportVersion >= iexportVersionGo1_18 {
   445  		// TODO: add support for using the kind
   446  		_ = constant.Kind(r.int64())
   447  	}
   448  
   449  	switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
   450  	case types.IsBoolean:
   451  		val = constant.MakeBool(r.bool())
   452  
   453  	case types.IsString:
   454  		val = constant.MakeString(r.string())
   455  
   456  	case types.IsInteger:
   457  		var x big.Int
   458  		r.mpint(&x, b)
   459  		val = constant.Make(&x)
   460  
   461  	case types.IsFloat:
   462  		val = r.mpfloat(b)
   463  
   464  	case types.IsComplex:
   465  		re := r.mpfloat(b)
   466  		im := r.mpfloat(b)
   467  		val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   468  
   469  	default:
   470  		errorf("unexpected type %v", typ) // panics
   471  		panic("unreachable")
   472  	}
   473  
   474  	return
   475  }
   476  
   477  func intSize(b *types.Basic) (signed bool, maxBytes uint) {
   478  	if (b.Info() & types.IsUntyped) != 0 {
   479  		return true, 64
   480  	}
   481  
   482  	switch b.Kind() {
   483  	case types.Float32, types.Complex64:
   484  		return true, 3
   485  	case types.Float64, types.Complex128:
   486  		return true, 7
   487  	}
   488  
   489  	signed = (b.Info() & types.IsUnsigned) == 0
   490  	switch b.Kind() {
   491  	case types.Int8, types.Uint8:
   492  		maxBytes = 1
   493  	case types.Int16, types.Uint16:
   494  		maxBytes = 2
   495  	case types.Int32, types.Uint32:
   496  		maxBytes = 4
   497  	default:
   498  		maxBytes = 8
   499  	}
   500  
   501  	return
   502  }
   503  
   504  func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
   505  	signed, maxBytes := intSize(typ)
   506  
   507  	maxSmall := 256 - maxBytes
   508  	if signed {
   509  		maxSmall = 256 - 2*maxBytes
   510  	}
   511  	if maxBytes == 1 {
   512  		maxSmall = 256
   513  	}
   514  
   515  	n, _ := r.declReader.ReadByte()
   516  	if uint(n) < maxSmall {
   517  		v := int64(n)
   518  		if signed {
   519  			v >>= 1
   520  			if n&1 != 0 {
   521  				v = ^v
   522  			}
   523  		}
   524  		x.SetInt64(v)
   525  		return
   526  	}
   527  
   528  	v := -n
   529  	if signed {
   530  		v = -(n &^ 1) >> 1
   531  	}
   532  	if v < 1 || uint(v) > maxBytes {
   533  		errorf("weird decoding: %v, %v => %v", n, signed, v)
   534  	}
   535  	b := make([]byte, v)
   536  	io.ReadFull(&r.declReader, b)
   537  	x.SetBytes(b)
   538  	if signed && n&1 != 0 {
   539  		x.Neg(x)
   540  	}
   541  }
   542  
   543  func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
   544  	var mant big.Int
   545  	r.mpint(&mant, typ)
   546  	var f big.Float
   547  	f.SetInt(&mant)
   548  	if f.Sign() != 0 {
   549  		f.SetMantExp(&f, int(r.int64()))
   550  	}
   551  	return constant.Make(&f)
   552  }
   553  
   554  func (r *importReader) ident() string {
   555  	return r.string()
   556  }
   557  
   558  func (r *importReader) qualifiedIdent() (*types.Package, string) {
   559  	name := r.string()
   560  	pkg := r.pkg()
   561  	return pkg, name
   562  }
   563  
   564  func (r *importReader) pos() token.Pos {
   565  	if r.p.version >= 1 {
   566  		r.posv1()
   567  	} else {
   568  		r.posv0()
   569  	}
   570  
   571  	if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
   572  		return token.NoPos
   573  	}
   574  	return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
   575  }
   576  
   577  func (r *importReader) posv0() {
   578  	delta := r.int64()
   579  	if delta != deltaNewFile {
   580  		r.prevLine += delta
   581  	} else if l := r.int64(); l == -1 {
   582  		r.prevLine += deltaNewFile
   583  	} else {
   584  		r.prevFile = r.string()
   585  		r.prevLine = l
   586  	}
   587  }
   588  
   589  func (r *importReader) posv1() {
   590  	delta := r.int64()
   591  	r.prevColumn += delta >> 1
   592  	if delta&1 != 0 {
   593  		delta = r.int64()
   594  		r.prevLine += delta >> 1
   595  		if delta&1 != 0 {
   596  			r.prevFile = r.string()
   597  		}
   598  	}
   599  }
   600  
   601  func (r *importReader) typ() types.Type {
   602  	return r.p.typAt(r.uint64(), nil)
   603  }
   604  
   605  func isInterface(t types.Type) bool {
   606  	_, ok := t.(*types.Interface)
   607  	return ok
   608  }
   609  
   610  func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
   611  func (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }
   612  
   613  func (r *importReader) doType(base *types.Named) types.Type {
   614  	switch k := r.kind(); k {
   615  	default:
   616  		errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
   617  		return nil
   618  
   619  	case definedType:
   620  		pkg, name := r.qualifiedIdent()
   621  		r.p.doDecl(pkg, name)
   622  		return pkg.Scope().Lookup(name).(*types.TypeName).Type()
   623  	case pointerType:
   624  		return types.NewPointer(r.typ())
   625  	case sliceType:
   626  		return types.NewSlice(r.typ())
   627  	case arrayType:
   628  		n := r.uint64()
   629  		return types.NewArray(r.typ(), int64(n))
   630  	case chanType:
   631  		dir := chanDir(int(r.uint64()))
   632  		return types.NewChan(dir, r.typ())
   633  	case mapType:
   634  		return types.NewMap(r.typ(), r.typ())
   635  	case signatureType:
   636  		r.currPkg = r.pkg()
   637  		return r.signature(nil, nil, nil)
   638  
   639  	case structType:
   640  		r.currPkg = r.pkg()
   641  
   642  		fields := make([]*types.Var, r.uint64())
   643  		tags := make([]string, len(fields))
   644  		for i := range fields {
   645  			fpos := r.pos()
   646  			fname := r.ident()
   647  			ftyp := r.typ()
   648  			emb := r.bool()
   649  			tag := r.string()
   650  
   651  			fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
   652  			tags[i] = tag
   653  		}
   654  		return types.NewStruct(fields, tags)
   655  
   656  	case interfaceType:
   657  		r.currPkg = r.pkg()
   658  
   659  		embeddeds := make([]types.Type, r.uint64())
   660  		for i := range embeddeds {
   661  			_ = r.pos()
   662  			embeddeds[i] = r.typ()
   663  		}
   664  
   665  		methods := make([]*types.Func, r.uint64())
   666  		for i := range methods {
   667  			mpos := r.pos()
   668  			mname := r.ident()
   669  
   670  			// TODO(mdempsky): Matches bimport.go, but I
   671  			// don't agree with this.
   672  			var recv *types.Var
   673  			if base != nil {
   674  				recv = types.NewVar(token.NoPos, r.currPkg, "", base)
   675  			}
   676  
   677  			msig := r.signature(recv, nil, nil)
   678  			methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
   679  		}
   680  
   681  		typ := types.NewInterfaceType(methods, embeddeds)
   682  		r.p.interfaceList = append(r.p.interfaceList, typ)
   683  		return typ
   684  
   685  	case typeParamType:
   686  		if r.p.exportVersion < iexportVersionGenerics {
   687  			errorf("unexpected type param type")
   688  		}
   689  		pkg, name := r.qualifiedIdent()
   690  		id := ident{pkg, name}
   691  		if t, ok := r.p.tparamIndex[id]; ok {
   692  			// We're already in the process of importing this typeparam.
   693  			return t
   694  		}
   695  		// Otherwise, import the definition of the typeparam now.
   696  		r.p.doDecl(pkg, name)
   697  		return r.p.tparamIndex[id]
   698  
   699  	case instanceType:
   700  		if r.p.exportVersion < iexportVersionGenerics {
   701  			errorf("unexpected instantiation type")
   702  		}
   703  		// pos does not matter for instances: they are positioned on the original
   704  		// type.
   705  		_ = r.pos()
   706  		len := r.uint64()
   707  		targs := make([]types.Type, len)
   708  		for i := range targs {
   709  			targs[i] = r.typ()
   710  		}
   711  		baseType := r.typ()
   712  		// The imported instantiated type doesn't include any methods, so
   713  		// we must always use the methods of the base (orig) type.
   714  		// TODO provide a non-nil *Context
   715  		t, _ := types.Instantiate(nil, baseType, targs, false)
   716  		return t
   717  
   718  	case unionType:
   719  		if r.p.exportVersion < iexportVersionGenerics {
   720  			errorf("unexpected instantiation type")
   721  		}
   722  		terms := make([]*types.Term, r.uint64())
   723  		for i := range terms {
   724  			terms[i] = types.NewTerm(r.bool(), r.typ())
   725  		}
   726  		return types.NewUnion(terms)
   727  	}
   728  }
   729  
   730  func (r *importReader) kind() itag {
   731  	return itag(r.uint64())
   732  }
   733  
   734  func (r *importReader) signature(recv *types.Var, rparams, tparams []*types.TypeParam) *types.Signature {
   735  	params := r.paramList()
   736  	results := r.paramList()
   737  	variadic := params.Len() > 0 && r.bool()
   738  	return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
   739  }
   740  
   741  func (r *importReader) tparamList() []*types.TypeParam {
   742  	n := r.uint64()
   743  	if n == 0 {
   744  		return nil
   745  	}
   746  	xs := make([]*types.TypeParam, n)
   747  	for i := range xs {
   748  		xs[i], _ = r.typ().(*types.TypeParam)
   749  	}
   750  	return xs
   751  }
   752  
   753  func (r *importReader) paramList() *types.Tuple {
   754  	xs := make([]*types.Var, r.uint64())
   755  	for i := range xs {
   756  		xs[i] = r.param()
   757  	}
   758  	return types.NewTuple(xs...)
   759  }
   760  
   761  func (r *importReader) param() *types.Var {
   762  	pos := r.pos()
   763  	name := r.ident()
   764  	typ := r.typ()
   765  	return types.NewParam(pos, r.currPkg, name, typ)
   766  }
   767  
   768  func (r *importReader) bool() bool {
   769  	return r.uint64() != 0
   770  }
   771  
   772  func (r *importReader) int64() int64 {
   773  	n, err := binary.ReadVarint(&r.declReader)
   774  	if err != nil {
   775  		errorf("readVarint: %v", err)
   776  	}
   777  	return n
   778  }
   779  
   780  func (r *importReader) uint64() uint64 {
   781  	n, err := binary.ReadUvarint(&r.declReader)
   782  	if err != nil {
   783  		errorf("readUvarint: %v", err)
   784  	}
   785  	return n
   786  }
   787  
   788  func (r *importReader) byte() byte {
   789  	x, err := r.declReader.ReadByte()
   790  	if err != nil {
   791  		errorf("declReader.ReadByte: %v", err)
   792  	}
   793  	return x
   794  }
   795  
   796  func baseType(typ types.Type) *types.Named {
   797  	// pointer receivers are never types.Named types
   798  	if p, _ := typ.(*types.Pointer); p != nil {
   799  		typ = p.Elem()
   800  	}
   801  	// receiver base types are always (possibly generic) types.Named types
   802  	n, _ := typ.(*types.Named)
   803  	return n
   804  }
   805  
   806  const blankMarker = "$"
   807  
   808  // tparamName returns the real name of a type parameter, after stripping its
   809  // qualifying prefix and reverting blank-name encoding. See tparamExportName
   810  // for details.
   811  func tparamName(exportName string) string {
   812  	// Remove the "path" from the type param name that makes it unique.
   813  	ix := strings.LastIndex(exportName, ".")
   814  	if ix < 0 {
   815  		errorf("malformed type parameter export name %s: missing prefix", exportName)
   816  	}
   817  	name := exportName[ix+1:]
   818  	if strings.HasPrefix(name, blankMarker) {
   819  		return "_"
   820  	}
   821  	return name
   822  }
   823  

View as plain text