golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/internal/gcimporter/iexport.go (about)

     1  // Copyright 2019 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 binary package export.
     6  // This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go;
     7  // see that file for specification of the format.
     8  
     9  package gcimporter
    10  
    11  import (
    12  	"bytes"
    13  	"encoding/binary"
    14  	"fmt"
    15  	"go/constant"
    16  	"go/token"
    17  	"go/types"
    18  	"io"
    19  	"math/big"
    20  	"reflect"
    21  	"sort"
    22  	"strconv"
    23  	"strings"
    24  
    25  	"golang.org/x/tools/go/types/objectpath"
    26  	"golang.org/x/tools/internal/aliases"
    27  	"golang.org/x/tools/internal/tokeninternal"
    28  )
    29  
    30  // IExportShallow encodes "shallow" export data for the specified package.
    31  //
    32  // No promises are made about the encoding other than that it can be decoded by
    33  // the same version of IIExportShallow. If you plan to save export data in the
    34  // file system, be sure to include a cryptographic digest of the executable in
    35  // the key to avoid version skew.
    36  //
    37  // If the provided reportf func is non-nil, it will be used for reporting bugs
    38  // encountered during export.
    39  // TODO(rfindley): remove reportf when we are confident enough in the new
    40  // objectpath encoding.
    41  func IExportShallow(fset *token.FileSet, pkg *types.Package, reportf ReportFunc) ([]byte, error) {
    42  	// In principle this operation can only fail if out.Write fails,
    43  	// but that's impossible for bytes.Buffer---and as a matter of
    44  	// fact iexportCommon doesn't even check for I/O errors.
    45  	// TODO(adonovan): handle I/O errors properly.
    46  	// TODO(adonovan): use byte slices throughout, avoiding copying.
    47  	const bundle, shallow = false, true
    48  	var out bytes.Buffer
    49  	err := iexportCommon(&out, fset, bundle, shallow, iexportVersion, []*types.Package{pkg})
    50  	return out.Bytes(), err
    51  }
    52  
    53  // IImportShallow decodes "shallow" types.Package data encoded by
    54  // IExportShallow in the same executable. This function cannot import data from
    55  // cmd/compile or gcexportdata.Write.
    56  //
    57  // The importer calls getPackages to obtain package symbols for all
    58  // packages mentioned in the export data, including the one being
    59  // decoded.
    60  //
    61  // If the provided reportf func is non-nil, it will be used for reporting bugs
    62  // encountered during import.
    63  // TODO(rfindley): remove reportf when we are confident enough in the new
    64  // objectpath encoding.
    65  func IImportShallow(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, path string, reportf ReportFunc) (*types.Package, error) {
    66  	const bundle = false
    67  	const shallow = true
    68  	pkgs, err := iimportCommon(fset, getPackages, data, bundle, path, shallow, reportf)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	return pkgs[0], nil
    73  }
    74  
    75  // ReportFunc is the type of a function used to report formatted bugs.
    76  type ReportFunc = func(string, ...interface{})
    77  
    78  // Current bundled export format version. Increase with each format change.
    79  // 0: initial implementation
    80  const bundleVersion = 0
    81  
    82  // IExportData writes indexed export data for pkg to out.
    83  //
    84  // If no file set is provided, position info will be missing.
    85  // The package path of the top-level package will not be recorded,
    86  // so that calls to IImportData can override with a provided package path.
    87  func IExportData(out io.Writer, fset *token.FileSet, pkg *types.Package) error {
    88  	const bundle, shallow = false, false
    89  	return iexportCommon(out, fset, bundle, shallow, iexportVersion, []*types.Package{pkg})
    90  }
    91  
    92  // IExportBundle writes an indexed export bundle for pkgs to out.
    93  func IExportBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {
    94  	const bundle, shallow = true, false
    95  	return iexportCommon(out, fset, bundle, shallow, iexportVersion, pkgs)
    96  }
    97  
    98  func iexportCommon(out io.Writer, fset *token.FileSet, bundle, shallow bool, version int, pkgs []*types.Package) (err error) {
    99  	if !debug {
   100  		defer func() {
   101  			if e := recover(); e != nil {
   102  				if ierr, ok := e.(internalError); ok {
   103  					err = ierr
   104  					return
   105  				}
   106  				// Not an internal error; panic again.
   107  				panic(e)
   108  			}
   109  		}()
   110  	}
   111  
   112  	p := iexporter{
   113  		fset:        fset,
   114  		version:     version,
   115  		shallow:     shallow,
   116  		allPkgs:     map[*types.Package]bool{},
   117  		stringIndex: map[string]uint64{},
   118  		declIndex:   map[types.Object]uint64{},
   119  		tparamNames: map[types.Object]string{},
   120  		typIndex:    map[types.Type]uint64{},
   121  	}
   122  	if !bundle {
   123  		p.localpkg = pkgs[0]
   124  	}
   125  
   126  	for i, pt := range predeclared() {
   127  		p.typIndex[pt] = uint64(i)
   128  	}
   129  	if len(p.typIndex) > predeclReserved {
   130  		panic(internalErrorf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved))
   131  	}
   132  
   133  	// Initialize work queue with exported declarations.
   134  	for _, pkg := range pkgs {
   135  		scope := pkg.Scope()
   136  		for _, name := range scope.Names() {
   137  			if token.IsExported(name) {
   138  				p.pushDecl(scope.Lookup(name))
   139  			}
   140  		}
   141  
   142  		if bundle {
   143  			// Ensure pkg and its imports are included in the index.
   144  			p.allPkgs[pkg] = true
   145  			for _, imp := range pkg.Imports() {
   146  				p.allPkgs[imp] = true
   147  			}
   148  		}
   149  	}
   150  
   151  	// Loop until no more work.
   152  	for !p.declTodo.empty() {
   153  		p.doDecl(p.declTodo.popHead())
   154  	}
   155  
   156  	// Produce index of offset of each file record in files.
   157  	var files intWriter
   158  	var fileOffset []uint64 // fileOffset[i] is offset in files of file encoded as i
   159  	if p.shallow {
   160  		fileOffset = make([]uint64, len(p.fileInfos))
   161  		for i, info := range p.fileInfos {
   162  			fileOffset[i] = uint64(files.Len())
   163  			p.encodeFile(&files, info.file, info.needed)
   164  		}
   165  	}
   166  
   167  	// Append indices to data0 section.
   168  	dataLen := uint64(p.data0.Len())
   169  	w := p.newWriter()
   170  	w.writeIndex(p.declIndex)
   171  
   172  	if bundle {
   173  		w.uint64(uint64(len(pkgs)))
   174  		for _, pkg := range pkgs {
   175  			w.pkg(pkg)
   176  			imps := pkg.Imports()
   177  			w.uint64(uint64(len(imps)))
   178  			for _, imp := range imps {
   179  				w.pkg(imp)
   180  			}
   181  		}
   182  	}
   183  	w.flush()
   184  
   185  	// Assemble header.
   186  	var hdr intWriter
   187  	if bundle {
   188  		hdr.uint64(bundleVersion)
   189  	}
   190  	hdr.uint64(uint64(p.version))
   191  	hdr.uint64(uint64(p.strings.Len()))
   192  	if p.shallow {
   193  		hdr.uint64(uint64(files.Len()))
   194  		hdr.uint64(uint64(len(fileOffset)))
   195  		for _, offset := range fileOffset {
   196  			hdr.uint64(offset)
   197  		}
   198  	}
   199  	hdr.uint64(dataLen)
   200  
   201  	// Flush output.
   202  	io.Copy(out, &hdr)
   203  	io.Copy(out, &p.strings)
   204  	if p.shallow {
   205  		io.Copy(out, &files)
   206  	}
   207  	io.Copy(out, &p.data0)
   208  
   209  	return nil
   210  }
   211  
   212  // encodeFile writes to w a representation of the file sufficient to
   213  // faithfully restore position information about all needed offsets.
   214  // Mutates the needed array.
   215  func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64) {
   216  	_ = needed[0] // precondition: needed is non-empty
   217  
   218  	w.uint64(p.stringOff(file.Name()))
   219  
   220  	size := uint64(file.Size())
   221  	w.uint64(size)
   222  
   223  	// Sort the set of needed offsets. Duplicates are harmless.
   224  	sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
   225  
   226  	lines := tokeninternal.GetLines(file) // byte offset of each line start
   227  	w.uint64(uint64(len(lines)))
   228  
   229  	// Rather than record the entire array of line start offsets,
   230  	// we save only a sparse list of (index, offset) pairs for
   231  	// the start of each line that contains a needed position.
   232  	var sparse [][2]int // (index, offset) pairs
   233  outer:
   234  	for i, lineStart := range lines {
   235  		lineEnd := size
   236  		if i < len(lines)-1 {
   237  			lineEnd = uint64(lines[i+1])
   238  		}
   239  		// Does this line contains a needed offset?
   240  		if needed[0] < lineEnd {
   241  			sparse = append(sparse, [2]int{i, lineStart})
   242  			for needed[0] < lineEnd {
   243  				needed = needed[1:]
   244  				if len(needed) == 0 {
   245  					break outer
   246  				}
   247  			}
   248  		}
   249  	}
   250  
   251  	// Delta-encode the columns.
   252  	w.uint64(uint64(len(sparse)))
   253  	var prev [2]int
   254  	for _, pair := range sparse {
   255  		w.uint64(uint64(pair[0] - prev[0]))
   256  		w.uint64(uint64(pair[1] - prev[1]))
   257  		prev = pair
   258  	}
   259  }
   260  
   261  // writeIndex writes out an object index. mainIndex indicates whether
   262  // we're writing out the main index, which is also read by
   263  // non-compiler tools and includes a complete package description
   264  // (i.e., name and height).
   265  func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
   266  	type pkgObj struct {
   267  		obj  types.Object
   268  		name string // qualified name; differs from obj.Name for type params
   269  	}
   270  	// Build a map from packages to objects from that package.
   271  	pkgObjs := map[*types.Package][]pkgObj{}
   272  
   273  	// For the main index, make sure to include every package that
   274  	// we reference, even if we're not exporting (or reexporting)
   275  	// any symbols from it.
   276  	if w.p.localpkg != nil {
   277  		pkgObjs[w.p.localpkg] = nil
   278  	}
   279  	for pkg := range w.p.allPkgs {
   280  		pkgObjs[pkg] = nil
   281  	}
   282  
   283  	for obj := range index {
   284  		name := w.p.exportName(obj)
   285  		pkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], pkgObj{obj, name})
   286  	}
   287  
   288  	var pkgs []*types.Package
   289  	for pkg, objs := range pkgObjs {
   290  		pkgs = append(pkgs, pkg)
   291  
   292  		sort.Slice(objs, func(i, j int) bool {
   293  			return objs[i].name < objs[j].name
   294  		})
   295  	}
   296  
   297  	sort.Slice(pkgs, func(i, j int) bool {
   298  		return w.exportPath(pkgs[i]) < w.exportPath(pkgs[j])
   299  	})
   300  
   301  	w.uint64(uint64(len(pkgs)))
   302  	for _, pkg := range pkgs {
   303  		w.string(w.exportPath(pkg))
   304  		w.string(pkg.Name())
   305  		w.uint64(uint64(0)) // package height is not needed for go/types
   306  
   307  		objs := pkgObjs[pkg]
   308  		w.uint64(uint64(len(objs)))
   309  		for _, obj := range objs {
   310  			w.string(obj.name)
   311  			w.uint64(index[obj.obj])
   312  		}
   313  	}
   314  }
   315  
   316  // exportName returns the 'exported' name of an object. It differs from
   317  // obj.Name() only for type parameters (see tparamExportName for details).
   318  func (p *iexporter) exportName(obj types.Object) (res string) {
   319  	if name := p.tparamNames[obj]; name != "" {
   320  		return name
   321  	}
   322  	return obj.Name()
   323  }
   324  
   325  type iexporter struct {
   326  	fset    *token.FileSet
   327  	out     *bytes.Buffer
   328  	version int
   329  
   330  	shallow    bool                // don't put types from other packages in the index
   331  	objEncoder *objectpath.Encoder // encodes objects from other packages in shallow mode; lazily allocated
   332  	localpkg   *types.Package      // (nil in bundle mode)
   333  
   334  	// allPkgs tracks all packages that have been referenced by
   335  	// the export data, so we can ensure to include them in the
   336  	// main index.
   337  	allPkgs map[*types.Package]bool
   338  
   339  	declTodo objQueue
   340  
   341  	strings     intWriter
   342  	stringIndex map[string]uint64
   343  
   344  	// In shallow mode, object positions are encoded as (file, offset).
   345  	// Each file is recorded as a line-number table.
   346  	// Only the lines of needed positions are saved faithfully.
   347  	fileInfo  map[*token.File]uint64 // value is index in fileInfos
   348  	fileInfos []*filePositions
   349  
   350  	data0       intWriter
   351  	declIndex   map[types.Object]uint64
   352  	tparamNames map[types.Object]string // typeparam->exported name
   353  	typIndex    map[types.Type]uint64
   354  
   355  	indent int // for tracing support
   356  }
   357  
   358  type filePositions struct {
   359  	file   *token.File
   360  	needed []uint64 // unordered list of needed file offsets
   361  }
   362  
   363  func (p *iexporter) trace(format string, args ...interface{}) {
   364  	if !trace {
   365  		// Call sites should also be guarded, but having this check here allows
   366  		// easily enabling/disabling debug trace statements.
   367  		return
   368  	}
   369  	fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
   370  }
   371  
   372  // objectpathEncoder returns the lazily allocated objectpath.Encoder to use
   373  // when encoding objects in other packages during shallow export.
   374  //
   375  // Using a shared Encoder amortizes some of cost of objectpath search.
   376  func (p *iexporter) objectpathEncoder() *objectpath.Encoder {
   377  	if p.objEncoder == nil {
   378  		p.objEncoder = new(objectpath.Encoder)
   379  	}
   380  	return p.objEncoder
   381  }
   382  
   383  // stringOff returns the offset of s within the string section.
   384  // If not already present, it's added to the end.
   385  func (p *iexporter) stringOff(s string) uint64 {
   386  	off, ok := p.stringIndex[s]
   387  	if !ok {
   388  		off = uint64(p.strings.Len())
   389  		p.stringIndex[s] = off
   390  
   391  		p.strings.uint64(uint64(len(s)))
   392  		p.strings.WriteString(s)
   393  	}
   394  	return off
   395  }
   396  
   397  // fileIndexAndOffset returns the index of the token.File and the byte offset of pos within it.
   398  func (p *iexporter) fileIndexAndOffset(file *token.File, pos token.Pos) (uint64, uint64) {
   399  	index, ok := p.fileInfo[file]
   400  	if !ok {
   401  		index = uint64(len(p.fileInfo))
   402  		p.fileInfos = append(p.fileInfos, &filePositions{file: file})
   403  		if p.fileInfo == nil {
   404  			p.fileInfo = make(map[*token.File]uint64)
   405  		}
   406  		p.fileInfo[file] = index
   407  	}
   408  	// Record each needed offset.
   409  	info := p.fileInfos[index]
   410  	offset := uint64(file.Offset(pos))
   411  	info.needed = append(info.needed, offset)
   412  
   413  	return index, offset
   414  }
   415  
   416  // pushDecl adds n to the declaration work queue, if not already present.
   417  func (p *iexporter) pushDecl(obj types.Object) {
   418  	// Package unsafe is known to the compiler and predeclared.
   419  	// Caller should not ask us to do export it.
   420  	if obj.Pkg() == types.Unsafe {
   421  		panic("cannot export package unsafe")
   422  	}
   423  
   424  	// Shallow export data: don't index decls from other packages.
   425  	if p.shallow && obj.Pkg() != p.localpkg {
   426  		return
   427  	}
   428  
   429  	if _, ok := p.declIndex[obj]; ok {
   430  		return
   431  	}
   432  
   433  	p.declIndex[obj] = ^uint64(0) // mark obj present in work queue
   434  	p.declTodo.pushTail(obj)
   435  }
   436  
   437  // exportWriter handles writing out individual data section chunks.
   438  type exportWriter struct {
   439  	p *iexporter
   440  
   441  	data       intWriter
   442  	prevFile   string
   443  	prevLine   int64
   444  	prevColumn int64
   445  }
   446  
   447  func (w *exportWriter) exportPath(pkg *types.Package) string {
   448  	if pkg == w.p.localpkg {
   449  		return ""
   450  	}
   451  	return pkg.Path()
   452  }
   453  
   454  func (p *iexporter) doDecl(obj types.Object) {
   455  	if trace {
   456  		p.trace("exporting decl %v (%T)", obj, obj)
   457  		p.indent++
   458  		defer func() {
   459  			p.indent--
   460  			p.trace("=> %s", obj)
   461  		}()
   462  	}
   463  	w := p.newWriter()
   464  
   465  	switch obj := obj.(type) {
   466  	case *types.Var:
   467  		w.tag(varTag)
   468  		w.pos(obj.Pos())
   469  		w.typ(obj.Type(), obj.Pkg())
   470  
   471  	case *types.Func:
   472  		sig, _ := obj.Type().(*types.Signature)
   473  		if sig.Recv() != nil {
   474  			// We shouldn't see methods in the package scope,
   475  			// but the type checker may repair "func () F() {}"
   476  			// to "func (Invalid) F()" and then treat it like "func F()",
   477  			// so allow that. See golang/go#57729.
   478  			if sig.Recv().Type() != types.Typ[types.Invalid] {
   479  				panic(internalErrorf("unexpected method: %v", sig))
   480  			}
   481  		}
   482  
   483  		// Function.
   484  		if sig.TypeParams().Len() == 0 {
   485  			w.tag(funcTag)
   486  		} else {
   487  			w.tag(genericFuncTag)
   488  		}
   489  		w.pos(obj.Pos())
   490  		// The tparam list of the function type is the declaration of the type
   491  		// params. So, write out the type params right now. Then those type params
   492  		// will be referenced via their type offset (via typOff) in all other
   493  		// places in the signature and function where they are used.
   494  		//
   495  		// While importing the type parameters, tparamList computes and records
   496  		// their export name, so that it can be later used when writing the index.
   497  		if tparams := sig.TypeParams(); tparams.Len() > 0 {
   498  			w.tparamList(obj.Name(), tparams, obj.Pkg())
   499  		}
   500  		w.signature(sig)
   501  
   502  	case *types.Const:
   503  		w.tag(constTag)
   504  		w.pos(obj.Pos())
   505  		w.value(obj.Type(), obj.Val())
   506  
   507  	case *types.TypeName:
   508  		t := obj.Type()
   509  
   510  		if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok {
   511  			w.tag(typeParamTag)
   512  			w.pos(obj.Pos())
   513  			constraint := tparam.Constraint()
   514  			if p.version >= iexportVersionGo1_18 {
   515  				implicit := false
   516  				if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil {
   517  					implicit = iface.IsImplicit()
   518  				}
   519  				w.bool(implicit)
   520  			}
   521  			w.typ(constraint, obj.Pkg())
   522  			break
   523  		}
   524  
   525  		if obj.IsAlias() {
   526  			w.tag(aliasTag)
   527  			w.pos(obj.Pos())
   528  			if alias, ok := t.(*aliases.Alias); ok {
   529  				// Preserve materialized aliases,
   530  				// even of non-exported types.
   531  				t = aliases.Rhs(alias)
   532  			}
   533  			w.typ(t, obj.Pkg())
   534  			break
   535  		}
   536  
   537  		// Defined type.
   538  		named, ok := t.(*types.Named)
   539  		if !ok {
   540  			panic(internalErrorf("%s is not a defined type", t))
   541  		}
   542  
   543  		if named.TypeParams().Len() == 0 {
   544  			w.tag(typeTag)
   545  		} else {
   546  			w.tag(genericTypeTag)
   547  		}
   548  		w.pos(obj.Pos())
   549  
   550  		if named.TypeParams().Len() > 0 {
   551  			// While importing the type parameters, tparamList computes and records
   552  			// their export name, so that it can be later used when writing the index.
   553  			w.tparamList(obj.Name(), named.TypeParams(), obj.Pkg())
   554  		}
   555  
   556  		underlying := named.Underlying()
   557  		w.typ(underlying, obj.Pkg())
   558  
   559  		if types.IsInterface(t) {
   560  			break
   561  		}
   562  
   563  		n := named.NumMethods()
   564  		w.uint64(uint64(n))
   565  		for i := 0; i < n; i++ {
   566  			m := named.Method(i)
   567  			w.pos(m.Pos())
   568  			w.string(m.Name())
   569  			sig, _ := m.Type().(*types.Signature)
   570  
   571  			// Receiver type parameters are type arguments of the receiver type, so
   572  			// their name must be qualified before exporting recv.
   573  			if rparams := sig.RecvTypeParams(); rparams.Len() > 0 {
   574  				prefix := obj.Name() + "." + m.Name()
   575  				for i := 0; i < rparams.Len(); i++ {
   576  					rparam := rparams.At(i)
   577  					name := tparamExportName(prefix, rparam)
   578  					w.p.tparamNames[rparam.Obj()] = name
   579  				}
   580  			}
   581  			w.param(sig.Recv())
   582  			w.signature(sig)
   583  		}
   584  
   585  	default:
   586  		panic(internalErrorf("unexpected object: %v", obj))
   587  	}
   588  
   589  	p.declIndex[obj] = w.flush()
   590  }
   591  
   592  func (w *exportWriter) tag(tag byte) {
   593  	w.data.WriteByte(tag)
   594  }
   595  
   596  func (w *exportWriter) pos(pos token.Pos) {
   597  	if w.p.shallow {
   598  		w.posV2(pos)
   599  	} else if w.p.version >= iexportVersionPosCol {
   600  		w.posV1(pos)
   601  	} else {
   602  		w.posV0(pos)
   603  	}
   604  }
   605  
   606  // posV2 encoding (used only in shallow mode) records positions as
   607  // (file, offset), where file is the index in the token.File table
   608  // (which records the file name and newline offsets) and offset is a
   609  // byte offset. It effectively ignores //line directives.
   610  func (w *exportWriter) posV2(pos token.Pos) {
   611  	if pos == token.NoPos {
   612  		w.uint64(0)
   613  		return
   614  	}
   615  	file := w.p.fset.File(pos) // fset must be non-nil
   616  	index, offset := w.p.fileIndexAndOffset(file, pos)
   617  	w.uint64(1 + index)
   618  	w.uint64(offset)
   619  }
   620  
   621  func (w *exportWriter) posV1(pos token.Pos) {
   622  	if w.p.fset == nil {
   623  		w.int64(0)
   624  		return
   625  	}
   626  
   627  	p := w.p.fset.Position(pos)
   628  	file := p.Filename
   629  	line := int64(p.Line)
   630  	column := int64(p.Column)
   631  
   632  	deltaColumn := (column - w.prevColumn) << 1
   633  	deltaLine := (line - w.prevLine) << 1
   634  
   635  	if file != w.prevFile {
   636  		deltaLine |= 1
   637  	}
   638  	if deltaLine != 0 {
   639  		deltaColumn |= 1
   640  	}
   641  
   642  	w.int64(deltaColumn)
   643  	if deltaColumn&1 != 0 {
   644  		w.int64(deltaLine)
   645  		if deltaLine&1 != 0 {
   646  			w.string(file)
   647  		}
   648  	}
   649  
   650  	w.prevFile = file
   651  	w.prevLine = line
   652  	w.prevColumn = column
   653  }
   654  
   655  func (w *exportWriter) posV0(pos token.Pos) {
   656  	if w.p.fset == nil {
   657  		w.int64(0)
   658  		return
   659  	}
   660  
   661  	p := w.p.fset.Position(pos)
   662  	file := p.Filename
   663  	line := int64(p.Line)
   664  
   665  	// When file is the same as the last position (common case),
   666  	// we can save a few bytes by delta encoding just the line
   667  	// number.
   668  	//
   669  	// Note: Because data objects may be read out of order (or not
   670  	// at all), we can only apply delta encoding within a single
   671  	// object. This is handled implicitly by tracking prevFile and
   672  	// prevLine as fields of exportWriter.
   673  
   674  	if file == w.prevFile {
   675  		delta := line - w.prevLine
   676  		w.int64(delta)
   677  		if delta == deltaNewFile {
   678  			w.int64(-1)
   679  		}
   680  	} else {
   681  		w.int64(deltaNewFile)
   682  		w.int64(line) // line >= 0
   683  		w.string(file)
   684  		w.prevFile = file
   685  	}
   686  	w.prevLine = line
   687  }
   688  
   689  func (w *exportWriter) pkg(pkg *types.Package) {
   690  	// Ensure any referenced packages are declared in the main index.
   691  	w.p.allPkgs[pkg] = true
   692  
   693  	w.string(w.exportPath(pkg))
   694  }
   695  
   696  func (w *exportWriter) qualifiedType(obj *types.TypeName) {
   697  	name := w.p.exportName(obj)
   698  
   699  	// Ensure any referenced declarations are written out too.
   700  	w.p.pushDecl(obj)
   701  	w.string(name)
   702  	w.pkg(obj.Pkg())
   703  }
   704  
   705  // TODO(rfindley): what does 'pkg' even mean here? It would be better to pass
   706  // it in explicitly into signatures and structs that may use it for
   707  // constructing fields.
   708  func (w *exportWriter) typ(t types.Type, pkg *types.Package) {
   709  	w.data.uint64(w.p.typOff(t, pkg))
   710  }
   711  
   712  func (p *iexporter) newWriter() *exportWriter {
   713  	return &exportWriter{p: p}
   714  }
   715  
   716  func (w *exportWriter) flush() uint64 {
   717  	off := uint64(w.p.data0.Len())
   718  	io.Copy(&w.p.data0, &w.data)
   719  	return off
   720  }
   721  
   722  func (p *iexporter) typOff(t types.Type, pkg *types.Package) uint64 {
   723  	off, ok := p.typIndex[t]
   724  	if !ok {
   725  		w := p.newWriter()
   726  		w.doTyp(t, pkg)
   727  		off = predeclReserved + w.flush()
   728  		p.typIndex[t] = off
   729  	}
   730  	return off
   731  }
   732  
   733  func (w *exportWriter) startType(k itag) {
   734  	w.data.uint64(uint64(k))
   735  }
   736  
   737  func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
   738  	if trace {
   739  		w.p.trace("exporting type %s (%T)", t, t)
   740  		w.p.indent++
   741  		defer func() {
   742  			w.p.indent--
   743  			w.p.trace("=> %s", t)
   744  		}()
   745  	}
   746  	switch t := t.(type) {
   747  	case *aliases.Alias:
   748  		// TODO(adonovan): support parameterized aliases, following *types.Named.
   749  		w.startType(aliasType)
   750  		w.qualifiedType(t.Obj())
   751  
   752  	case *types.Named:
   753  		if targs := t.TypeArgs(); targs.Len() > 0 {
   754  			w.startType(instanceType)
   755  			// TODO(rfindley): investigate if this position is correct, and if it
   756  			// matters.
   757  			w.pos(t.Obj().Pos())
   758  			w.typeList(targs, pkg)
   759  			w.typ(t.Origin(), pkg)
   760  			return
   761  		}
   762  		w.startType(definedType)
   763  		w.qualifiedType(t.Obj())
   764  
   765  	case *types.TypeParam:
   766  		w.startType(typeParamType)
   767  		w.qualifiedType(t.Obj())
   768  
   769  	case *types.Pointer:
   770  		w.startType(pointerType)
   771  		w.typ(t.Elem(), pkg)
   772  
   773  	case *types.Slice:
   774  		w.startType(sliceType)
   775  		w.typ(t.Elem(), pkg)
   776  
   777  	case *types.Array:
   778  		w.startType(arrayType)
   779  		w.uint64(uint64(t.Len()))
   780  		w.typ(t.Elem(), pkg)
   781  
   782  	case *types.Chan:
   783  		w.startType(chanType)
   784  		// 1 RecvOnly; 2 SendOnly; 3 SendRecv
   785  		var dir uint64
   786  		switch t.Dir() {
   787  		case types.RecvOnly:
   788  			dir = 1
   789  		case types.SendOnly:
   790  			dir = 2
   791  		case types.SendRecv:
   792  			dir = 3
   793  		}
   794  		w.uint64(dir)
   795  		w.typ(t.Elem(), pkg)
   796  
   797  	case *types.Map:
   798  		w.startType(mapType)
   799  		w.typ(t.Key(), pkg)
   800  		w.typ(t.Elem(), pkg)
   801  
   802  	case *types.Signature:
   803  		w.startType(signatureType)
   804  		w.pkg(pkg)
   805  		w.signature(t)
   806  
   807  	case *types.Struct:
   808  		w.startType(structType)
   809  		n := t.NumFields()
   810  		// Even for struct{} we must emit some qualifying package, because that's
   811  		// what the compiler does, and thus that's what the importer expects.
   812  		fieldPkg := pkg
   813  		if n > 0 {
   814  			fieldPkg = t.Field(0).Pkg()
   815  		}
   816  		if fieldPkg == nil {
   817  			// TODO(rfindley): improve this very hacky logic.
   818  			//
   819  			// The importer expects a package to be set for all struct types, even
   820  			// those with no fields. A better encoding might be to set NumFields
   821  			// before pkg. setPkg panics with a nil package, which may be possible
   822  			// to reach with invalid packages (and perhaps valid packages, too?), so
   823  			// (arbitrarily) set the localpkg if available.
   824  			//
   825  			// Alternatively, we may be able to simply guarantee that pkg != nil, by
   826  			// reconsidering the encoding of constant values.
   827  			if w.p.shallow {
   828  				fieldPkg = w.p.localpkg
   829  			} else {
   830  				panic(internalErrorf("no package to set for empty struct"))
   831  			}
   832  		}
   833  		w.pkg(fieldPkg)
   834  		w.uint64(uint64(n))
   835  
   836  		for i := 0; i < n; i++ {
   837  			f := t.Field(i)
   838  			if w.p.shallow {
   839  				w.objectPath(f)
   840  			}
   841  			w.pos(f.Pos())
   842  			w.string(f.Name()) // unexported fields implicitly qualified by prior setPkg
   843  			w.typ(f.Type(), fieldPkg)
   844  			w.bool(f.Anonymous())
   845  			w.string(t.Tag(i)) // note (or tag)
   846  		}
   847  
   848  	case *types.Interface:
   849  		w.startType(interfaceType)
   850  		w.pkg(pkg)
   851  
   852  		n := t.NumEmbeddeds()
   853  		w.uint64(uint64(n))
   854  		for i := 0; i < n; i++ {
   855  			ft := t.EmbeddedType(i)
   856  			tPkg := pkg
   857  			if named, _ := aliases.Unalias(ft).(*types.Named); named != nil {
   858  				w.pos(named.Obj().Pos())
   859  			} else {
   860  				w.pos(token.NoPos)
   861  			}
   862  			w.typ(ft, tPkg)
   863  		}
   864  
   865  		// See comment for struct fields. In shallow mode we change the encoding
   866  		// for interface methods that are promoted from other packages.
   867  
   868  		n = t.NumExplicitMethods()
   869  		w.uint64(uint64(n))
   870  		for i := 0; i < n; i++ {
   871  			m := t.ExplicitMethod(i)
   872  			if w.p.shallow {
   873  				w.objectPath(m)
   874  			}
   875  			w.pos(m.Pos())
   876  			w.string(m.Name())
   877  			sig, _ := m.Type().(*types.Signature)
   878  			w.signature(sig)
   879  		}
   880  
   881  	case *types.Union:
   882  		w.startType(unionType)
   883  		nt := t.Len()
   884  		w.uint64(uint64(nt))
   885  		for i := 0; i < nt; i++ {
   886  			term := t.Term(i)
   887  			w.bool(term.Tilde())
   888  			w.typ(term.Type(), pkg)
   889  		}
   890  
   891  	default:
   892  		panic(internalErrorf("unexpected type: %v, %v", t, reflect.TypeOf(t)))
   893  	}
   894  }
   895  
   896  // objectPath writes the package and objectPath to use to look up obj in a
   897  // different package, when encoding in "shallow" mode.
   898  //
   899  // When doing a shallow import, the importer creates only the local package,
   900  // and requests package symbols for dependencies from the client.
   901  // However, certain types defined in the local package may hold objects defined
   902  // (perhaps deeply) within another package.
   903  //
   904  // For example, consider the following:
   905  //
   906  //	package a
   907  //	func F() chan * map[string] struct { X int }
   908  //
   909  //	package b
   910  //	import "a"
   911  //	var B = a.F()
   912  //
   913  // In this example, the type of b.B holds fields defined in package a.
   914  // In order to have the correct canonical objects for the field defined in the
   915  // type of B, they are encoded as objectPaths and later looked up in the
   916  // importer. The same problem applies to interface methods.
   917  func (w *exportWriter) objectPath(obj types.Object) {
   918  	if obj.Pkg() == nil || obj.Pkg() == w.p.localpkg {
   919  		// obj.Pkg() may be nil for the builtin error.Error.
   920  		// In this case, or if obj is declared in the local package, no need to
   921  		// encode.
   922  		w.string("")
   923  		return
   924  	}
   925  	objectPath, err := w.p.objectpathEncoder().For(obj)
   926  	if err != nil {
   927  		// Fall back to the empty string, which will cause the importer to create a
   928  		// new object, which matches earlier behavior. Creating a new object is
   929  		// sufficient for many purposes (such as type checking), but causes certain
   930  		// references algorithms to fail (golang/go#60819). However, we didn't
   931  		// notice this problem during months of gopls@v0.12.0 testing.
   932  		//
   933  		// TODO(golang/go#61674): this workaround is insufficient, as in the case
   934  		// where the field forwarded from an instantiated type that may not appear
   935  		// in the export data of the original package:
   936  		//
   937  		//  // package a
   938  		//  type A[P any] struct{ F P }
   939  		//
   940  		//  // package b
   941  		//  type B a.A[int]
   942  		//
   943  		// We need to update references algorithms not to depend on this
   944  		// de-duplication, at which point we may want to simply remove the
   945  		// workaround here.
   946  		w.string("")
   947  		return
   948  	}
   949  	w.string(string(objectPath))
   950  	w.pkg(obj.Pkg())
   951  }
   952  
   953  func (w *exportWriter) signature(sig *types.Signature) {
   954  	w.paramList(sig.Params())
   955  	w.paramList(sig.Results())
   956  	if sig.Params().Len() > 0 {
   957  		w.bool(sig.Variadic())
   958  	}
   959  }
   960  
   961  func (w *exportWriter) typeList(ts *types.TypeList, pkg *types.Package) {
   962  	w.uint64(uint64(ts.Len()))
   963  	for i := 0; i < ts.Len(); i++ {
   964  		w.typ(ts.At(i), pkg)
   965  	}
   966  }
   967  
   968  func (w *exportWriter) tparamList(prefix string, list *types.TypeParamList, pkg *types.Package) {
   969  	ll := uint64(list.Len())
   970  	w.uint64(ll)
   971  	for i := 0; i < list.Len(); i++ {
   972  		tparam := list.At(i)
   973  		// Set the type parameter exportName before exporting its type.
   974  		exportName := tparamExportName(prefix, tparam)
   975  		w.p.tparamNames[tparam.Obj()] = exportName
   976  		w.typ(list.At(i), pkg)
   977  	}
   978  }
   979  
   980  const blankMarker = "$"
   981  
   982  // tparamExportName returns the 'exported' name of a type parameter, which
   983  // differs from its actual object name: it is prefixed with a qualifier, and
   984  // blank type parameter names are disambiguated by their index in the type
   985  // parameter list.
   986  func tparamExportName(prefix string, tparam *types.TypeParam) string {
   987  	assert(prefix != "")
   988  	name := tparam.Obj().Name()
   989  	if name == "_" {
   990  		name = blankMarker + strconv.Itoa(tparam.Index())
   991  	}
   992  	return prefix + "." + name
   993  }
   994  
   995  // tparamName returns the real name of a type parameter, after stripping its
   996  // qualifying prefix and reverting blank-name encoding. See tparamExportName
   997  // for details.
   998  func tparamName(exportName string) string {
   999  	// Remove the "path" from the type param name that makes it unique.
  1000  	ix := strings.LastIndex(exportName, ".")
  1001  	if ix < 0 {
  1002  		errorf("malformed type parameter export name %s: missing prefix", exportName)
  1003  	}
  1004  	name := exportName[ix+1:]
  1005  	if strings.HasPrefix(name, blankMarker) {
  1006  		return "_"
  1007  	}
  1008  	return name
  1009  }
  1010  
  1011  func (w *exportWriter) paramList(tup *types.Tuple) {
  1012  	n := tup.Len()
  1013  	w.uint64(uint64(n))
  1014  	for i := 0; i < n; i++ {
  1015  		w.param(tup.At(i))
  1016  	}
  1017  }
  1018  
  1019  func (w *exportWriter) param(obj types.Object) {
  1020  	w.pos(obj.Pos())
  1021  	w.localIdent(obj)
  1022  	w.typ(obj.Type(), obj.Pkg())
  1023  }
  1024  
  1025  func (w *exportWriter) value(typ types.Type, v constant.Value) {
  1026  	w.typ(typ, nil)
  1027  	if w.p.version >= iexportVersionGo1_18 {
  1028  		w.int64(int64(v.Kind()))
  1029  	}
  1030  
  1031  	if v.Kind() == constant.Unknown {
  1032  		// golang/go#60605: treat unknown constant values as if they have invalid type
  1033  		//
  1034  		// This loses some fidelity over the package type-checked from source, but that
  1035  		// is acceptable.
  1036  		//
  1037  		// TODO(rfindley): we should switch on the recorded constant kind rather
  1038  		// than the constant type
  1039  		return
  1040  	}
  1041  
  1042  	switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
  1043  	case types.IsBoolean:
  1044  		w.bool(constant.BoolVal(v))
  1045  	case types.IsInteger:
  1046  		var i big.Int
  1047  		if i64, exact := constant.Int64Val(v); exact {
  1048  			i.SetInt64(i64)
  1049  		} else if ui64, exact := constant.Uint64Val(v); exact {
  1050  			i.SetUint64(ui64)
  1051  		} else {
  1052  			i.SetString(v.ExactString(), 10)
  1053  		}
  1054  		w.mpint(&i, typ)
  1055  	case types.IsFloat:
  1056  		f := constantToFloat(v)
  1057  		w.mpfloat(f, typ)
  1058  	case types.IsComplex:
  1059  		w.mpfloat(constantToFloat(constant.Real(v)), typ)
  1060  		w.mpfloat(constantToFloat(constant.Imag(v)), typ)
  1061  	case types.IsString:
  1062  		w.string(constant.StringVal(v))
  1063  	default:
  1064  		if b.Kind() == types.Invalid {
  1065  			// package contains type errors
  1066  			break
  1067  		}
  1068  		panic(internalErrorf("unexpected type %v (%v)", typ, typ.Underlying()))
  1069  	}
  1070  }
  1071  
  1072  // constantToFloat converts a constant.Value with kind constant.Float to a
  1073  // big.Float.
  1074  func constantToFloat(x constant.Value) *big.Float {
  1075  	x = constant.ToFloat(x)
  1076  	// Use the same floating-point precision (512) as cmd/compile
  1077  	// (see Mpprec in cmd/compile/internal/gc/mpfloat.go).
  1078  	const mpprec = 512
  1079  	var f big.Float
  1080  	f.SetPrec(mpprec)
  1081  	if v, exact := constant.Float64Val(x); exact {
  1082  		// float64
  1083  		f.SetFloat64(v)
  1084  	} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
  1085  		// TODO(gri): add big.Rat accessor to constant.Value.
  1086  		n := valueToRat(num)
  1087  		d := valueToRat(denom)
  1088  		f.SetRat(n.Quo(n, d))
  1089  	} else {
  1090  		// Value too large to represent as a fraction => inaccessible.
  1091  		// TODO(gri): add big.Float accessor to constant.Value.
  1092  		_, ok := f.SetString(x.ExactString())
  1093  		assert(ok)
  1094  	}
  1095  	return &f
  1096  }
  1097  
  1098  func valueToRat(x constant.Value) *big.Rat {
  1099  	// Convert little-endian to big-endian.
  1100  	// I can't believe this is necessary.
  1101  	bytes := constant.Bytes(x)
  1102  	for i := 0; i < len(bytes)/2; i++ {
  1103  		bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
  1104  	}
  1105  	return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
  1106  }
  1107  
  1108  // mpint exports a multi-precision integer.
  1109  //
  1110  // For unsigned types, small values are written out as a single
  1111  // byte. Larger values are written out as a length-prefixed big-endian
  1112  // byte string, where the length prefix is encoded as its complement.
  1113  // For example, bytes 0, 1, and 2 directly represent the integer
  1114  // values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
  1115  // 2-, and 3-byte big-endian string follow.
  1116  //
  1117  // Encoding for signed types use the same general approach as for
  1118  // unsigned types, except small values use zig-zag encoding and the
  1119  // bottom bit of length prefix byte for large values is reserved as a
  1120  // sign bit.
  1121  //
  1122  // The exact boundary between small and large encodings varies
  1123  // according to the maximum number of bytes needed to encode a value
  1124  // of type typ. As a special case, 8-bit types are always encoded as a
  1125  // single byte.
  1126  //
  1127  // TODO(mdempsky): Is this level of complexity really worthwhile?
  1128  func (w *exportWriter) mpint(x *big.Int, typ types.Type) {
  1129  	basic, ok := typ.Underlying().(*types.Basic)
  1130  	if !ok {
  1131  		panic(internalErrorf("unexpected type %v (%T)", typ.Underlying(), typ.Underlying()))
  1132  	}
  1133  
  1134  	signed, maxBytes := intSize(basic)
  1135  
  1136  	negative := x.Sign() < 0
  1137  	if !signed && negative {
  1138  		panic(internalErrorf("negative unsigned integer; type %v, value %v", typ, x))
  1139  	}
  1140  
  1141  	b := x.Bytes()
  1142  	if len(b) > 0 && b[0] == 0 {
  1143  		panic(internalErrorf("leading zeros"))
  1144  	}
  1145  	if uint(len(b)) > maxBytes {
  1146  		panic(internalErrorf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x))
  1147  	}
  1148  
  1149  	maxSmall := 256 - maxBytes
  1150  	if signed {
  1151  		maxSmall = 256 - 2*maxBytes
  1152  	}
  1153  	if maxBytes == 1 {
  1154  		maxSmall = 256
  1155  	}
  1156  
  1157  	// Check if x can use small value encoding.
  1158  	if len(b) <= 1 {
  1159  		var ux uint
  1160  		if len(b) == 1 {
  1161  			ux = uint(b[0])
  1162  		}
  1163  		if signed {
  1164  			ux <<= 1
  1165  			if negative {
  1166  				ux--
  1167  			}
  1168  		}
  1169  		if ux < maxSmall {
  1170  			w.data.WriteByte(byte(ux))
  1171  			return
  1172  		}
  1173  	}
  1174  
  1175  	n := 256 - uint(len(b))
  1176  	if signed {
  1177  		n = 256 - 2*uint(len(b))
  1178  		if negative {
  1179  			n |= 1
  1180  		}
  1181  	}
  1182  	if n < maxSmall || n >= 256 {
  1183  		panic(internalErrorf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n))
  1184  	}
  1185  
  1186  	w.data.WriteByte(byte(n))
  1187  	w.data.Write(b)
  1188  }
  1189  
  1190  // mpfloat exports a multi-precision floating point number.
  1191  //
  1192  // The number's value is decomposed into mantissa × 2**exponent, where
  1193  // mantissa is an integer. The value is written out as mantissa (as a
  1194  // multi-precision integer) and then the exponent, except exponent is
  1195  // omitted if mantissa is zero.
  1196  func (w *exportWriter) mpfloat(f *big.Float, typ types.Type) {
  1197  	if f.IsInf() {
  1198  		panic("infinite constant")
  1199  	}
  1200  
  1201  	// Break into f = mant × 2**exp, with 0.5 <= mant < 1.
  1202  	var mant big.Float
  1203  	exp := int64(f.MantExp(&mant))
  1204  
  1205  	// Scale so that mant is an integer.
  1206  	prec := mant.MinPrec()
  1207  	mant.SetMantExp(&mant, int(prec))
  1208  	exp -= int64(prec)
  1209  
  1210  	manti, acc := mant.Int(nil)
  1211  	if acc != big.Exact {
  1212  		panic(internalErrorf("mantissa scaling failed for %f (%s)", f, acc))
  1213  	}
  1214  	w.mpint(manti, typ)
  1215  	if manti.Sign() != 0 {
  1216  		w.int64(exp)
  1217  	}
  1218  }
  1219  
  1220  func (w *exportWriter) bool(b bool) bool {
  1221  	var x uint64
  1222  	if b {
  1223  		x = 1
  1224  	}
  1225  	w.uint64(x)
  1226  	return b
  1227  }
  1228  
  1229  func (w *exportWriter) int64(x int64)   { w.data.int64(x) }
  1230  func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
  1231  func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
  1232  
  1233  func (w *exportWriter) localIdent(obj types.Object) {
  1234  	// Anonymous parameters.
  1235  	if obj == nil {
  1236  		w.string("")
  1237  		return
  1238  	}
  1239  
  1240  	name := obj.Name()
  1241  	if name == "_" {
  1242  		w.string("_")
  1243  		return
  1244  	}
  1245  
  1246  	w.string(name)
  1247  }
  1248  
  1249  type intWriter struct {
  1250  	bytes.Buffer
  1251  }
  1252  
  1253  func (w *intWriter) int64(x int64) {
  1254  	var buf [binary.MaxVarintLen64]byte
  1255  	n := binary.PutVarint(buf[:], x)
  1256  	w.Write(buf[:n])
  1257  }
  1258  
  1259  func (w *intWriter) uint64(x uint64) {
  1260  	var buf [binary.MaxVarintLen64]byte
  1261  	n := binary.PutUvarint(buf[:], x)
  1262  	w.Write(buf[:n])
  1263  }
  1264  
  1265  func assert(cond bool) {
  1266  	if !cond {
  1267  		panic("internal error: assertion failed")
  1268  	}
  1269  }
  1270  
  1271  // The below is copied from go/src/cmd/compile/internal/gc/syntax.go.
  1272  
  1273  // objQueue is a FIFO queue of types.Object. The zero value of objQueue is
  1274  // a ready-to-use empty queue.
  1275  type objQueue struct {
  1276  	ring       []types.Object
  1277  	head, tail int
  1278  }
  1279  
  1280  // empty returns true if q contains no Nodes.
  1281  func (q *objQueue) empty() bool {
  1282  	return q.head == q.tail
  1283  }
  1284  
  1285  // pushTail appends n to the tail of the queue.
  1286  func (q *objQueue) pushTail(obj types.Object) {
  1287  	if len(q.ring) == 0 {
  1288  		q.ring = make([]types.Object, 16)
  1289  	} else if q.head+len(q.ring) == q.tail {
  1290  		// Grow the ring.
  1291  		nring := make([]types.Object, len(q.ring)*2)
  1292  		// Copy the old elements.
  1293  		part := q.ring[q.head%len(q.ring):]
  1294  		if q.tail-q.head <= len(part) {
  1295  			part = part[:q.tail-q.head]
  1296  			copy(nring, part)
  1297  		} else {
  1298  			pos := copy(nring, part)
  1299  			copy(nring[pos:], q.ring[:q.tail%len(q.ring)])
  1300  		}
  1301  		q.ring, q.head, q.tail = nring, 0, q.tail-q.head
  1302  	}
  1303  
  1304  	q.ring[q.tail%len(q.ring)] = obj
  1305  	q.tail++
  1306  }
  1307  
  1308  // popHead pops a node from the head of the queue. It panics if q is empty.
  1309  func (q *objQueue) popHead() types.Object {
  1310  	if q.empty() {
  1311  		panic("dequeue empty")
  1312  	}
  1313  	obj := q.ring[q.head%len(q.ring)]
  1314  	q.head++
  1315  	return obj
  1316  }
  1317  
  1318  // internalError represents an error generated inside this package.
  1319  type internalError string
  1320  
  1321  func (e internalError) Error() string { return "gcimporter: " + string(e) }
  1322  
  1323  // TODO(adonovan): make this call panic, so that it's symmetric with errorf.
  1324  // Otherwise it's easy to forget to do anything with the error.
  1325  //
  1326  // TODO(adonovan): also, consider switching the names "errorf" and
  1327  // "internalErrorf" as the former is used for bugs, whose cause is
  1328  // internal inconsistency, whereas the latter is used for ordinary
  1329  // situations like bad input, whose cause is external.
  1330  func internalErrorf(format string, args ...interface{}) error {
  1331  	return internalError(fmt.Sprintf(format, args...))
  1332  }