chore: update deps
This commit is contained in:
parent
95803010d5
commit
d514cf41c3
525 changed files with 43230 additions and 14901 deletions
38
vendor/golang.org/x/tools/internal/aliases/aliases.go
generated
vendored
Normal file
38
vendor/golang.org/x/tools/internal/aliases/aliases.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package aliases
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// Package aliases defines backward compatible shims
|
||||
// for the types.Alias type representation added in 1.22.
|
||||
// This defines placeholders for x/tools until 1.26.
|
||||
|
||||
// NewAlias creates a new TypeName in Package pkg that
|
||||
// is an alias for the type rhs.
|
||||
//
|
||||
// The enabled parameter determines whether the resulting [TypeName]'s
|
||||
// type is an [types.Alias]. Its value must be the result of a call to
|
||||
// [Enabled], which computes the effective value of
|
||||
// GODEBUG=gotypesalias=... by invoking the type checker. The Enabled
|
||||
// function is expensive and should be called once per task (e.g.
|
||||
// package import), not once per call to NewAlias.
|
||||
//
|
||||
// Precondition: enabled || len(tparams)==0.
|
||||
// If materialized aliases are disabled, there must not be any type parameters.
|
||||
func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName {
|
||||
if enabled {
|
||||
tname := types.NewTypeName(pos, pkg, name, nil)
|
||||
SetTypeParams(types.NewAlias(tname, rhs), tparams)
|
||||
return tname
|
||||
}
|
||||
if len(tparams) > 0 {
|
||||
panic("cannot create an alias with type parameters when gotypesalias is not enabled")
|
||||
}
|
||||
return types.NewTypeName(pos, pkg, name, rhs)
|
||||
}
|
80
vendor/golang.org/x/tools/internal/aliases/aliases_go122.go
generated
vendored
Normal file
80
vendor/golang.org/x/tools/internal/aliases/aliases_go122.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package aliases
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// Rhs returns the type on the right-hand side of the alias declaration.
|
||||
func Rhs(alias *types.Alias) types.Type {
|
||||
if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
|
||||
return alias.Rhs() // go1.23+
|
||||
}
|
||||
|
||||
// go1.22's Alias didn't have the Rhs method,
|
||||
// so Unalias is the best we can do.
|
||||
return types.Unalias(alias)
|
||||
}
|
||||
|
||||
// TypeParams returns the type parameter list of the alias.
|
||||
func TypeParams(alias *types.Alias) *types.TypeParamList {
|
||||
if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok {
|
||||
return alias.TypeParams() // go1.23+
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTypeParams sets the type parameters of the alias type.
|
||||
func SetTypeParams(alias *types.Alias, tparams []*types.TypeParam) {
|
||||
if alias, ok := any(alias).(interface {
|
||||
SetTypeParams(tparams []*types.TypeParam)
|
||||
}); ok {
|
||||
alias.SetTypeParams(tparams) // go1.23+
|
||||
} else if len(tparams) > 0 {
|
||||
panic("cannot set type parameters of an Alias type in go1.22")
|
||||
}
|
||||
}
|
||||
|
||||
// TypeArgs returns the type arguments used to instantiate the Alias type.
|
||||
func TypeArgs(alias *types.Alias) *types.TypeList {
|
||||
if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok {
|
||||
return alias.TypeArgs() // go1.23+
|
||||
}
|
||||
return nil // empty (go1.22)
|
||||
}
|
||||
|
||||
// Origin returns the generic Alias type of which alias is an instance.
|
||||
// If alias is not an instance of a generic alias, Origin returns alias.
|
||||
func Origin(alias *types.Alias) *types.Alias {
|
||||
if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok {
|
||||
return alias.Origin() // go1.23+
|
||||
}
|
||||
return alias // not an instance of a generic alias (go1.22)
|
||||
}
|
||||
|
||||
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
||||
//
|
||||
// This function is expensive! Call it sparingly.
|
||||
func Enabled() bool {
|
||||
// The only reliable way to compute the answer is to invoke go/types.
|
||||
// We don't parse the GODEBUG environment variable, because
|
||||
// (a) it's tricky to do so in a manner that is consistent
|
||||
// with the godebug package; in particular, a simple
|
||||
// substring check is not good enough. The value is a
|
||||
// rightmost-wins list of options. But more importantly:
|
||||
// (b) it is impossible to detect changes to the effective
|
||||
// setting caused by os.Setenv("GODEBUG"), as happens in
|
||||
// many tests. Therefore any attempt to cache the result
|
||||
// is just incorrect.
|
||||
fset := token.NewFileSet()
|
||||
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", parser.SkipObjectResolution)
|
||||
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
|
||||
_, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
|
||||
return enabled
|
||||
}
|
21
vendor/golang.org/x/tools/internal/event/keys/util.go
generated
vendored
Normal file
21
vendor/golang.org/x/tools/internal/event/keys/util.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Join returns a canonical join of the keys in S:
|
||||
// a sorted comma-separated string list.
|
||||
func Join[S ~[]T, T ~string](s S) string {
|
||||
strs := make([]string, 0, len(s))
|
||||
for _, v := range s {
|
||||
strs = append(strs, string(v))
|
||||
}
|
||||
sort.Strings(strs)
|
||||
return strings.Join(strs, ",")
|
||||
}
|
852
vendor/golang.org/x/tools/internal/gcimporter/bexport.go
generated
vendored
852
vendor/golang.org/x/tools/internal/gcimporter/bexport.go
generated
vendored
|
@ -1,852 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Binary package export.
|
||||
// This file was derived from $GOROOT/src/cmd/compile/internal/gc/bexport.go;
|
||||
// see that file for specification of the format.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// If debugFormat is set, each integer and string value is preceded by a marker
|
||||
// and position information in the encoding. This mechanism permits an importer
|
||||
// to recognize immediately when it is out of sync. The importer recognizes this
|
||||
// mode automatically (i.e., it can import export data produced with debugging
|
||||
// support even if debugFormat is not set at the time of import). This mode will
|
||||
// lead to massively larger export data (by a factor of 2 to 3) and should only
|
||||
// be enabled during development and debugging.
|
||||
//
|
||||
// NOTE: This flag is the first flag to enable if importing dies because of
|
||||
// (suspected) format errors, and whenever a change is made to the format.
|
||||
const debugFormat = false // default: false
|
||||
|
||||
// Current export format version. Increase with each format change.
|
||||
//
|
||||
// Note: The latest binary (non-indexed) export format is at version 6.
|
||||
// This exporter is still at level 4, but it doesn't matter since
|
||||
// the binary importer can handle older versions just fine.
|
||||
//
|
||||
// 6: package height (CL 105038) -- NOT IMPLEMENTED HERE
|
||||
// 5: improved position encoding efficiency (issue 20080, CL 41619) -- NOT IMPLEMENTED HERE
|
||||
// 4: type name objects support type aliases, uses aliasTag
|
||||
// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
|
||||
// 2: removed unused bool in ODCL export (compiler only)
|
||||
// 1: header format change (more regular), export package for _ struct fields
|
||||
// 0: Go1.7 encoding
|
||||
const exportVersion = 4
|
||||
|
||||
// trackAllTypes enables cycle tracking for all types, not just named
|
||||
// types. The existing compiler invariants assume that unnamed types
|
||||
// that are not completely set up are not used, or else there are spurious
|
||||
// errors.
|
||||
// If disabled, only named types are tracked, possibly leading to slightly
|
||||
// less efficient encoding in rare cases. It also prevents the export of
|
||||
// some corner-case type declarations (but those are not handled correctly
|
||||
// with with the textual export format either).
|
||||
// TODO(gri) enable and remove once issues caused by it are fixed
|
||||
const trackAllTypes = false
|
||||
|
||||
type exporter struct {
|
||||
fset *token.FileSet
|
||||
out bytes.Buffer
|
||||
|
||||
// object -> index maps, indexed in order of serialization
|
||||
strIndex map[string]int
|
||||
pkgIndex map[*types.Package]int
|
||||
typIndex map[types.Type]int
|
||||
|
||||
// position encoding
|
||||
posInfoFormat bool
|
||||
prevFile string
|
||||
prevLine int
|
||||
|
||||
// debugging support
|
||||
written int // bytes written
|
||||
indent int // for trace
|
||||
}
|
||||
|
||||
// internalError represents an error generated inside this package.
|
||||
type internalError string
|
||||
|
||||
func (e internalError) Error() string { return "gcimporter: " + string(e) }
|
||||
|
||||
func internalErrorf(format string, args ...interface{}) error {
|
||||
return internalError(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// BExportData returns binary export data for pkg.
|
||||
// If no file set is provided, position info will be missing.
|
||||
func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
|
||||
if !debug {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
if ierr, ok := e.(internalError); ok {
|
||||
err = ierr
|
||||
return
|
||||
}
|
||||
// Not an internal error; panic again.
|
||||
panic(e)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
p := exporter{
|
||||
fset: fset,
|
||||
strIndex: map[string]int{"": 0}, // empty string is mapped to 0
|
||||
pkgIndex: make(map[*types.Package]int),
|
||||
typIndex: make(map[types.Type]int),
|
||||
posInfoFormat: true, // TODO(gri) might become a flag, eventually
|
||||
}
|
||||
|
||||
// write version info
|
||||
// The version string must start with "version %d" where %d is the version
|
||||
// number. Additional debugging information may follow after a blank; that
|
||||
// text is ignored by the importer.
|
||||
p.rawStringln(fmt.Sprintf("version %d", exportVersion))
|
||||
var debug string
|
||||
if debugFormat {
|
||||
debug = "debug"
|
||||
}
|
||||
p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly
|
||||
p.bool(trackAllTypes)
|
||||
p.bool(p.posInfoFormat)
|
||||
|
||||
// --- generic export data ---
|
||||
|
||||
// populate type map with predeclared "known" types
|
||||
for index, typ := range predeclared() {
|
||||
p.typIndex[typ] = index
|
||||
}
|
||||
if len(p.typIndex) != len(predeclared()) {
|
||||
return nil, internalError("duplicate entries in type map?")
|
||||
}
|
||||
|
||||
// write package data
|
||||
p.pkg(pkg, true)
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
// write objects
|
||||
objcount := 0
|
||||
scope := pkg.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
if !token.IsExported(name) {
|
||||
continue
|
||||
}
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.obj(scope.Lookup(name))
|
||||
objcount++
|
||||
}
|
||||
|
||||
// indicate end of list
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.tag(endTag)
|
||||
|
||||
// for self-verification only (redundant)
|
||||
p.int(objcount)
|
||||
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
// --- end of export data ---
|
||||
|
||||
return p.out.Bytes(), nil
|
||||
}
|
||||
|
||||
func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
|
||||
if pkg == nil {
|
||||
panic(internalError("unexpected nil pkg"))
|
||||
}
|
||||
|
||||
// if we saw the package before, write its index (>= 0)
|
||||
if i, ok := p.pkgIndex[pkg]; ok {
|
||||
p.index('P', i)
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise, remember the package, write the package tag (< 0) and package data
|
||||
if trace {
|
||||
p.tracef("P%d = { ", len(p.pkgIndex))
|
||||
defer p.tracef("} ")
|
||||
}
|
||||
p.pkgIndex[pkg] = len(p.pkgIndex)
|
||||
|
||||
p.tag(packageTag)
|
||||
p.string(pkg.Name())
|
||||
if emptypath {
|
||||
p.string("")
|
||||
} else {
|
||||
p.string(pkg.Path())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) obj(obj types.Object) {
|
||||
switch obj := obj.(type) {
|
||||
case *types.Const:
|
||||
p.tag(constTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
p.typ(obj.Type())
|
||||
p.value(obj.Val())
|
||||
|
||||
case *types.TypeName:
|
||||
if obj.IsAlias() {
|
||||
p.tag(aliasTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
} else {
|
||||
p.tag(typeTag)
|
||||
}
|
||||
p.typ(obj.Type())
|
||||
|
||||
case *types.Var:
|
||||
p.tag(varTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
p.typ(obj.Type())
|
||||
|
||||
case *types.Func:
|
||||
p.tag(funcTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
sig := obj.Type().(*types.Signature)
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
|
||||
default:
|
||||
panic(internalErrorf("unexpected object %v (%T)", obj, obj))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) pos(obj types.Object) {
|
||||
if !p.posInfoFormat {
|
||||
return
|
||||
}
|
||||
|
||||
file, line := p.fileLine(obj)
|
||||
if file == p.prevFile {
|
||||
// common case: write line delta
|
||||
// delta == 0 means different file or no line change
|
||||
delta := line - p.prevLine
|
||||
p.int(delta)
|
||||
if delta == 0 {
|
||||
p.int(-1) // -1 means no file change
|
||||
}
|
||||
} else {
|
||||
// different file
|
||||
p.int(0)
|
||||
// Encode filename as length of common prefix with previous
|
||||
// filename, followed by (possibly empty) suffix. Filenames
|
||||
// frequently share path prefixes, so this can save a lot
|
||||
// of space and make export data size less dependent on file
|
||||
// path length. The suffix is unlikely to be empty because
|
||||
// file names tend to end in ".go".
|
||||
n := commonPrefixLen(p.prevFile, file)
|
||||
p.int(n) // n >= 0
|
||||
p.string(file[n:]) // write suffix only
|
||||
p.prevFile = file
|
||||
p.int(line)
|
||||
}
|
||||
p.prevLine = line
|
||||
}
|
||||
|
||||
func (p *exporter) fileLine(obj types.Object) (file string, line int) {
|
||||
if p.fset != nil {
|
||||
pos := p.fset.Position(obj.Pos())
|
||||
file = pos.Filename
|
||||
line = pos.Line
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func commonPrefixLen(a, b string) int {
|
||||
if len(a) > len(b) {
|
||||
a, b = b, a
|
||||
}
|
||||
// len(a) <= len(b)
|
||||
i := 0
|
||||
for i < len(a) && a[i] == b[i] {
|
||||
i++
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (p *exporter) qualifiedName(obj types.Object) {
|
||||
p.string(obj.Name())
|
||||
p.pkg(obj.Pkg(), false)
|
||||
}
|
||||
|
||||
func (p *exporter) typ(t types.Type) {
|
||||
if t == nil {
|
||||
panic(internalError("nil type"))
|
||||
}
|
||||
|
||||
// Possible optimization: Anonymous pointer types *T where
|
||||
// T is a named type are common. We could canonicalize all
|
||||
// such types *T to a single type PT = *T. This would lead
|
||||
// to at most one *T entry in typIndex, and all future *T's
|
||||
// would be encoded as the respective index directly. Would
|
||||
// save 1 byte (pointerTag) per *T and reduce the typIndex
|
||||
// size (at the cost of a canonicalization map). We can do
|
||||
// this later, without encoding format change.
|
||||
|
||||
// if we saw the type before, write its index (>= 0)
|
||||
if i, ok := p.typIndex[t]; ok {
|
||||
p.index('T', i)
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise, remember the type, write the type tag (< 0) and type data
|
||||
if trackAllTypes {
|
||||
if trace {
|
||||
p.tracef("T%d = {>\n", len(p.typIndex))
|
||||
defer p.tracef("<\n} ")
|
||||
}
|
||||
p.typIndex[t] = len(p.typIndex)
|
||||
}
|
||||
|
||||
switch t := t.(type) {
|
||||
case *types.Named:
|
||||
if !trackAllTypes {
|
||||
// if we don't track all types, track named types now
|
||||
p.typIndex[t] = len(p.typIndex)
|
||||
}
|
||||
|
||||
p.tag(namedTag)
|
||||
p.pos(t.Obj())
|
||||
p.qualifiedName(t.Obj())
|
||||
p.typ(t.Underlying())
|
||||
if !types.IsInterface(t) {
|
||||
p.assocMethods(t)
|
||||
}
|
||||
|
||||
case *types.Array:
|
||||
p.tag(arrayTag)
|
||||
p.int64(t.Len())
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *types.Slice:
|
||||
p.tag(sliceTag)
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *dddSlice:
|
||||
p.tag(dddTag)
|
||||
p.typ(t.elem)
|
||||
|
||||
case *types.Struct:
|
||||
p.tag(structTag)
|
||||
p.fieldList(t)
|
||||
|
||||
case *types.Pointer:
|
||||
p.tag(pointerTag)
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *types.Signature:
|
||||
p.tag(signatureTag)
|
||||
p.paramList(t.Params(), t.Variadic())
|
||||
p.paramList(t.Results(), false)
|
||||
|
||||
case *types.Interface:
|
||||
p.tag(interfaceTag)
|
||||
p.iface(t)
|
||||
|
||||
case *types.Map:
|
||||
p.tag(mapTag)
|
||||
p.typ(t.Key())
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *types.Chan:
|
||||
p.tag(chanTag)
|
||||
p.int(int(3 - t.Dir())) // hack
|
||||
p.typ(t.Elem())
|
||||
|
||||
default:
|
||||
panic(internalErrorf("unexpected type %T: %s", t, t))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) assocMethods(named *types.Named) {
|
||||
// Sort methods (for determinism).
|
||||
var methods []*types.Func
|
||||
for i := 0; i < named.NumMethods(); i++ {
|
||||
methods = append(methods, named.Method(i))
|
||||
}
|
||||
sort.Sort(methodsByName(methods))
|
||||
|
||||
p.int(len(methods))
|
||||
|
||||
if trace && methods != nil {
|
||||
p.tracef("associated methods {>\n")
|
||||
}
|
||||
|
||||
for i, m := range methods {
|
||||
if trace && i > 0 {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
p.pos(m)
|
||||
name := m.Name()
|
||||
p.string(name)
|
||||
if !exported(name) {
|
||||
p.pkg(m.Pkg(), false)
|
||||
}
|
||||
|
||||
sig := m.Type().(*types.Signature)
|
||||
p.paramList(types.NewTuple(sig.Recv()), false)
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
p.int(0) // dummy value for go:nointerface pragma - ignored by importer
|
||||
}
|
||||
|
||||
if trace && methods != nil {
|
||||
p.tracef("<\n} ")
|
||||
}
|
||||
}
|
||||
|
||||
type methodsByName []*types.Func
|
||||
|
||||
func (x methodsByName) Len() int { return len(x) }
|
||||
func (x methodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
func (x methodsByName) Less(i, j int) bool { return x[i].Name() < x[j].Name() }
|
||||
|
||||
func (p *exporter) fieldList(t *types.Struct) {
|
||||
if trace && t.NumFields() > 0 {
|
||||
p.tracef("fields {>\n")
|
||||
defer p.tracef("<\n} ")
|
||||
}
|
||||
|
||||
p.int(t.NumFields())
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
if trace && i > 0 {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.field(t.Field(i))
|
||||
p.string(t.Tag(i))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) field(f *types.Var) {
|
||||
if !f.IsField() {
|
||||
panic(internalError("field expected"))
|
||||
}
|
||||
|
||||
p.pos(f)
|
||||
p.fieldName(f)
|
||||
p.typ(f.Type())
|
||||
}
|
||||
|
||||
func (p *exporter) iface(t *types.Interface) {
|
||||
// TODO(gri): enable importer to load embedded interfaces,
|
||||
// then emit Embeddeds and ExplicitMethods separately here.
|
||||
p.int(0)
|
||||
|
||||
n := t.NumMethods()
|
||||
if trace && n > 0 {
|
||||
p.tracef("methods {>\n")
|
||||
defer p.tracef("<\n} ")
|
||||
}
|
||||
p.int(n)
|
||||
for i := 0; i < n; i++ {
|
||||
if trace && i > 0 {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.method(t.Method(i))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) method(m *types.Func) {
|
||||
sig := m.Type().(*types.Signature)
|
||||
if sig.Recv() == nil {
|
||||
panic(internalError("method expected"))
|
||||
}
|
||||
|
||||
p.pos(m)
|
||||
p.string(m.Name())
|
||||
if m.Name() != "_" && !token.IsExported(m.Name()) {
|
||||
p.pkg(m.Pkg(), false)
|
||||
}
|
||||
|
||||
// interface method; no need to encode receiver.
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
}
|
||||
|
||||
func (p *exporter) fieldName(f *types.Var) {
|
||||
name := f.Name()
|
||||
|
||||
if f.Anonymous() {
|
||||
// anonymous field - we distinguish between 3 cases:
|
||||
// 1) field name matches base type name and is exported
|
||||
// 2) field name matches base type name and is not exported
|
||||
// 3) field name doesn't match base type name (alias name)
|
||||
bname := basetypeName(f.Type())
|
||||
if name == bname {
|
||||
if token.IsExported(name) {
|
||||
name = "" // 1) we don't need to know the field name or package
|
||||
} else {
|
||||
name = "?" // 2) use unexported name "?" to force package export
|
||||
}
|
||||
} else {
|
||||
// 3) indicate alias and export name as is
|
||||
// (this requires an extra "@" but this is a rare case)
|
||||
p.string("@")
|
||||
}
|
||||
}
|
||||
|
||||
p.string(name)
|
||||
if name != "" && !token.IsExported(name) {
|
||||
p.pkg(f.Pkg(), false)
|
||||
}
|
||||
}
|
||||
|
||||
func basetypeName(typ types.Type) string {
|
||||
switch typ := deref(typ).(type) {
|
||||
case *types.Basic:
|
||||
return typ.Name()
|
||||
case *types.Named:
|
||||
return typ.Obj().Name()
|
||||
default:
|
||||
return "" // unnamed type
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) paramList(params *types.Tuple, variadic bool) {
|
||||
// use negative length to indicate unnamed parameters
|
||||
// (look at the first parameter only since either all
|
||||
// names are present or all are absent)
|
||||
n := params.Len()
|
||||
if n > 0 && params.At(0).Name() == "" {
|
||||
n = -n
|
||||
}
|
||||
p.int(n)
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
q := params.At(i)
|
||||
t := q.Type()
|
||||
if variadic && i == params.Len()-1 {
|
||||
t = &dddSlice{t.(*types.Slice).Elem()}
|
||||
}
|
||||
p.typ(t)
|
||||
if n > 0 {
|
||||
name := q.Name()
|
||||
p.string(name)
|
||||
if name != "_" {
|
||||
p.pkg(q.Pkg(), false)
|
||||
}
|
||||
}
|
||||
p.string("") // no compiler-specific info
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) value(x constant.Value) {
|
||||
if trace {
|
||||
p.tracef("= ")
|
||||
}
|
||||
|
||||
switch x.Kind() {
|
||||
case constant.Bool:
|
||||
tag := falseTag
|
||||
if constant.BoolVal(x) {
|
||||
tag = trueTag
|
||||
}
|
||||
p.tag(tag)
|
||||
|
||||
case constant.Int:
|
||||
if v, exact := constant.Int64Val(x); exact {
|
||||
// common case: x fits into an int64 - use compact encoding
|
||||
p.tag(int64Tag)
|
||||
p.int64(v)
|
||||
return
|
||||
}
|
||||
// uncommon case: large x - use float encoding
|
||||
// (powers of 2 will be encoded efficiently with exponent)
|
||||
p.tag(floatTag)
|
||||
p.float(constant.ToFloat(x))
|
||||
|
||||
case constant.Float:
|
||||
p.tag(floatTag)
|
||||
p.float(x)
|
||||
|
||||
case constant.Complex:
|
||||
p.tag(complexTag)
|
||||
p.float(constant.Real(x))
|
||||
p.float(constant.Imag(x))
|
||||
|
||||
case constant.String:
|
||||
p.tag(stringTag)
|
||||
p.string(constant.StringVal(x))
|
||||
|
||||
case constant.Unknown:
|
||||
// package contains type errors
|
||||
p.tag(unknownTag)
|
||||
|
||||
default:
|
||||
panic(internalErrorf("unexpected value %v (%T)", x, x))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) float(x constant.Value) {
|
||||
if x.Kind() != constant.Float {
|
||||
panic(internalErrorf("unexpected constant %v, want float", x))
|
||||
}
|
||||
// extract sign (there is no -0)
|
||||
sign := constant.Sign(x)
|
||||
if sign == 0 {
|
||||
// x == 0
|
||||
p.int(0)
|
||||
return
|
||||
}
|
||||
// x != 0
|
||||
|
||||
var f big.Float
|
||||
if v, exact := constant.Float64Val(x); exact {
|
||||
// float64
|
||||
f.SetFloat64(v)
|
||||
} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
|
||||
// TODO(gri): add big.Rat accessor to constant.Value.
|
||||
r := valueToRat(num)
|
||||
f.SetRat(r.Quo(r, valueToRat(denom)))
|
||||
} else {
|
||||
// Value too large to represent as a fraction => inaccessible.
|
||||
// TODO(gri): add big.Float accessor to constant.Value.
|
||||
f.SetFloat64(math.MaxFloat64) // FIXME
|
||||
}
|
||||
|
||||
// extract exponent such that 0.5 <= m < 1.0
|
||||
var m big.Float
|
||||
exp := f.MantExp(&m)
|
||||
|
||||
// extract mantissa as *big.Int
|
||||
// - set exponent large enough so mant satisfies mant.IsInt()
|
||||
// - get *big.Int from mant
|
||||
m.SetMantExp(&m, int(m.MinPrec()))
|
||||
mant, acc := m.Int(nil)
|
||||
if acc != big.Exact {
|
||||
panic(internalError("internal error"))
|
||||
}
|
||||
|
||||
p.int(sign)
|
||||
p.int(exp)
|
||||
p.string(string(mant.Bytes()))
|
||||
}
|
||||
|
||||
func valueToRat(x constant.Value) *big.Rat {
|
||||
// Convert little-endian to big-endian.
|
||||
// I can't believe this is necessary.
|
||||
bytes := constant.Bytes(x)
|
||||
for i := 0; i < len(bytes)/2; i++ {
|
||||
bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
|
||||
}
|
||||
return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
|
||||
}
|
||||
|
||||
func (p *exporter) bool(b bool) bool {
|
||||
if trace {
|
||||
p.tracef("[")
|
||||
defer p.tracef("= %v] ", b)
|
||||
}
|
||||
|
||||
x := 0
|
||||
if b {
|
||||
x = 1
|
||||
}
|
||||
p.int(x)
|
||||
return b
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Low-level encoders
|
||||
|
||||
func (p *exporter) index(marker byte, index int) {
|
||||
if index < 0 {
|
||||
panic(internalError("invalid index < 0"))
|
||||
}
|
||||
if debugFormat {
|
||||
p.marker('t')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%c%d ", marker, index)
|
||||
}
|
||||
p.rawInt64(int64(index))
|
||||
}
|
||||
|
||||
func (p *exporter) tag(tag int) {
|
||||
if tag >= 0 {
|
||||
panic(internalError("invalid tag >= 0"))
|
||||
}
|
||||
if debugFormat {
|
||||
p.marker('t')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%s ", tagString[-tag])
|
||||
}
|
||||
p.rawInt64(int64(tag))
|
||||
}
|
||||
|
||||
func (p *exporter) int(x int) {
|
||||
p.int64(int64(x))
|
||||
}
|
||||
|
||||
func (p *exporter) int64(x int64) {
|
||||
if debugFormat {
|
||||
p.marker('i')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%d ", x)
|
||||
}
|
||||
p.rawInt64(x)
|
||||
}
|
||||
|
||||
func (p *exporter) string(s string) {
|
||||
if debugFormat {
|
||||
p.marker('s')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%q ", s)
|
||||
}
|
||||
// if we saw the string before, write its index (>= 0)
|
||||
// (the empty string is mapped to 0)
|
||||
if i, ok := p.strIndex[s]; ok {
|
||||
p.rawInt64(int64(i))
|
||||
return
|
||||
}
|
||||
// otherwise, remember string and write its negative length and bytes
|
||||
p.strIndex[s] = len(p.strIndex)
|
||||
p.rawInt64(-int64(len(s)))
|
||||
for i := 0; i < len(s); i++ {
|
||||
p.rawByte(s[i])
|
||||
}
|
||||
}
|
||||
|
||||
// marker emits a marker byte and position information which makes
|
||||
// it easy for a reader to detect if it is "out of sync". Used for
|
||||
// debugFormat format only.
|
||||
func (p *exporter) marker(m byte) {
|
||||
p.rawByte(m)
|
||||
// Enable this for help tracking down the location
|
||||
// of an incorrect marker when running in debugFormat.
|
||||
if false && trace {
|
||||
p.tracef("#%d ", p.written)
|
||||
}
|
||||
p.rawInt64(int64(p.written))
|
||||
}
|
||||
|
||||
// rawInt64 should only be used by low-level encoders.
|
||||
func (p *exporter) rawInt64(x int64) {
|
||||
var tmp [binary.MaxVarintLen64]byte
|
||||
n := binary.PutVarint(tmp[:], x)
|
||||
for i := 0; i < n; i++ {
|
||||
p.rawByte(tmp[i])
|
||||
}
|
||||
}
|
||||
|
||||
// rawStringln should only be used to emit the initial version string.
|
||||
func (p *exporter) rawStringln(s string) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
p.rawByte(s[i])
|
||||
}
|
||||
p.rawByte('\n')
|
||||
}
|
||||
|
||||
// rawByte is the bottleneck interface to write to p.out.
|
||||
// rawByte escapes b as follows (any encoding does that
|
||||
// hides '$'):
|
||||
//
|
||||
// '$' => '|' 'S'
|
||||
// '|' => '|' '|'
|
||||
//
|
||||
// Necessary so other tools can find the end of the
|
||||
// export data by searching for "$$".
|
||||
// rawByte should only be used by low-level encoders.
|
||||
func (p *exporter) rawByte(b byte) {
|
||||
switch b {
|
||||
case '$':
|
||||
// write '$' as '|' 'S'
|
||||
b = 'S'
|
||||
fallthrough
|
||||
case '|':
|
||||
// write '|' as '|' '|'
|
||||
p.out.WriteByte('|')
|
||||
p.written++
|
||||
}
|
||||
p.out.WriteByte(b)
|
||||
p.written++
|
||||
}
|
||||
|
||||
// tracef is like fmt.Printf but it rewrites the format string
|
||||
// to take care of indentation.
|
||||
func (p *exporter) tracef(format string, args ...interface{}) {
|
||||
if strings.ContainsAny(format, "<>\n") {
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < len(format); i++ {
|
||||
// no need to deal with runes
|
||||
ch := format[i]
|
||||
switch ch {
|
||||
case '>':
|
||||
p.indent++
|
||||
continue
|
||||
case '<':
|
||||
p.indent--
|
||||
continue
|
||||
}
|
||||
buf.WriteByte(ch)
|
||||
if ch == '\n' {
|
||||
for j := p.indent; j > 0; j-- {
|
||||
buf.WriteString(". ")
|
||||
}
|
||||
}
|
||||
}
|
||||
format = buf.String()
|
||||
}
|
||||
fmt.Printf(format, args...)
|
||||
}
|
||||
|
||||
// Debugging support.
|
||||
// (tagString is only used when tracing is enabled)
|
||||
var tagString = [...]string{
|
||||
// Packages
|
||||
-packageTag: "package",
|
||||
|
||||
// Types
|
||||
-namedTag: "named type",
|
||||
-arrayTag: "array",
|
||||
-sliceTag: "slice",
|
||||
-dddTag: "ddd",
|
||||
-structTag: "struct",
|
||||
-pointerTag: "pointer",
|
||||
-signatureTag: "signature",
|
||||
-interfaceTag: "interface",
|
||||
-mapTag: "map",
|
||||
-chanTag: "chan",
|
||||
|
||||
// Values
|
||||
-falseTag: "false",
|
||||
-trueTag: "true",
|
||||
-int64Tag: "int64",
|
||||
-floatTag: "float",
|
||||
-fractionTag: "fraction",
|
||||
-complexTag: "complex",
|
||||
-stringTag: "string",
|
||||
-unknownTag: "unknown",
|
||||
|
||||
// Type aliases
|
||||
-aliasTag: "alias",
|
||||
}
|
968
vendor/golang.org/x/tools/internal/gcimporter/bimport.go
generated
vendored
968
vendor/golang.org/x/tools/internal/gcimporter/bimport.go
generated
vendored
|
@ -2,340 +2,24 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go.
|
||||
// This file contains the remaining vestiges of
|
||||
// $GOROOT/src/go/internal/gcimporter/bimport.go.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type importer struct {
|
||||
imports map[string]*types.Package
|
||||
data []byte
|
||||
importpath string
|
||||
buf []byte // for reading strings
|
||||
version int // export format version
|
||||
|
||||
// object lists
|
||||
strList []string // in order of appearance
|
||||
pathList []string // in order of appearance
|
||||
pkgList []*types.Package // in order of appearance
|
||||
typList []types.Type // in order of appearance
|
||||
interfaceList []*types.Interface // for delayed completion only
|
||||
trackAllTypes bool
|
||||
|
||||
// position encoding
|
||||
posInfoFormat bool
|
||||
prevFile string
|
||||
prevLine int
|
||||
fake fakeFileSet
|
||||
|
||||
// debugging support
|
||||
debugFormat bool
|
||||
read int // bytes read
|
||||
}
|
||||
|
||||
// BImportData imports a package from the serialized package data
|
||||
// and returns the number of bytes consumed and a reference to the package.
|
||||
// If the export data version is not recognized or the format is otherwise
|
||||
// compromised, an error is returned.
|
||||
func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||
// catch panics and return them as errors
|
||||
const currentVersion = 6
|
||||
version := -1 // unknown version
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// Return a (possibly nil or incomplete) package unchanged (see #16088).
|
||||
if version > currentVersion {
|
||||
err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
|
||||
} else {
|
||||
err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
p := importer{
|
||||
imports: imports,
|
||||
data: data,
|
||||
importpath: path,
|
||||
version: version,
|
||||
strList: []string{""}, // empty string is mapped to 0
|
||||
pathList: []string{""}, // empty string is mapped to 0
|
||||
fake: fakeFileSet{
|
||||
fset: fset,
|
||||
files: make(map[string]*fileInfo),
|
||||
},
|
||||
}
|
||||
defer p.fake.setLines() // set lines for files in fset
|
||||
|
||||
// read version info
|
||||
var versionstr string
|
||||
if b := p.rawByte(); b == 'c' || b == 'd' {
|
||||
// Go1.7 encoding; first byte encodes low-level
|
||||
// encoding format (compact vs debug).
|
||||
// For backward-compatibility only (avoid problems with
|
||||
// old installed packages). Newly compiled packages use
|
||||
// the extensible format string.
|
||||
// TODO(gri) Remove this support eventually; after Go1.8.
|
||||
if b == 'd' {
|
||||
p.debugFormat = true
|
||||
}
|
||||
p.trackAllTypes = p.rawByte() == 'a'
|
||||
p.posInfoFormat = p.int() != 0
|
||||
versionstr = p.string()
|
||||
if versionstr == "v1" {
|
||||
version = 0
|
||||
}
|
||||
} else {
|
||||
// Go1.8 extensible encoding
|
||||
// read version string and extract version number (ignore anything after the version number)
|
||||
versionstr = p.rawStringln(b)
|
||||
if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
|
||||
if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
|
||||
version = v
|
||||
}
|
||||
}
|
||||
}
|
||||
p.version = version
|
||||
|
||||
// read version specific flags - extend as necessary
|
||||
switch p.version {
|
||||
// case currentVersion:
|
||||
// ...
|
||||
// fallthrough
|
||||
case currentVersion, 5, 4, 3, 2, 1:
|
||||
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
||||
p.trackAllTypes = p.int() != 0
|
||||
p.posInfoFormat = p.int() != 0
|
||||
case 0:
|
||||
// Go1.7 encoding format - nothing to do here
|
||||
default:
|
||||
errorf("unknown bexport format version %d (%q)", p.version, versionstr)
|
||||
}
|
||||
|
||||
// --- generic export data ---
|
||||
|
||||
// populate typList with predeclared "known" types
|
||||
p.typList = append(p.typList, predeclared()...)
|
||||
|
||||
// read package data
|
||||
pkg = p.pkg()
|
||||
|
||||
// read objects of phase 1 only (see cmd/compile/internal/gc/bexport.go)
|
||||
objcount := 0
|
||||
for {
|
||||
tag := p.tagOrIndex()
|
||||
if tag == endTag {
|
||||
break
|
||||
}
|
||||
p.obj(tag)
|
||||
objcount++
|
||||
}
|
||||
|
||||
// self-verification
|
||||
if count := p.int(); count != objcount {
|
||||
errorf("got %d objects; want %d", objcount, count)
|
||||
}
|
||||
|
||||
// ignore compiler-specific import data
|
||||
|
||||
// complete interfaces
|
||||
// TODO(gri) re-investigate if we still need to do this in a delayed fashion
|
||||
for _, typ := range p.interfaceList {
|
||||
typ.Complete()
|
||||
}
|
||||
|
||||
// record all referenced packages as imports
|
||||
list := append(([]*types.Package)(nil), p.pkgList[1:]...)
|
||||
sort.Sort(byPath(list))
|
||||
pkg.SetImports(list)
|
||||
|
||||
// package was imported completely and without errors
|
||||
pkg.MarkComplete()
|
||||
|
||||
return p.read, pkg, nil
|
||||
}
|
||||
|
||||
func errorf(format string, args ...interface{}) {
|
||||
panic(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (p *importer) pkg() *types.Package {
|
||||
// if the package was seen before, i is its index (>= 0)
|
||||
i := p.tagOrIndex()
|
||||
if i >= 0 {
|
||||
return p.pkgList[i]
|
||||
}
|
||||
|
||||
// otherwise, i is the package tag (< 0)
|
||||
if i != packageTag {
|
||||
errorf("unexpected package tag %d version %d", i, p.version)
|
||||
}
|
||||
|
||||
// read package data
|
||||
name := p.string()
|
||||
var path string
|
||||
if p.version >= 5 {
|
||||
path = p.path()
|
||||
} else {
|
||||
path = p.string()
|
||||
}
|
||||
if p.version >= 6 {
|
||||
p.int() // package height; unused by go/types
|
||||
}
|
||||
|
||||
// we should never see an empty package name
|
||||
if name == "" {
|
||||
errorf("empty package name in import")
|
||||
}
|
||||
|
||||
// an empty path denotes the package we are currently importing;
|
||||
// it must be the first package we see
|
||||
if (path == "") != (len(p.pkgList) == 0) {
|
||||
errorf("package path %q for pkg index %d", path, len(p.pkgList))
|
||||
}
|
||||
|
||||
// if the package was imported before, use that one; otherwise create a new one
|
||||
if path == "" {
|
||||
path = p.importpath
|
||||
}
|
||||
pkg := p.imports[path]
|
||||
if pkg == nil {
|
||||
pkg = types.NewPackage(path, name)
|
||||
p.imports[path] = pkg
|
||||
} else if pkg.Name() != name {
|
||||
errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
|
||||
}
|
||||
p.pkgList = append(p.pkgList, pkg)
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
||||
// objTag returns the tag value for each object kind.
|
||||
func objTag(obj types.Object) int {
|
||||
switch obj.(type) {
|
||||
case *types.Const:
|
||||
return constTag
|
||||
case *types.TypeName:
|
||||
return typeTag
|
||||
case *types.Var:
|
||||
return varTag
|
||||
case *types.Func:
|
||||
return funcTag
|
||||
default:
|
||||
errorf("unexpected object: %v (%T)", obj, obj) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func sameObj(a, b types.Object) bool {
|
||||
// Because unnamed types are not canonicalized, we cannot simply compare types for
|
||||
// (pointer) identity.
|
||||
// Ideally we'd check equality of constant values as well, but this is good enough.
|
||||
return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
|
||||
}
|
||||
|
||||
func (p *importer) declare(obj types.Object) {
|
||||
pkg := obj.Pkg()
|
||||
if alt := pkg.Scope().Insert(obj); alt != nil {
|
||||
// This can only trigger if we import a (non-type) object a second time.
|
||||
// Excluding type aliases, this cannot happen because 1) we only import a package
|
||||
// once; and b) we ignore compiler-specific export data which may contain
|
||||
// functions whose inlined function bodies refer to other functions that
|
||||
// were already imported.
|
||||
// However, type aliases require reexporting the original type, so we need
|
||||
// to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
|
||||
// method importer.obj, switch case importing functions).
|
||||
// TODO(gri) review/update this comment once the gc compiler handles type aliases.
|
||||
if !sameObj(obj, alt) {
|
||||
errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) obj(tag int) {
|
||||
switch tag {
|
||||
case constTag:
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil, nil)
|
||||
val := p.value()
|
||||
p.declare(types.NewConst(pos, pkg, name, typ, val))
|
||||
|
||||
case aliasTag:
|
||||
// TODO(gri) verify type alias hookup is correct
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil, nil)
|
||||
p.declare(types.NewTypeName(pos, pkg, name, typ))
|
||||
|
||||
case typeTag:
|
||||
p.typ(nil, nil)
|
||||
|
||||
case varTag:
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil, nil)
|
||||
p.declare(types.NewVar(pos, pkg, name, typ))
|
||||
|
||||
case funcTag:
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
sig := types.NewSignature(nil, params, result, isddd)
|
||||
p.declare(types.NewFunc(pos, pkg, name, sig))
|
||||
|
||||
default:
|
||||
errorf("unexpected object tag %d", tag)
|
||||
}
|
||||
}
|
||||
|
||||
const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
|
||||
|
||||
func (p *importer) pos() token.Pos {
|
||||
if !p.posInfoFormat {
|
||||
return token.NoPos
|
||||
}
|
||||
|
||||
file := p.prevFile
|
||||
line := p.prevLine
|
||||
delta := p.int()
|
||||
line += delta
|
||||
if p.version >= 5 {
|
||||
if delta == deltaNewFile {
|
||||
if n := p.int(); n >= 0 {
|
||||
// file changed
|
||||
file = p.path()
|
||||
line = n
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if delta == 0 {
|
||||
if n := p.int(); n >= 0 {
|
||||
// file changed
|
||||
file = p.prevFile[:n] + p.string()
|
||||
line = p.int()
|
||||
}
|
||||
}
|
||||
}
|
||||
p.prevFile = file
|
||||
p.prevLine = line
|
||||
|
||||
return p.fake.pos(file, line, 0)
|
||||
}
|
||||
|
||||
// Synthesize a token.Pos
|
||||
type fakeFileSet struct {
|
||||
fset *token.FileSet
|
||||
|
@ -389,205 +73,6 @@ var (
|
|||
fakeLinesOnce sync.Once
|
||||
)
|
||||
|
||||
func (p *importer) qualifiedName() (pkg *types.Package, name string) {
|
||||
name = p.string()
|
||||
pkg = p.pkg()
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) record(t types.Type) {
|
||||
p.typList = append(p.typList, t)
|
||||
}
|
||||
|
||||
// A dddSlice is a types.Type representing ...T parameters.
|
||||
// It only appears for parameter types and does not escape
|
||||
// the importer.
|
||||
type dddSlice struct {
|
||||
elem types.Type
|
||||
}
|
||||
|
||||
func (t *dddSlice) Underlying() types.Type { return t }
|
||||
func (t *dddSlice) String() string { return "..." + t.elem.String() }
|
||||
|
||||
// parent is the package which declared the type; parent == nil means
|
||||
// the package currently imported. The parent package is needed for
|
||||
// exported struct fields and interface methods which don't contain
|
||||
// explicit package information in the export data.
|
||||
//
|
||||
// A non-nil tname is used as the "owner" of the result type; i.e.,
|
||||
// the result type is the underlying type of tname. tname is used
|
||||
// to give interface methods a named receiver type where possible.
|
||||
func (p *importer) typ(parent *types.Package, tname *types.Named) types.Type {
|
||||
// if the type was seen before, i is its index (>= 0)
|
||||
i := p.tagOrIndex()
|
||||
if i >= 0 {
|
||||
return p.typList[i]
|
||||
}
|
||||
|
||||
// otherwise, i is the type tag (< 0)
|
||||
switch i {
|
||||
case namedTag:
|
||||
// read type object
|
||||
pos := p.pos()
|
||||
parent, name := p.qualifiedName()
|
||||
scope := parent.Scope()
|
||||
obj := scope.Lookup(name)
|
||||
|
||||
// if the object doesn't exist yet, create and insert it
|
||||
if obj == nil {
|
||||
obj = types.NewTypeName(pos, parent, name, nil)
|
||||
scope.Insert(obj)
|
||||
}
|
||||
|
||||
if _, ok := obj.(*types.TypeName); !ok {
|
||||
errorf("pkg = %s, name = %s => %s", parent, name, obj)
|
||||
}
|
||||
|
||||
// associate new named type with obj if it doesn't exist yet
|
||||
t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
|
||||
|
||||
// but record the existing type, if any
|
||||
tname := obj.Type().(*types.Named) // tname is either t0 or the existing type
|
||||
p.record(tname)
|
||||
|
||||
// read underlying type
|
||||
t0.SetUnderlying(p.typ(parent, t0))
|
||||
|
||||
// interfaces don't have associated methods
|
||||
if types.IsInterface(t0) {
|
||||
return tname
|
||||
}
|
||||
|
||||
// read associated methods
|
||||
for i := p.int(); i > 0; i-- {
|
||||
// TODO(gri) replace this with something closer to fieldName
|
||||
pos := p.pos()
|
||||
name := p.string()
|
||||
if !exported(name) {
|
||||
p.pkg()
|
||||
}
|
||||
|
||||
recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
p.int() // go:nointerface pragma - discarded
|
||||
|
||||
sig := types.NewSignature(recv.At(0), params, result, isddd)
|
||||
t0.AddMethod(types.NewFunc(pos, parent, name, sig))
|
||||
}
|
||||
|
||||
return tname
|
||||
|
||||
case arrayTag:
|
||||
t := new(types.Array)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
n := p.int64()
|
||||
*t = *types.NewArray(p.typ(parent, nil), n)
|
||||
return t
|
||||
|
||||
case sliceTag:
|
||||
t := new(types.Slice)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
*t = *types.NewSlice(p.typ(parent, nil))
|
||||
return t
|
||||
|
||||
case dddTag:
|
||||
t := new(dddSlice)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
t.elem = p.typ(parent, nil)
|
||||
return t
|
||||
|
||||
case structTag:
|
||||
t := new(types.Struct)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
*t = *types.NewStruct(p.fieldList(parent))
|
||||
return t
|
||||
|
||||
case pointerTag:
|
||||
t := new(types.Pointer)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
*t = *types.NewPointer(p.typ(parent, nil))
|
||||
return t
|
||||
|
||||
case signatureTag:
|
||||
t := new(types.Signature)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
*t = *types.NewSignature(nil, params, result, isddd)
|
||||
return t
|
||||
|
||||
case interfaceTag:
|
||||
// Create a dummy entry in the type list. This is safe because we
|
||||
// cannot expect the interface type to appear in a cycle, as any
|
||||
// such cycle must contain a named type which would have been
|
||||
// first defined earlier.
|
||||
// TODO(gri) Is this still true now that we have type aliases?
|
||||
// See issue #23225.
|
||||
n := len(p.typList)
|
||||
if p.trackAllTypes {
|
||||
p.record(nil)
|
||||
}
|
||||
|
||||
var embeddeds []types.Type
|
||||
for n := p.int(); n > 0; n-- {
|
||||
p.pos()
|
||||
embeddeds = append(embeddeds, p.typ(parent, nil))
|
||||
}
|
||||
|
||||
t := newInterface(p.methodList(parent, tname), embeddeds)
|
||||
p.interfaceList = append(p.interfaceList, t)
|
||||
if p.trackAllTypes {
|
||||
p.typList[n] = t
|
||||
}
|
||||
return t
|
||||
|
||||
case mapTag:
|
||||
t := new(types.Map)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
key := p.typ(parent, nil)
|
||||
val := p.typ(parent, nil)
|
||||
*t = *types.NewMap(key, val)
|
||||
return t
|
||||
|
||||
case chanTag:
|
||||
t := new(types.Chan)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
dir := chanDir(p.int())
|
||||
val := p.typ(parent, nil)
|
||||
*t = *types.NewChan(dir, val)
|
||||
return t
|
||||
|
||||
default:
|
||||
errorf("unexpected type tag %d", i) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func chanDir(d int) types.ChanDir {
|
||||
// tag values must match the constants in cmd/compile/internal/gc/go.go
|
||||
switch d {
|
||||
|
@ -602,452 +87,3 @@ func chanDir(d int) types.ChanDir {
|
|||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) {
|
||||
if n := p.int(); n > 0 {
|
||||
fields = make([]*types.Var, n)
|
||||
tags = make([]string, n)
|
||||
for i := range fields {
|
||||
fields[i], tags[i] = p.field(parent)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) field(parent *types.Package) (*types.Var, string) {
|
||||
pos := p.pos()
|
||||
pkg, name, alias := p.fieldName(parent)
|
||||
typ := p.typ(parent, nil)
|
||||
tag := p.string()
|
||||
|
||||
anonymous := false
|
||||
if name == "" {
|
||||
// anonymous field - typ must be T or *T and T must be a type name
|
||||
switch typ := deref(typ).(type) {
|
||||
case *types.Basic: // basic types are named types
|
||||
pkg = nil // // objects defined in Universe scope have no package
|
||||
name = typ.Name()
|
||||
case *types.Named:
|
||||
name = typ.Obj().Name()
|
||||
default:
|
||||
errorf("named base type expected")
|
||||
}
|
||||
anonymous = true
|
||||
} else if alias {
|
||||
// anonymous field: we have an explicit name because it's an alias
|
||||
anonymous = true
|
||||
}
|
||||
|
||||
return types.NewField(pos, pkg, name, typ, anonymous), tag
|
||||
}
|
||||
|
||||
func (p *importer) methodList(parent *types.Package, baseType *types.Named) (methods []*types.Func) {
|
||||
if n := p.int(); n > 0 {
|
||||
methods = make([]*types.Func, n)
|
||||
for i := range methods {
|
||||
methods[i] = p.method(parent, baseType)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) method(parent *types.Package, baseType *types.Named) *types.Func {
|
||||
pos := p.pos()
|
||||
pkg, name, _ := p.fieldName(parent)
|
||||
// If we don't have a baseType, use a nil receiver.
|
||||
// A receiver using the actual interface type (which
|
||||
// we don't know yet) will be filled in when we call
|
||||
// types.Interface.Complete.
|
||||
var recv *types.Var
|
||||
if baseType != nil {
|
||||
recv = types.NewVar(token.NoPos, parent, "", baseType)
|
||||
}
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
sig := types.NewSignature(recv, params, result, isddd)
|
||||
return types.NewFunc(pos, pkg, name, sig)
|
||||
}
|
||||
|
||||
func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
|
||||
name = p.string()
|
||||
pkg = parent
|
||||
if pkg == nil {
|
||||
// use the imported package instead
|
||||
pkg = p.pkgList[0]
|
||||
}
|
||||
if p.version == 0 && name == "_" {
|
||||
// version 0 didn't export a package for _ fields
|
||||
return
|
||||
}
|
||||
switch name {
|
||||
case "":
|
||||
// 1) field name matches base type name and is exported: nothing to do
|
||||
case "?":
|
||||
// 2) field name matches base type name and is not exported: need package
|
||||
name = ""
|
||||
pkg = p.pkg()
|
||||
case "@":
|
||||
// 3) field name doesn't match type name (alias)
|
||||
name = p.string()
|
||||
alias = true
|
||||
fallthrough
|
||||
default:
|
||||
if !exported(name) {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) paramList() (*types.Tuple, bool) {
|
||||
n := p.int()
|
||||
if n == 0 {
|
||||
return nil, false
|
||||
}
|
||||
// negative length indicates unnamed parameters
|
||||
named := true
|
||||
if n < 0 {
|
||||
n = -n
|
||||
named = false
|
||||
}
|
||||
// n > 0
|
||||
params := make([]*types.Var, n)
|
||||
isddd := false
|
||||
for i := range params {
|
||||
params[i], isddd = p.param(named)
|
||||
}
|
||||
return types.NewTuple(params...), isddd
|
||||
}
|
||||
|
||||
func (p *importer) param(named bool) (*types.Var, bool) {
|
||||
t := p.typ(nil, nil)
|
||||
td, isddd := t.(*dddSlice)
|
||||
if isddd {
|
||||
t = types.NewSlice(td.elem)
|
||||
}
|
||||
|
||||
var pkg *types.Package
|
||||
var name string
|
||||
if named {
|
||||
name = p.string()
|
||||
if name == "" {
|
||||
errorf("expected named parameter")
|
||||
}
|
||||
if name != "_" {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
if i := strings.Index(name, "·"); i > 0 {
|
||||
name = name[:i] // cut off gc-specific parameter numbering
|
||||
}
|
||||
}
|
||||
|
||||
// read and discard compiler-specific info
|
||||
p.string()
|
||||
|
||||
return types.NewVar(token.NoPos, pkg, name, t), isddd
|
||||
}
|
||||
|
||||
func exported(name string) bool {
|
||||
ch, _ := utf8.DecodeRuneInString(name)
|
||||
return unicode.IsUpper(ch)
|
||||
}
|
||||
|
||||
func (p *importer) value() constant.Value {
|
||||
switch tag := p.tagOrIndex(); tag {
|
||||
case falseTag:
|
||||
return constant.MakeBool(false)
|
||||
case trueTag:
|
||||
return constant.MakeBool(true)
|
||||
case int64Tag:
|
||||
return constant.MakeInt64(p.int64())
|
||||
case floatTag:
|
||||
return p.float()
|
||||
case complexTag:
|
||||
re := p.float()
|
||||
im := p.float()
|
||||
return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
|
||||
case stringTag:
|
||||
return constant.MakeString(p.string())
|
||||
case unknownTag:
|
||||
return constant.MakeUnknown()
|
||||
default:
|
||||
errorf("unexpected value tag %d", tag) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) float() constant.Value {
|
||||
sign := p.int()
|
||||
if sign == 0 {
|
||||
return constant.MakeInt64(0)
|
||||
}
|
||||
|
||||
exp := p.int()
|
||||
mant := []byte(p.string()) // big endian
|
||||
|
||||
// remove leading 0's if any
|
||||
for len(mant) > 0 && mant[0] == 0 {
|
||||
mant = mant[1:]
|
||||
}
|
||||
|
||||
// convert to little endian
|
||||
// TODO(gri) go/constant should have a more direct conversion function
|
||||
// (e.g., once it supports a big.Float based implementation)
|
||||
for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
|
||||
mant[i], mant[j] = mant[j], mant[i]
|
||||
}
|
||||
|
||||
// adjust exponent (constant.MakeFromBytes creates an integer value,
|
||||
// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
|
||||
exp -= len(mant) << 3
|
||||
if len(mant) > 0 {
|
||||
for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
|
||||
exp++
|
||||
}
|
||||
}
|
||||
|
||||
x := constant.MakeFromBytes(mant)
|
||||
switch {
|
||||
case exp < 0:
|
||||
d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
|
||||
x = constant.BinaryOp(x, token.QUO, d)
|
||||
case exp > 0:
|
||||
x = constant.Shift(x, token.SHL, uint(exp))
|
||||
}
|
||||
|
||||
if sign < 0 {
|
||||
x = constant.UnaryOp(token.SUB, x, 0)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Low-level decoders
|
||||
|
||||
func (p *importer) tagOrIndex() int {
|
||||
if p.debugFormat {
|
||||
p.marker('t')
|
||||
}
|
||||
|
||||
return int(p.rawInt64())
|
||||
}
|
||||
|
||||
func (p *importer) int() int {
|
||||
x := p.int64()
|
||||
if int64(int(x)) != x {
|
||||
errorf("exported integer too large")
|
||||
}
|
||||
return int(x)
|
||||
}
|
||||
|
||||
func (p *importer) int64() int64 {
|
||||
if p.debugFormat {
|
||||
p.marker('i')
|
||||
}
|
||||
|
||||
return p.rawInt64()
|
||||
}
|
||||
|
||||
func (p *importer) path() string {
|
||||
if p.debugFormat {
|
||||
p.marker('p')
|
||||
}
|
||||
// if the path was seen before, i is its index (>= 0)
|
||||
// (the empty string is at index 0)
|
||||
i := p.rawInt64()
|
||||
if i >= 0 {
|
||||
return p.pathList[i]
|
||||
}
|
||||
// otherwise, i is the negative path length (< 0)
|
||||
a := make([]string, -i)
|
||||
for n := range a {
|
||||
a[n] = p.string()
|
||||
}
|
||||
s := strings.Join(a, "/")
|
||||
p.pathList = append(p.pathList, s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *importer) string() string {
|
||||
if p.debugFormat {
|
||||
p.marker('s')
|
||||
}
|
||||
// if the string was seen before, i is its index (>= 0)
|
||||
// (the empty string is at index 0)
|
||||
i := p.rawInt64()
|
||||
if i >= 0 {
|
||||
return p.strList[i]
|
||||
}
|
||||
// otherwise, i is the negative string length (< 0)
|
||||
if n := int(-i); n <= cap(p.buf) {
|
||||
p.buf = p.buf[:n]
|
||||
} else {
|
||||
p.buf = make([]byte, n)
|
||||
}
|
||||
for i := range p.buf {
|
||||
p.buf[i] = p.rawByte()
|
||||
}
|
||||
s := string(p.buf)
|
||||
p.strList = append(p.strList, s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *importer) marker(want byte) {
|
||||
if got := p.rawByte(); got != want {
|
||||
errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
|
||||
}
|
||||
|
||||
pos := p.read
|
||||
if n := int(p.rawInt64()); n != pos {
|
||||
errorf("incorrect position: got %d; want %d", n, pos)
|
||||
}
|
||||
}
|
||||
|
||||
// rawInt64 should only be used by low-level decoders.
|
||||
func (p *importer) rawInt64() int64 {
|
||||
i, err := binary.ReadVarint(p)
|
||||
if err != nil {
|
||||
errorf("read error: %v", err)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// rawStringln should only be used to read the initial version string.
|
||||
func (p *importer) rawStringln(b byte) string {
|
||||
p.buf = p.buf[:0]
|
||||
for b != '\n' {
|
||||
p.buf = append(p.buf, b)
|
||||
b = p.rawByte()
|
||||
}
|
||||
return string(p.buf)
|
||||
}
|
||||
|
||||
// needed for binary.ReadVarint in rawInt64
|
||||
func (p *importer) ReadByte() (byte, error) {
|
||||
return p.rawByte(), nil
|
||||
}
|
||||
|
||||
// byte is the bottleneck interface for reading p.data.
|
||||
// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
|
||||
// rawByte should only be used by low-level decoders.
|
||||
func (p *importer) rawByte() byte {
|
||||
b := p.data[0]
|
||||
r := 1
|
||||
if b == '|' {
|
||||
b = p.data[1]
|
||||
r = 2
|
||||
switch b {
|
||||
case 'S':
|
||||
b = '$'
|
||||
case '|':
|
||||
// nothing to do
|
||||
default:
|
||||
errorf("unexpected escape sequence in export data")
|
||||
}
|
||||
}
|
||||
p.data = p.data[r:]
|
||||
p.read += r
|
||||
return b
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Export format
|
||||
|
||||
// Tags. Must be < 0.
|
||||
const (
|
||||
// Objects
|
||||
packageTag = -(iota + 1)
|
||||
constTag
|
||||
typeTag
|
||||
varTag
|
||||
funcTag
|
||||
endTag
|
||||
|
||||
// Types
|
||||
namedTag
|
||||
arrayTag
|
||||
sliceTag
|
||||
dddTag
|
||||
structTag
|
||||
pointerTag
|
||||
signatureTag
|
||||
interfaceTag
|
||||
mapTag
|
||||
chanTag
|
||||
|
||||
// Values
|
||||
falseTag
|
||||
trueTag
|
||||
int64Tag
|
||||
floatTag
|
||||
fractionTag // not used by gc
|
||||
complexTag
|
||||
stringTag
|
||||
nilTag // only used by gc (appears in exported inlined function bodies)
|
||||
unknownTag // not used by gc (only appears in packages with errors)
|
||||
|
||||
// Type aliases
|
||||
aliasTag
|
||||
)
|
||||
|
||||
var predeclOnce sync.Once
|
||||
var predecl []types.Type // initialized lazily
|
||||
|
||||
func predeclared() []types.Type {
|
||||
predeclOnce.Do(func() {
|
||||
// initialize lazily to be sure that all
|
||||
// elements have been initialized before
|
||||
predecl = []types.Type{ // basic types
|
||||
types.Typ[types.Bool],
|
||||
types.Typ[types.Int],
|
||||
types.Typ[types.Int8],
|
||||
types.Typ[types.Int16],
|
||||
types.Typ[types.Int32],
|
||||
types.Typ[types.Int64],
|
||||
types.Typ[types.Uint],
|
||||
types.Typ[types.Uint8],
|
||||
types.Typ[types.Uint16],
|
||||
types.Typ[types.Uint32],
|
||||
types.Typ[types.Uint64],
|
||||
types.Typ[types.Uintptr],
|
||||
types.Typ[types.Float32],
|
||||
types.Typ[types.Float64],
|
||||
types.Typ[types.Complex64],
|
||||
types.Typ[types.Complex128],
|
||||
types.Typ[types.String],
|
||||
|
||||
// basic type aliases
|
||||
types.Universe.Lookup("byte").Type(),
|
||||
types.Universe.Lookup("rune").Type(),
|
||||
|
||||
// error
|
||||
types.Universe.Lookup("error").Type(),
|
||||
|
||||
// untyped types
|
||||
types.Typ[types.UntypedBool],
|
||||
types.Typ[types.UntypedInt],
|
||||
types.Typ[types.UntypedRune],
|
||||
types.Typ[types.UntypedFloat],
|
||||
types.Typ[types.UntypedComplex],
|
||||
types.Typ[types.UntypedString],
|
||||
types.Typ[types.UntypedNil],
|
||||
|
||||
// package unsafe
|
||||
types.Typ[types.UnsafePointer],
|
||||
|
||||
// invalid type
|
||||
types.Typ[types.Invalid], // only appears in packages with errors
|
||||
|
||||
// used internally by gc; never used by this package or in .a files
|
||||
anyType{},
|
||||
}
|
||||
predecl = append(predecl, additionalPredeclared()...)
|
||||
})
|
||||
return predecl
|
||||
}
|
||||
|
||||
type anyType struct{}
|
||||
|
||||
func (t anyType) Underlying() types.Type { return t }
|
||||
func (t anyType) String() string { return "any" }
|
||||
|
|
448
vendor/golang.org/x/tools/internal/gcimporter/exportdata.go
generated
vendored
448
vendor/golang.org/x/tools/internal/gcimporter/exportdata.go
generated
vendored
|
@ -2,49 +2,183 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go.
|
||||
|
||||
// This file implements FindExportData.
|
||||
// This file should be kept in sync with $GOROOT/src/internal/exportdata/exportdata.go.
|
||||
// This file also additionally implements FindExportData for gcexportdata.NewReader.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"strconv"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func readGopackHeader(r *bufio.Reader) (name string, size int64, err error) {
|
||||
// See $GOROOT/include/ar.h.
|
||||
hdr := make([]byte, 16+12+6+6+8+10+2)
|
||||
_, err = io.ReadFull(r, hdr)
|
||||
// FindExportData positions the reader r at the beginning of the
|
||||
// export data section of an underlying cmd/compile created archive
|
||||
// file by reading from it. The reader must be positioned at the
|
||||
// start of the file before calling this function.
|
||||
// This returns the length of the export data in bytes.
|
||||
//
|
||||
// This function is needed by [gcexportdata.Read], which must
|
||||
// accept inputs produced by the last two releases of cmd/compile,
|
||||
// plus tip.
|
||||
func FindExportData(r *bufio.Reader) (size int64, err error) {
|
||||
arsize, err := FindPackageDefinition(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// leave for debugging
|
||||
if false {
|
||||
fmt.Printf("header: %s", hdr)
|
||||
}
|
||||
s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
|
||||
length, err := strconv.Atoi(s)
|
||||
size = int64(length)
|
||||
if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
|
||||
err = fmt.Errorf("invalid archive header")
|
||||
size = int64(arsize)
|
||||
|
||||
objapi, headers, err := ReadObjectHeaders(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
name = strings.TrimSpace(string(hdr[:16]))
|
||||
size -= int64(len(objapi))
|
||||
for _, h := range headers {
|
||||
size -= int64(len(h))
|
||||
}
|
||||
|
||||
// Check for the binary export data section header "$$B\n".
|
||||
// TODO(taking): Unify with ReadExportDataHeader so that it stops at the 'u' instead of reading
|
||||
line, err := r.ReadSlice('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
hdr := string(line)
|
||||
if hdr != "$$B\n" {
|
||||
err = fmt.Errorf("unknown export data header: %q", hdr)
|
||||
return
|
||||
}
|
||||
size -= int64(len(hdr))
|
||||
|
||||
// For files with a binary export data header "$$B\n",
|
||||
// these are always terminated by an end-of-section marker "\n$$\n".
|
||||
// So the last bytes must always be this constant.
|
||||
//
|
||||
// The end-of-section marker is not a part of the export data itself.
|
||||
// Do not include these in size.
|
||||
//
|
||||
// It would be nice to have sanity check that the final bytes after
|
||||
// the export data are indeed the end-of-section marker. The split
|
||||
// of gcexportdata.NewReader and gcexportdata.Read make checking this
|
||||
// ugly so gcimporter gives up enforcing this. The compiler and go/types
|
||||
// importer do enforce this, which seems good enough.
|
||||
const endofsection = "\n$$\n"
|
||||
size -= int64(len(endofsection))
|
||||
|
||||
if size < 0 {
|
||||
err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", arsize, size)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindExportData positions the reader r at the beginning of the
|
||||
// export data section of an underlying GC-created object/archive
|
||||
// file by reading from it. The reader must be positioned at the
|
||||
// start of the file before calling this function. The hdr result
|
||||
// is the string before the export data, either "$$" or "$$B".
|
||||
// The size result is the length of the export data in bytes, or -1 if not known.
|
||||
func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) {
|
||||
// ReadUnified reads the contents of the unified export data from a reader r
|
||||
// that contains the contents of a GC-created archive file.
|
||||
//
|
||||
// On success, the reader will be positioned after the end-of-section marker "\n$$\n".
|
||||
//
|
||||
// Supported GC-created archive files have 4 layers of nesting:
|
||||
// - An archive file containing a package definition file.
|
||||
// - The package definition file contains headers followed by a data section.
|
||||
// Headers are lines (≤ 4kb) that do not start with "$$".
|
||||
// - The data section starts with "$$B\n" followed by export data followed
|
||||
// by an end of section marker "\n$$\n". (The section start "$$\n" is no
|
||||
// longer supported.)
|
||||
// - The export data starts with a format byte ('u') followed by the <data> in
|
||||
// the given format. (See ReadExportDataHeader for older formats.)
|
||||
//
|
||||
// Putting this together, the bytes in a GC-created archive files are expected
|
||||
// to look like the following.
|
||||
// See cmd/internal/archive for more details on ar file headers.
|
||||
//
|
||||
// | <!arch>\n | ar file signature
|
||||
// | __.PKGDEF...size...\n | ar header for __.PKGDEF including size.
|
||||
// | go object <...>\n | objabi header
|
||||
// | <optional headers>\n | other headers such as build id
|
||||
// | $$B\n | binary format marker
|
||||
// | u<data>\n | unified export <data>
|
||||
// | $$\n | end-of-section marker
|
||||
// | [optional padding] | padding byte (0x0A) if size is odd
|
||||
// | [ar file header] | other ar files
|
||||
// | [ar file data] |
|
||||
func ReadUnified(r *bufio.Reader) (data []byte, err error) {
|
||||
// We historically guaranteed headers at the default buffer size (4096) work.
|
||||
// This ensures we can use ReadSlice throughout.
|
||||
const minBufferSize = 4096
|
||||
r = bufio.NewReaderSize(r, minBufferSize)
|
||||
|
||||
size, err := FindPackageDefinition(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n := size
|
||||
|
||||
objapi, headers, err := ReadObjectHeaders(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n -= len(objapi)
|
||||
for _, h := range headers {
|
||||
n -= len(h)
|
||||
}
|
||||
|
||||
hdrlen, err := ReadExportDataHeader(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n -= hdrlen
|
||||
|
||||
// size also includes the end of section marker. Remove that many bytes from the end.
|
||||
const marker = "\n$$\n"
|
||||
n -= len(marker)
|
||||
|
||||
if n < 0 {
|
||||
err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", size, n)
|
||||
return
|
||||
}
|
||||
|
||||
// Read n bytes from buf.
|
||||
data = make([]byte, n)
|
||||
_, err = io.ReadFull(r, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check for marker at the end.
|
||||
var suffix [len(marker)]byte
|
||||
_, err = io.ReadFull(r, suffix[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if s := string(suffix[:]); s != marker {
|
||||
err = fmt.Errorf("read %q instead of end-of-section marker (%q)", s, marker)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindPackageDefinition positions the reader r at the beginning of a package
|
||||
// definition file ("__.PKGDEF") within a GC-created archive by reading
|
||||
// from it, and returns the size of the package definition file in the archive.
|
||||
//
|
||||
// The reader must be positioned at the start of the archive file before calling
|
||||
// this function, and "__.PKGDEF" is assumed to be the first file in the archive.
|
||||
//
|
||||
// See cmd/internal/archive for details on the archive format.
|
||||
func FindPackageDefinition(r *bufio.Reader) (size int, err error) {
|
||||
// Uses ReadSlice to limit risk of malformed inputs.
|
||||
|
||||
// Read first line to make sure this is an object file.
|
||||
line, err := r.ReadSlice('\n')
|
||||
if err != nil {
|
||||
|
@ -52,48 +186,236 @@ func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
if string(line) == "!<arch>\n" {
|
||||
// Archive file. Scan to __.PKGDEF.
|
||||
var name string
|
||||
if name, size, err = readGopackHeader(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// First entry should be __.PKGDEF.
|
||||
if name != "__.PKGDEF" {
|
||||
err = fmt.Errorf("go archive is missing __.PKGDEF")
|
||||
return
|
||||
}
|
||||
|
||||
// Read first line of __.PKGDEF data, so that line
|
||||
// is once again the first line of the input.
|
||||
if line, err = r.ReadSlice('\n'); err != nil {
|
||||
err = fmt.Errorf("can't find export data (%v)", err)
|
||||
return
|
||||
}
|
||||
size -= int64(len(line))
|
||||
}
|
||||
|
||||
// Now at __.PKGDEF in archive or still at beginning of file.
|
||||
// Either way, line should begin with "go object ".
|
||||
if !strings.HasPrefix(string(line), "go object ") {
|
||||
err = fmt.Errorf("not a Go object file")
|
||||
// Is the first line an archive file signature?
|
||||
if string(line) != "!<arch>\n" {
|
||||
err = fmt.Errorf("not the start of an archive file (%q)", line)
|
||||
return
|
||||
}
|
||||
|
||||
// Skip over object header to export data.
|
||||
// Begins after first line starting with $$.
|
||||
for line[0] != '$' {
|
||||
if line, err = r.ReadSlice('\n'); err != nil {
|
||||
err = fmt.Errorf("can't find export data (%v)", err)
|
||||
return
|
||||
}
|
||||
size -= int64(len(line))
|
||||
}
|
||||
hdr = string(line)
|
||||
if size < 0 {
|
||||
size = -1
|
||||
// package export block should be first
|
||||
size = readArchiveHeader(r, "__.PKGDEF")
|
||||
if size <= 0 {
|
||||
err = fmt.Errorf("not a package file")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ReadObjectHeaders reads object headers from the reader. Object headers are
|
||||
// lines that do not start with an end-of-section marker "$$". The first header
|
||||
// is the objabi header. On success, the reader will be positioned at the beginning
|
||||
// of the end-of-section marker.
|
||||
//
|
||||
// It returns an error if any header does not fit in r.Size() bytes.
|
||||
func ReadObjectHeaders(r *bufio.Reader) (objapi string, headers []string, err error) {
|
||||
// line is a temporary buffer for headers.
|
||||
// Use bounded reads (ReadSlice, Peek) to limit risk of malformed inputs.
|
||||
var line []byte
|
||||
|
||||
// objapi header should be the first line
|
||||
if line, err = r.ReadSlice('\n'); err != nil {
|
||||
err = fmt.Errorf("can't find export data (%v)", err)
|
||||
return
|
||||
}
|
||||
objapi = string(line)
|
||||
|
||||
// objapi header begins with "go object ".
|
||||
if !strings.HasPrefix(objapi, "go object ") {
|
||||
err = fmt.Errorf("not a go object file: %s", objapi)
|
||||
return
|
||||
}
|
||||
|
||||
// process remaining object header lines
|
||||
for {
|
||||
// check for an end of section marker "$$"
|
||||
line, err = r.Peek(2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if string(line) == "$$" {
|
||||
return // stop
|
||||
}
|
||||
|
||||
// read next header
|
||||
line, err = r.ReadSlice('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
headers = append(headers, string(line))
|
||||
}
|
||||
}
|
||||
|
||||
// ReadExportDataHeader reads the export data header and format from r.
|
||||
// It returns the number of bytes read, or an error if the format is no longer
|
||||
// supported or it failed to read.
|
||||
//
|
||||
// The only currently supported format is binary export data in the
|
||||
// unified export format.
|
||||
func ReadExportDataHeader(r *bufio.Reader) (n int, err error) {
|
||||
// Read export data header.
|
||||
line, err := r.ReadSlice('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
hdr := string(line)
|
||||
switch hdr {
|
||||
case "$$\n":
|
||||
err = fmt.Errorf("old textual export format no longer supported (recompile package)")
|
||||
return
|
||||
|
||||
case "$$B\n":
|
||||
var format byte
|
||||
format, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// The unified export format starts with a 'u'.
|
||||
switch format {
|
||||
case 'u':
|
||||
default:
|
||||
// Older no longer supported export formats include:
|
||||
// indexed export format which started with an 'i'; and
|
||||
// the older binary export format which started with a 'c',
|
||||
// 'd', or 'v' (from "version").
|
||||
err = fmt.Errorf("binary export format %q is no longer supported (recompile package)", format)
|
||||
return
|
||||
}
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unknown export data header: %q", hdr)
|
||||
return
|
||||
}
|
||||
|
||||
n = len(hdr) + 1 // + 1 is for 'u'
|
||||
return
|
||||
}
|
||||
|
||||
// FindPkg returns the filename and unique package id for an import
|
||||
// path based on package information provided by build.Import (using
|
||||
// the build.Default build.Context). A relative srcDir is interpreted
|
||||
// relative to the current working directory.
|
||||
//
|
||||
// FindPkg is only used in tests within x/tools.
|
||||
func FindPkg(path, srcDir string) (filename, id string, err error) {
|
||||
// TODO(taking): Move internal/exportdata.FindPkg into its own file,
|
||||
// and then this copy into a _test package.
|
||||
if path == "" {
|
||||
return "", "", errors.New("path is empty")
|
||||
}
|
||||
|
||||
var noext string
|
||||
switch {
|
||||
default:
|
||||
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
|
||||
// Don't require the source files to be present.
|
||||
if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282
|
||||
srcDir = abs
|
||||
}
|
||||
var bp *build.Package
|
||||
bp, err = build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
|
||||
if bp.PkgObj == "" {
|
||||
if bp.Goroot && bp.Dir != "" {
|
||||
filename, err = lookupGorootExport(bp.Dir)
|
||||
if err == nil {
|
||||
_, err = os.Stat(filename)
|
||||
}
|
||||
if err == nil {
|
||||
return filename, bp.ImportPath, nil
|
||||
}
|
||||
}
|
||||
goto notfound
|
||||
} else {
|
||||
noext = strings.TrimSuffix(bp.PkgObj, ".a")
|
||||
}
|
||||
id = bp.ImportPath
|
||||
|
||||
case build.IsLocalImport(path):
|
||||
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
|
||||
noext = filepath.Join(srcDir, path)
|
||||
id = noext
|
||||
|
||||
case filepath.IsAbs(path):
|
||||
// for completeness only - go/build.Import
|
||||
// does not support absolute imports
|
||||
// "/x" -> "/x.ext", "/x"
|
||||
noext = path
|
||||
id = path
|
||||
}
|
||||
|
||||
if false { // for debugging
|
||||
if path != id {
|
||||
fmt.Printf("%s -> %s\n", path, id)
|
||||
}
|
||||
}
|
||||
|
||||
// try extensions
|
||||
for _, ext := range pkgExts {
|
||||
filename = noext + ext
|
||||
f, statErr := os.Stat(filename)
|
||||
if statErr == nil && !f.IsDir() {
|
||||
return filename, id, nil
|
||||
}
|
||||
if err == nil {
|
||||
err = statErr
|
||||
}
|
||||
}
|
||||
|
||||
notfound:
|
||||
if err == nil {
|
||||
return "", path, fmt.Errorf("can't find import: %q", path)
|
||||
}
|
||||
return "", path, fmt.Errorf("can't find import: %q: %w", path, err)
|
||||
}
|
||||
|
||||
var pkgExts = [...]string{".a", ".o"} // a file from the build cache will have no extension
|
||||
|
||||
var exportMap sync.Map // package dir → func() (string, error)
|
||||
|
||||
// lookupGorootExport returns the location of the export data
|
||||
// (normally found in the build cache, but located in GOROOT/pkg
|
||||
// in prior Go releases) for the package located in pkgDir.
|
||||
//
|
||||
// (We use the package's directory instead of its import path
|
||||
// mainly to simplify handling of the packages in src/vendor
|
||||
// and cmd/vendor.)
|
||||
//
|
||||
// lookupGorootExport is only used in tests within x/tools.
|
||||
func lookupGorootExport(pkgDir string) (string, error) {
|
||||
f, ok := exportMap.Load(pkgDir)
|
||||
if !ok {
|
||||
var (
|
||||
listOnce sync.Once
|
||||
exportPath string
|
||||
err error
|
||||
)
|
||||
f, _ = exportMap.LoadOrStore(pkgDir, func() (string, error) {
|
||||
listOnce.Do(func() {
|
||||
cmd := exec.Command(filepath.Join(build.Default.GOROOT, "bin", "go"), "list", "-export", "-f", "{{.Export}}", pkgDir)
|
||||
cmd.Dir = build.Default.GOROOT
|
||||
cmd.Env = append(os.Environ(), "PWD="+cmd.Dir, "GOROOT="+build.Default.GOROOT)
|
||||
var output []byte
|
||||
output, err = cmd.Output()
|
||||
if err != nil {
|
||||
if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
|
||||
err = errors.New(string(ee.Stderr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
exports := strings.Split(string(bytes.TrimSpace(output)), "\n")
|
||||
if len(exports) != 1 {
|
||||
err = fmt.Errorf("go list reported %d exports; expected 1", len(exports))
|
||||
return
|
||||
}
|
||||
|
||||
exportPath = exports[0]
|
||||
})
|
||||
|
||||
return exportPath, err
|
||||
})
|
||||
}
|
||||
|
||||
return f.(func() (string, error))()
|
||||
}
|
||||
|
|
1102
vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
generated
vendored
1102
vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
generated
vendored
File diff suppressed because it is too large
Load diff
654
vendor/golang.org/x/tools/internal/gcimporter/iexport.go
generated
vendored
654
vendor/golang.org/x/tools/internal/gcimporter/iexport.go
generated
vendored
|
@ -2,9 +2,227 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Indexed binary package export.
|
||||
// This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go;
|
||||
// see that file for specification of the format.
|
||||
// Indexed package export.
|
||||
//
|
||||
// The indexed export data format is an evolution of the previous
|
||||
// binary export data format. Its chief contribution is introducing an
|
||||
// index table, which allows efficient random access of individual
|
||||
// declarations and inline function bodies. In turn, this allows
|
||||
// avoiding unnecessary work for compilation units that import large
|
||||
// packages.
|
||||
//
|
||||
//
|
||||
// The top-level data format is structured as:
|
||||
//
|
||||
// Header struct {
|
||||
// Tag byte // 'i'
|
||||
// Version uvarint
|
||||
// StringSize uvarint
|
||||
// DataSize uvarint
|
||||
// }
|
||||
//
|
||||
// Strings [StringSize]byte
|
||||
// Data [DataSize]byte
|
||||
//
|
||||
// MainIndex []struct{
|
||||
// PkgPath stringOff
|
||||
// PkgName stringOff
|
||||
// PkgHeight uvarint
|
||||
//
|
||||
// Decls []struct{
|
||||
// Name stringOff
|
||||
// Offset declOff
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Fingerprint [8]byte
|
||||
//
|
||||
// uvarint means a uint64 written out using uvarint encoding.
|
||||
//
|
||||
// []T means a uvarint followed by that many T objects. In other
|
||||
// words:
|
||||
//
|
||||
// Len uvarint
|
||||
// Elems [Len]T
|
||||
//
|
||||
// stringOff means a uvarint that indicates an offset within the
|
||||
// Strings section. At that offset is another uvarint, followed by
|
||||
// that many bytes, which form the string value.
|
||||
//
|
||||
// declOff means a uvarint that indicates an offset within the Data
|
||||
// section where the associated declaration can be found.
|
||||
//
|
||||
//
|
||||
// There are five kinds of declarations, distinguished by their first
|
||||
// byte:
|
||||
//
|
||||
// type Var struct {
|
||||
// Tag byte // 'V'
|
||||
// Pos Pos
|
||||
// Type typeOff
|
||||
// }
|
||||
//
|
||||
// type Func struct {
|
||||
// Tag byte // 'F' or 'G'
|
||||
// Pos Pos
|
||||
// TypeParams []typeOff // only present if Tag == 'G'
|
||||
// Signature Signature
|
||||
// }
|
||||
//
|
||||
// type Const struct {
|
||||
// Tag byte // 'C'
|
||||
// Pos Pos
|
||||
// Value Value
|
||||
// }
|
||||
//
|
||||
// type Type struct {
|
||||
// Tag byte // 'T' or 'U'
|
||||
// Pos Pos
|
||||
// TypeParams []typeOff // only present if Tag == 'U'
|
||||
// Underlying typeOff
|
||||
//
|
||||
// Methods []struct{ // omitted if Underlying is an interface type
|
||||
// Pos Pos
|
||||
// Name stringOff
|
||||
// Recv Param
|
||||
// Signature Signature
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// type Alias struct {
|
||||
// Tag byte // 'A' or 'B'
|
||||
// Pos Pos
|
||||
// TypeParams []typeOff // only present if Tag == 'B'
|
||||
// Type typeOff
|
||||
// }
|
||||
//
|
||||
// // "Automatic" declaration of each typeparam
|
||||
// type TypeParam struct {
|
||||
// Tag byte // 'P'
|
||||
// Pos Pos
|
||||
// Implicit bool
|
||||
// Constraint typeOff
|
||||
// }
|
||||
//
|
||||
// typeOff means a uvarint that either indicates a predeclared type,
|
||||
// or an offset into the Data section. If the uvarint is less than
|
||||
// predeclReserved, then it indicates the index into the predeclared
|
||||
// types list (see predeclared in bexport.go for order). Otherwise,
|
||||
// subtracting predeclReserved yields the offset of a type descriptor.
|
||||
//
|
||||
// Value means a type, kind, and type-specific value. See
|
||||
// (*exportWriter).value for details.
|
||||
//
|
||||
//
|
||||
// There are twelve kinds of type descriptors, distinguished by an itag:
|
||||
//
|
||||
// type DefinedType struct {
|
||||
// Tag itag // definedType
|
||||
// Name stringOff
|
||||
// PkgPath stringOff
|
||||
// }
|
||||
//
|
||||
// type PointerType struct {
|
||||
// Tag itag // pointerType
|
||||
// Elem typeOff
|
||||
// }
|
||||
//
|
||||
// type SliceType struct {
|
||||
// Tag itag // sliceType
|
||||
// Elem typeOff
|
||||
// }
|
||||
//
|
||||
// type ArrayType struct {
|
||||
// Tag itag // arrayType
|
||||
// Len uint64
|
||||
// Elem typeOff
|
||||
// }
|
||||
//
|
||||
// type ChanType struct {
|
||||
// Tag itag // chanType
|
||||
// Dir uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv
|
||||
// Elem typeOff
|
||||
// }
|
||||
//
|
||||
// type MapType struct {
|
||||
// Tag itag // mapType
|
||||
// Key typeOff
|
||||
// Elem typeOff
|
||||
// }
|
||||
//
|
||||
// type FuncType struct {
|
||||
// Tag itag // signatureType
|
||||
// PkgPath stringOff
|
||||
// Signature Signature
|
||||
// }
|
||||
//
|
||||
// type StructType struct {
|
||||
// Tag itag // structType
|
||||
// PkgPath stringOff
|
||||
// Fields []struct {
|
||||
// Pos Pos
|
||||
// Name stringOff
|
||||
// Type typeOff
|
||||
// Embedded bool
|
||||
// Note stringOff
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// type InterfaceType struct {
|
||||
// Tag itag // interfaceType
|
||||
// PkgPath stringOff
|
||||
// Embeddeds []struct {
|
||||
// Pos Pos
|
||||
// Type typeOff
|
||||
// }
|
||||
// Methods []struct {
|
||||
// Pos Pos
|
||||
// Name stringOff
|
||||
// Signature Signature
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Reference to a type param declaration
|
||||
// type TypeParamType struct {
|
||||
// Tag itag // typeParamType
|
||||
// Name stringOff
|
||||
// PkgPath stringOff
|
||||
// }
|
||||
//
|
||||
// // Instantiation of a generic type (like List[T2] or List[int])
|
||||
// type InstanceType struct {
|
||||
// Tag itag // instanceType
|
||||
// Pos pos
|
||||
// TypeArgs []typeOff
|
||||
// BaseType typeOff
|
||||
// }
|
||||
//
|
||||
// type UnionType struct {
|
||||
// Tag itag // interfaceType
|
||||
// Terms []struct {
|
||||
// tilde bool
|
||||
// Type typeOff
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// type Signature struct {
|
||||
// Params []Param
|
||||
// Results []Param
|
||||
// Variadic bool // omitted if Results is empty
|
||||
// }
|
||||
//
|
||||
// type Param struct {
|
||||
// Pos Pos
|
||||
// Name stringOff
|
||||
// Type typOff
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Pos encodes a file:line:column triple, incorporating a simple delta
|
||||
// encoding scheme within a data object. See exportWriter.pos for
|
||||
// details.
|
||||
|
||||
package gcimporter
|
||||
|
||||
|
@ -22,16 +240,42 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/internal/typeparams"
|
||||
"golang.org/x/tools/go/types/objectpath"
|
||||
"golang.org/x/tools/internal/aliases"
|
||||
)
|
||||
|
||||
// IExportShallow encodes "shallow" export data for the specified package.
|
||||
//
|
||||
// No promises are made about the encoding other than that it can be
|
||||
// decoded by the same version of IIExportShallow. If you plan to save
|
||||
// export data in the file system, be sure to include a cryptographic
|
||||
// digest of the executable in the key to avoid version skew.
|
||||
func IExportShallow(fset *token.FileSet, pkg *types.Package) ([]byte, error) {
|
||||
// For types, we use "shallow" export data. Historically, the Go
|
||||
// compiler always produced a summary of the types for a given package
|
||||
// that included types from other packages that it indirectly
|
||||
// referenced: "deep" export data. This had the advantage that the
|
||||
// compiler (and analogous tools such as gopls) need only load one
|
||||
// file per direct import. However, it meant that the files tended to
|
||||
// get larger based on the level of the package in the import
|
||||
// graph. For example, higher-level packages in the kubernetes module
|
||||
// have over 1MB of "deep" export data, even when they have almost no
|
||||
// content of their own, merely because they mention a major type that
|
||||
// references many others. In pathological cases the export data was
|
||||
// 300x larger than the source for a package due to this quadratic
|
||||
// growth.
|
||||
//
|
||||
// "Shallow" export data means that the serialized types describe only
|
||||
// a single package. If those types mention types from other packages,
|
||||
// the type checker may need to request additional packages beyond
|
||||
// just the direct imports. Type information for the entire transitive
|
||||
// closure of imports is provided (lazily) by the DAG.
|
||||
//
|
||||
// No promises are made about the encoding other than that it can be decoded by
|
||||
// the same version of IIExportShallow. If you plan to save export data in the
|
||||
// file system, be sure to include a cryptographic digest of the executable in
|
||||
// the key to avoid version skew.
|
||||
//
|
||||
// If the provided reportf func is non-nil, it will be used for reporting bugs
|
||||
// encountered during export.
|
||||
// TODO(rfindley): remove reportf when we are confident enough in the new
|
||||
// objectpath encoding.
|
||||
func IExportShallow(fset *token.FileSet, pkg *types.Package, reportf ReportFunc) ([]byte, error) {
|
||||
// In principle this operation can only fail if out.Write fails,
|
||||
// but that's impossible for bytes.Buffer---and as a matter of
|
||||
// fact iexportCommon doesn't even check for I/O errors.
|
||||
|
@ -43,22 +287,30 @@ func IExportShallow(fset *token.FileSet, pkg *types.Package) ([]byte, error) {
|
|||
return out.Bytes(), err
|
||||
}
|
||||
|
||||
// IImportShallow decodes "shallow" types.Package data encoded by IExportShallow
|
||||
// in the same executable. This function cannot import data from
|
||||
// cmd/compile or gcexportdata.Write.
|
||||
func IImportShallow(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string, insert InsertType) (*types.Package, error) {
|
||||
// IImportShallow decodes "shallow" types.Package data encoded by
|
||||
// [IExportShallow] in the same executable. This function cannot import data
|
||||
// from cmd/compile or gcexportdata.Write.
|
||||
//
|
||||
// The importer calls getPackages to obtain package symbols for all
|
||||
// packages mentioned in the export data, including the one being
|
||||
// decoded.
|
||||
//
|
||||
// If the provided reportf func is non-nil, it will be used for reporting bugs
|
||||
// encountered during import.
|
||||
// TODO(rfindley): remove reportf when we are confident enough in the new
|
||||
// objectpath encoding.
|
||||
func IImportShallow(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, path string, reportf ReportFunc) (*types.Package, error) {
|
||||
const bundle = false
|
||||
pkgs, err := iimportCommon(fset, imports, data, bundle, path, insert)
|
||||
const shallow = true
|
||||
pkgs, err := iimportCommon(fset, getPackages, data, bundle, path, shallow, reportf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pkgs[0], nil
|
||||
}
|
||||
|
||||
// InsertType is the type of a function that creates a types.TypeName
|
||||
// object for a named type and inserts it into the scope of the
|
||||
// specified Package.
|
||||
type InsertType = func(pkg *types.Package, name string)
|
||||
// ReportFunc is the type of a function used to report formatted bugs.
|
||||
type ReportFunc = func(string, ...interface{})
|
||||
|
||||
// Current bundled export format version. Increase with each format change.
|
||||
// 0: initial implementation
|
||||
|
@ -138,6 +390,17 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle, shallow bool, ver
|
|||
p.doDecl(p.declTodo.popHead())
|
||||
}
|
||||
|
||||
// Produce index of offset of each file record in files.
|
||||
var files intWriter
|
||||
var fileOffset []uint64 // fileOffset[i] is offset in files of file encoded as i
|
||||
if p.shallow {
|
||||
fileOffset = make([]uint64, len(p.fileInfos))
|
||||
for i, info := range p.fileInfos {
|
||||
fileOffset[i] = uint64(files.Len())
|
||||
p.encodeFile(&files, info.file, info.needed)
|
||||
}
|
||||
}
|
||||
|
||||
// Append indices to data0 section.
|
||||
dataLen := uint64(p.data0.Len())
|
||||
w := p.newWriter()
|
||||
|
@ -163,16 +426,75 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle, shallow bool, ver
|
|||
}
|
||||
hdr.uint64(uint64(p.version))
|
||||
hdr.uint64(uint64(p.strings.Len()))
|
||||
if p.shallow {
|
||||
hdr.uint64(uint64(files.Len()))
|
||||
hdr.uint64(uint64(len(fileOffset)))
|
||||
for _, offset := range fileOffset {
|
||||
hdr.uint64(offset)
|
||||
}
|
||||
}
|
||||
hdr.uint64(dataLen)
|
||||
|
||||
// Flush output.
|
||||
io.Copy(out, &hdr)
|
||||
io.Copy(out, &p.strings)
|
||||
if p.shallow {
|
||||
io.Copy(out, &files)
|
||||
}
|
||||
io.Copy(out, &p.data0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodeFile writes to w a representation of the file sufficient to
|
||||
// faithfully restore position information about all needed offsets.
|
||||
// Mutates the needed array.
|
||||
func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64) {
|
||||
_ = needed[0] // precondition: needed is non-empty
|
||||
|
||||
w.uint64(p.stringOff(file.Name()))
|
||||
|
||||
size := uint64(file.Size())
|
||||
w.uint64(size)
|
||||
|
||||
// Sort the set of needed offsets. Duplicates are harmless.
|
||||
sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
|
||||
|
||||
lines := file.Lines() // byte offset of each line start
|
||||
w.uint64(uint64(len(lines)))
|
||||
|
||||
// Rather than record the entire array of line start offsets,
|
||||
// we save only a sparse list of (index, offset) pairs for
|
||||
// the start of each line that contains a needed position.
|
||||
var sparse [][2]int // (index, offset) pairs
|
||||
outer:
|
||||
for i, lineStart := range lines {
|
||||
lineEnd := size
|
||||
if i < len(lines)-1 {
|
||||
lineEnd = uint64(lines[i+1])
|
||||
}
|
||||
// Does this line contains a needed offset?
|
||||
if needed[0] < lineEnd {
|
||||
sparse = append(sparse, [2]int{i, lineStart})
|
||||
for needed[0] < lineEnd {
|
||||
needed = needed[1:]
|
||||
if len(needed) == 0 {
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delta-encode the columns.
|
||||
w.uint64(uint64(len(sparse)))
|
||||
var prev [2]int
|
||||
for _, pair := range sparse {
|
||||
w.uint64(uint64(pair[0] - prev[0]))
|
||||
w.uint64(uint64(pair[1] - prev[1]))
|
||||
prev = pair
|
||||
}
|
||||
}
|
||||
|
||||
// writeIndex writes out an object index. mainIndex indicates whether
|
||||
// we're writing out the main index, which is also read by
|
||||
// non-compiler tools and includes a complete package description
|
||||
|
@ -242,8 +564,9 @@ type iexporter struct {
|
|||
out *bytes.Buffer
|
||||
version int
|
||||
|
||||
shallow bool // don't put types from other packages in the index
|
||||
localpkg *types.Package // (nil in bundle mode)
|
||||
shallow bool // don't put types from other packages in the index
|
||||
objEncoder *objectpath.Encoder // encodes objects from other packages in shallow mode; lazily allocated
|
||||
localpkg *types.Package // (nil in bundle mode)
|
||||
|
||||
// allPkgs tracks all packages that have been referenced by
|
||||
// the export data, so we can ensure to include them in the
|
||||
|
@ -255,6 +578,12 @@ type iexporter struct {
|
|||
strings intWriter
|
||||
stringIndex map[string]uint64
|
||||
|
||||
// In shallow mode, object positions are encoded as (file, offset).
|
||||
// Each file is recorded as a line-number table.
|
||||
// Only the lines of needed positions are saved faithfully.
|
||||
fileInfo map[*token.File]uint64 // value is index in fileInfos
|
||||
fileInfos []*filePositions
|
||||
|
||||
data0 intWriter
|
||||
declIndex map[types.Object]uint64
|
||||
tparamNames map[types.Object]string // typeparam->exported name
|
||||
|
@ -263,6 +592,11 @@ type iexporter struct {
|
|||
indent int // for tracing support
|
||||
}
|
||||
|
||||
type filePositions struct {
|
||||
file *token.File
|
||||
needed []uint64 // unordered list of needed file offsets
|
||||
}
|
||||
|
||||
func (p *iexporter) trace(format string, args ...interface{}) {
|
||||
if !trace {
|
||||
// Call sites should also be guarded, but having this check here allows
|
||||
|
@ -272,6 +606,17 @@ func (p *iexporter) trace(format string, args ...interface{}) {
|
|||
fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
|
||||
}
|
||||
|
||||
// objectpathEncoder returns the lazily allocated objectpath.Encoder to use
|
||||
// when encoding objects in other packages during shallow export.
|
||||
//
|
||||
// Using a shared Encoder amortizes some of cost of objectpath search.
|
||||
func (p *iexporter) objectpathEncoder() *objectpath.Encoder {
|
||||
if p.objEncoder == nil {
|
||||
p.objEncoder = new(objectpath.Encoder)
|
||||
}
|
||||
return p.objEncoder
|
||||
}
|
||||
|
||||
// stringOff returns the offset of s within the string section.
|
||||
// If not already present, it's added to the end.
|
||||
func (p *iexporter) stringOff(s string) uint64 {
|
||||
|
@ -286,6 +631,25 @@ func (p *iexporter) stringOff(s string) uint64 {
|
|||
return off
|
||||
}
|
||||
|
||||
// fileIndexAndOffset returns the index of the token.File and the byte offset of pos within it.
|
||||
func (p *iexporter) fileIndexAndOffset(file *token.File, pos token.Pos) (uint64, uint64) {
|
||||
index, ok := p.fileInfo[file]
|
||||
if !ok {
|
||||
index = uint64(len(p.fileInfo))
|
||||
p.fileInfos = append(p.fileInfos, &filePositions{file: file})
|
||||
if p.fileInfo == nil {
|
||||
p.fileInfo = make(map[*token.File]uint64)
|
||||
}
|
||||
p.fileInfo[file] = index
|
||||
}
|
||||
// Record each needed offset.
|
||||
info := p.fileInfos[index]
|
||||
offset := uint64(file.Offset(pos))
|
||||
info.needed = append(info.needed, offset)
|
||||
|
||||
return index, offset
|
||||
}
|
||||
|
||||
// pushDecl adds n to the declaration work queue, if not already present.
|
||||
func (p *iexporter) pushDecl(obj types.Object) {
|
||||
// Package unsafe is known to the compiler and predeclared.
|
||||
|
@ -312,7 +676,6 @@ type exportWriter struct {
|
|||
p *iexporter
|
||||
|
||||
data intWriter
|
||||
currPkg *types.Package
|
||||
prevFile string
|
||||
prevLine int64
|
||||
prevColumn int64
|
||||
|
@ -335,25 +698,30 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||
}()
|
||||
}
|
||||
w := p.newWriter()
|
||||
w.setPkg(obj.Pkg(), false)
|
||||
|
||||
switch obj := obj.(type) {
|
||||
case *types.Var:
|
||||
w.tag('V')
|
||||
w.tag(varTag)
|
||||
w.pos(obj.Pos())
|
||||
w.typ(obj.Type(), obj.Pkg())
|
||||
|
||||
case *types.Func:
|
||||
sig, _ := obj.Type().(*types.Signature)
|
||||
if sig.Recv() != nil {
|
||||
panic(internalErrorf("unexpected method: %v", sig))
|
||||
// We shouldn't see methods in the package scope,
|
||||
// but the type checker may repair "func () F() {}"
|
||||
// to "func (Invalid) F()" and then treat it like "func F()",
|
||||
// so allow that. See golang/go#57729.
|
||||
if sig.Recv().Type() != types.Typ[types.Invalid] {
|
||||
panic(internalErrorf("unexpected method: %v", sig))
|
||||
}
|
||||
}
|
||||
|
||||
// Function.
|
||||
if typeparams.ForSignature(sig).Len() == 0 {
|
||||
w.tag('F')
|
||||
if sig.TypeParams().Len() == 0 {
|
||||
w.tag(funcTag)
|
||||
} else {
|
||||
w.tag('G')
|
||||
w.tag(genericFuncTag)
|
||||
}
|
||||
w.pos(obj.Pos())
|
||||
// The tparam list of the function type is the declaration of the type
|
||||
|
@ -363,27 +731,27 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||
//
|
||||
// While importing the type parameters, tparamList computes and records
|
||||
// their export name, so that it can be later used when writing the index.
|
||||
if tparams := typeparams.ForSignature(sig); tparams.Len() > 0 {
|
||||
if tparams := sig.TypeParams(); tparams.Len() > 0 {
|
||||
w.tparamList(obj.Name(), tparams, obj.Pkg())
|
||||
}
|
||||
w.signature(sig)
|
||||
|
||||
case *types.Const:
|
||||
w.tag('C')
|
||||
w.tag(constTag)
|
||||
w.pos(obj.Pos())
|
||||
w.value(obj.Type(), obj.Val())
|
||||
|
||||
case *types.TypeName:
|
||||
t := obj.Type()
|
||||
|
||||
if tparam, ok := t.(*typeparams.TypeParam); ok {
|
||||
w.tag('P')
|
||||
if tparam, ok := types.Unalias(t).(*types.TypeParam); ok {
|
||||
w.tag(typeParamTag)
|
||||
w.pos(obj.Pos())
|
||||
constraint := tparam.Constraint()
|
||||
if p.version >= iexportVersionGo1_18 {
|
||||
implicit := false
|
||||
if iface, _ := constraint.(*types.Interface); iface != nil {
|
||||
implicit = typeparams.IsImplicit(iface)
|
||||
if iface, _ := types.Unalias(constraint).(*types.Interface); iface != nil {
|
||||
implicit = iface.IsImplicit()
|
||||
}
|
||||
w.bool(implicit)
|
||||
}
|
||||
|
@ -392,8 +760,26 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||
}
|
||||
|
||||
if obj.IsAlias() {
|
||||
w.tag('A')
|
||||
alias, materialized := t.(*types.Alias) // may fail when aliases are not enabled
|
||||
|
||||
var tparams *types.TypeParamList
|
||||
if materialized {
|
||||
tparams = aliases.TypeParams(alias)
|
||||
}
|
||||
if tparams.Len() == 0 {
|
||||
w.tag(aliasTag)
|
||||
} else {
|
||||
w.tag(genericAliasTag)
|
||||
}
|
||||
w.pos(obj.Pos())
|
||||
if tparams.Len() > 0 {
|
||||
w.tparamList(obj.Name(), tparams, obj.Pkg())
|
||||
}
|
||||
if materialized {
|
||||
// Preserve materialized aliases,
|
||||
// even of non-exported types.
|
||||
t = aliases.Rhs(alias)
|
||||
}
|
||||
w.typ(t, obj.Pkg())
|
||||
break
|
||||
}
|
||||
|
@ -404,20 +790,20 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||
panic(internalErrorf("%s is not a defined type", t))
|
||||
}
|
||||
|
||||
if typeparams.ForNamed(named).Len() == 0 {
|
||||
w.tag('T')
|
||||
if named.TypeParams().Len() == 0 {
|
||||
w.tag(typeTag)
|
||||
} else {
|
||||
w.tag('U')
|
||||
w.tag(genericTypeTag)
|
||||
}
|
||||
w.pos(obj.Pos())
|
||||
|
||||
if typeparams.ForNamed(named).Len() > 0 {
|
||||
if named.TypeParams().Len() > 0 {
|
||||
// While importing the type parameters, tparamList computes and records
|
||||
// their export name, so that it can be later used when writing the index.
|
||||
w.tparamList(obj.Name(), typeparams.ForNamed(named), obj.Pkg())
|
||||
w.tparamList(obj.Name(), named.TypeParams(), obj.Pkg())
|
||||
}
|
||||
|
||||
underlying := obj.Type().Underlying()
|
||||
underlying := named.Underlying()
|
||||
w.typ(underlying, obj.Pkg())
|
||||
|
||||
if types.IsInterface(t) {
|
||||
|
@ -434,7 +820,7 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||
|
||||
// Receiver type parameters are type arguments of the receiver type, so
|
||||
// their name must be qualified before exporting recv.
|
||||
if rparams := typeparams.RecvTypeParams(sig); rparams.Len() > 0 {
|
||||
if rparams := sig.RecvTypeParams(); rparams.Len() > 0 {
|
||||
prefix := obj.Name() + "." + m.Name()
|
||||
for i := 0; i < rparams.Len(); i++ {
|
||||
rparam := rparams.At(i)
|
||||
|
@ -458,13 +844,30 @@ func (w *exportWriter) tag(tag byte) {
|
|||
}
|
||||
|
||||
func (w *exportWriter) pos(pos token.Pos) {
|
||||
if w.p.version >= iexportVersionPosCol {
|
||||
if w.p.shallow {
|
||||
w.posV2(pos)
|
||||
} else if w.p.version >= iexportVersionPosCol {
|
||||
w.posV1(pos)
|
||||
} else {
|
||||
w.posV0(pos)
|
||||
}
|
||||
}
|
||||
|
||||
// posV2 encoding (used only in shallow mode) records positions as
|
||||
// (file, offset), where file is the index in the token.File table
|
||||
// (which records the file name and newline offsets) and offset is a
|
||||
// byte offset. It effectively ignores //line directives.
|
||||
func (w *exportWriter) posV2(pos token.Pos) {
|
||||
if pos == token.NoPos {
|
||||
w.uint64(0)
|
||||
return
|
||||
}
|
||||
file := w.p.fset.File(pos) // fset must be non-nil
|
||||
index, offset := w.p.fileIndexAndOffset(file, pos)
|
||||
w.uint64(1 + index)
|
||||
w.uint64(offset)
|
||||
}
|
||||
|
||||
func (w *exportWriter) posV1(pos token.Pos) {
|
||||
if w.p.fset == nil {
|
||||
w.int64(0)
|
||||
|
@ -549,6 +952,9 @@ func (w *exportWriter) qualifiedType(obj *types.TypeName) {
|
|||
w.pkg(obj.Pkg())
|
||||
}
|
||||
|
||||
// TODO(rfindley): what does 'pkg' even mean here? It would be better to pass
|
||||
// it in explicitly into signatures and structs that may use it for
|
||||
// constructing fields.
|
||||
func (w *exportWriter) typ(t types.Type, pkg *types.Package) {
|
||||
w.data.uint64(w.p.typOff(t, pkg))
|
||||
}
|
||||
|
@ -588,20 +994,31 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||
}()
|
||||
}
|
||||
switch t := t.(type) {
|
||||
case *types.Alias:
|
||||
if targs := aliases.TypeArgs(t); targs.Len() > 0 {
|
||||
w.startType(instanceType)
|
||||
w.pos(t.Obj().Pos())
|
||||
w.typeList(targs, pkg)
|
||||
w.typ(aliases.Origin(t), pkg)
|
||||
return
|
||||
}
|
||||
w.startType(aliasType)
|
||||
w.qualifiedType(t.Obj())
|
||||
|
||||
case *types.Named:
|
||||
if targs := typeparams.NamedTypeArgs(t); targs.Len() > 0 {
|
||||
if targs := t.TypeArgs(); targs.Len() > 0 {
|
||||
w.startType(instanceType)
|
||||
// TODO(rfindley): investigate if this position is correct, and if it
|
||||
// matters.
|
||||
w.pos(t.Obj().Pos())
|
||||
w.typeList(targs, pkg)
|
||||
w.typ(typeparams.NamedTypeOrigin(t), pkg)
|
||||
w.typ(t.Origin(), pkg)
|
||||
return
|
||||
}
|
||||
w.startType(definedType)
|
||||
w.qualifiedType(t.Obj())
|
||||
|
||||
case *typeparams.TypeParam:
|
||||
case *types.TypeParam:
|
||||
w.startType(typeParamType)
|
||||
w.qualifiedType(t.Obj())
|
||||
|
||||
|
@ -640,37 +1057,60 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||
|
||||
case *types.Signature:
|
||||
w.startType(signatureType)
|
||||
w.setPkg(pkg, true)
|
||||
w.pkg(pkg)
|
||||
w.signature(t)
|
||||
|
||||
case *types.Struct:
|
||||
w.startType(structType)
|
||||
n := t.NumFields()
|
||||
// Even for struct{} we must emit some qualifying package, because that's
|
||||
// what the compiler does, and thus that's what the importer expects.
|
||||
fieldPkg := pkg
|
||||
if n > 0 {
|
||||
w.setPkg(t.Field(0).Pkg(), true) // qualifying package for field objects
|
||||
} else {
|
||||
w.setPkg(pkg, true)
|
||||
fieldPkg = t.Field(0).Pkg()
|
||||
}
|
||||
if fieldPkg == nil {
|
||||
// TODO(rfindley): improve this very hacky logic.
|
||||
//
|
||||
// The importer expects a package to be set for all struct types, even
|
||||
// those with no fields. A better encoding might be to set NumFields
|
||||
// before pkg. setPkg panics with a nil package, which may be possible
|
||||
// to reach with invalid packages (and perhaps valid packages, too?), so
|
||||
// (arbitrarily) set the localpkg if available.
|
||||
//
|
||||
// Alternatively, we may be able to simply guarantee that pkg != nil, by
|
||||
// reconsidering the encoding of constant values.
|
||||
if w.p.shallow {
|
||||
fieldPkg = w.p.localpkg
|
||||
} else {
|
||||
panic(internalErrorf("no package to set for empty struct"))
|
||||
}
|
||||
}
|
||||
w.pkg(fieldPkg)
|
||||
w.uint64(uint64(n))
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
f := t.Field(i)
|
||||
if w.p.shallow {
|
||||
w.objectPath(f)
|
||||
}
|
||||
w.pos(f.Pos())
|
||||
w.string(f.Name()) // unexported fields implicitly qualified by prior setPkg
|
||||
w.typ(f.Type(), pkg)
|
||||
w.typ(f.Type(), fieldPkg)
|
||||
w.bool(f.Anonymous())
|
||||
w.string(t.Tag(i)) // note (or tag)
|
||||
}
|
||||
|
||||
case *types.Interface:
|
||||
w.startType(interfaceType)
|
||||
w.setPkg(pkg, true)
|
||||
w.pkg(pkg)
|
||||
|
||||
n := t.NumEmbeddeds()
|
||||
w.uint64(uint64(n))
|
||||
for i := 0; i < n; i++ {
|
||||
ft := t.EmbeddedType(i)
|
||||
tPkg := pkg
|
||||
if named, _ := ft.(*types.Named); named != nil {
|
||||
if named, _ := types.Unalias(ft).(*types.Named); named != nil {
|
||||
w.pos(named.Obj().Pos())
|
||||
} else {
|
||||
w.pos(token.NoPos)
|
||||
|
@ -678,17 +1118,23 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||
w.typ(ft, tPkg)
|
||||
}
|
||||
|
||||
// See comment for struct fields. In shallow mode we change the encoding
|
||||
// for interface methods that are promoted from other packages.
|
||||
|
||||
n = t.NumExplicitMethods()
|
||||
w.uint64(uint64(n))
|
||||
for i := 0; i < n; i++ {
|
||||
m := t.ExplicitMethod(i)
|
||||
if w.p.shallow {
|
||||
w.objectPath(m)
|
||||
}
|
||||
w.pos(m.Pos())
|
||||
w.string(m.Name())
|
||||
sig, _ := m.Type().(*types.Signature)
|
||||
w.signature(sig)
|
||||
}
|
||||
|
||||
case *typeparams.Union:
|
||||
case *types.Union:
|
||||
w.startType(unionType)
|
||||
nt := t.Len()
|
||||
w.uint64(uint64(nt))
|
||||
|
@ -703,12 +1149,61 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *exportWriter) setPkg(pkg *types.Package, write bool) {
|
||||
if write {
|
||||
w.pkg(pkg)
|
||||
// objectPath writes the package and objectPath to use to look up obj in a
|
||||
// different package, when encoding in "shallow" mode.
|
||||
//
|
||||
// When doing a shallow import, the importer creates only the local package,
|
||||
// and requests package symbols for dependencies from the client.
|
||||
// However, certain types defined in the local package may hold objects defined
|
||||
// (perhaps deeply) within another package.
|
||||
//
|
||||
// For example, consider the following:
|
||||
//
|
||||
// package a
|
||||
// func F() chan * map[string] struct { X int }
|
||||
//
|
||||
// package b
|
||||
// import "a"
|
||||
// var B = a.F()
|
||||
//
|
||||
// In this example, the type of b.B holds fields defined in package a.
|
||||
// In order to have the correct canonical objects for the field defined in the
|
||||
// type of B, they are encoded as objectPaths and later looked up in the
|
||||
// importer. The same problem applies to interface methods.
|
||||
func (w *exportWriter) objectPath(obj types.Object) {
|
||||
if obj.Pkg() == nil || obj.Pkg() == w.p.localpkg {
|
||||
// obj.Pkg() may be nil for the builtin error.Error.
|
||||
// In this case, or if obj is declared in the local package, no need to
|
||||
// encode.
|
||||
w.string("")
|
||||
return
|
||||
}
|
||||
|
||||
w.currPkg = pkg
|
||||
objectPath, err := w.p.objectpathEncoder().For(obj)
|
||||
if err != nil {
|
||||
// Fall back to the empty string, which will cause the importer to create a
|
||||
// new object, which matches earlier behavior. Creating a new object is
|
||||
// sufficient for many purposes (such as type checking), but causes certain
|
||||
// references algorithms to fail (golang/go#60819). However, we didn't
|
||||
// notice this problem during months of gopls@v0.12.0 testing.
|
||||
//
|
||||
// TODO(golang/go#61674): this workaround is insufficient, as in the case
|
||||
// where the field forwarded from an instantiated type that may not appear
|
||||
// in the export data of the original package:
|
||||
//
|
||||
// // package a
|
||||
// type A[P any] struct{ F P }
|
||||
//
|
||||
// // package b
|
||||
// type B a.A[int]
|
||||
//
|
||||
// We need to update references algorithms not to depend on this
|
||||
// de-duplication, at which point we may want to simply remove the
|
||||
// workaround here.
|
||||
w.string("")
|
||||
return
|
||||
}
|
||||
w.string(string(objectPath))
|
||||
w.pkg(obj.Pkg())
|
||||
}
|
||||
|
||||
func (w *exportWriter) signature(sig *types.Signature) {
|
||||
|
@ -719,14 +1214,14 @@ func (w *exportWriter) signature(sig *types.Signature) {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *exportWriter) typeList(ts *typeparams.TypeList, pkg *types.Package) {
|
||||
func (w *exportWriter) typeList(ts *types.TypeList, pkg *types.Package) {
|
||||
w.uint64(uint64(ts.Len()))
|
||||
for i := 0; i < ts.Len(); i++ {
|
||||
w.typ(ts.At(i), pkg)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *exportWriter) tparamList(prefix string, list *typeparams.TypeParamList, pkg *types.Package) {
|
||||
func (w *exportWriter) tparamList(prefix string, list *types.TypeParamList, pkg *types.Package) {
|
||||
ll := uint64(list.Len())
|
||||
w.uint64(ll)
|
||||
for i := 0; i < list.Len(); i++ {
|
||||
|
@ -744,7 +1239,7 @@ const blankMarker = "$"
|
|||
// differs from its actual object name: it is prefixed with a qualifier, and
|
||||
// blank type parameter names are disambiguated by their index in the type
|
||||
// parameter list.
|
||||
func tparamExportName(prefix string, tparam *typeparams.TypeParam) string {
|
||||
func tparamExportName(prefix string, tparam *types.TypeParam) string {
|
||||
assert(prefix != "")
|
||||
name := tparam.Obj().Name()
|
||||
if name == "_" {
|
||||
|
@ -789,6 +1284,17 @@ func (w *exportWriter) value(typ types.Type, v constant.Value) {
|
|||
w.int64(int64(v.Kind()))
|
||||
}
|
||||
|
||||
if v.Kind() == constant.Unknown {
|
||||
// golang/go#60605: treat unknown constant values as if they have invalid type
|
||||
//
|
||||
// This loses some fidelity over the package type-checked from source, but that
|
||||
// is acceptable.
|
||||
//
|
||||
// TODO(rfindley): we should switch on the recorded constant kind rather
|
||||
// than the constant type
|
||||
return
|
||||
}
|
||||
|
||||
switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
|
||||
case types.IsBoolean:
|
||||
w.bool(constant.BoolVal(v))
|
||||
|
@ -845,6 +1351,16 @@ func constantToFloat(x constant.Value) *big.Float {
|
|||
return &f
|
||||
}
|
||||
|
||||
func valueToRat(x constant.Value) *big.Rat {
|
||||
// Convert little-endian to big-endian.
|
||||
// I can't believe this is necessary.
|
||||
bytes := constant.Bytes(x)
|
||||
for i := 0; i < len(bytes)/2; i++ {
|
||||
bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
|
||||
}
|
||||
return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
|
||||
}
|
||||
|
||||
// mpint exports a multi-precision integer.
|
||||
//
|
||||
// For unsigned types, small values are written out as a single
|
||||
|
@ -1054,3 +1570,19 @@ func (q *objQueue) popHead() types.Object {
|
|||
q.head++
|
||||
return obj
|
||||
}
|
||||
|
||||
// internalError represents an error generated inside this package.
|
||||
type internalError string
|
||||
|
||||
func (e internalError) Error() string { return "gcimporter: " + string(e) }
|
||||
|
||||
// TODO(adonovan): make this call panic, so that it's symmetric with errorf.
|
||||
// Otherwise it's easy to forget to do anything with the error.
|
||||
//
|
||||
// TODO(adonovan): also, consider switching the names "errorf" and
|
||||
// "internalErrorf" as the former is used for bugs, whose cause is
|
||||
// internal inconsistency, whereas the latter is used for ordinary
|
||||
// situations like bad input, whose cause is external.
|
||||
func internalErrorf(format string, args ...interface{}) error {
|
||||
return internalError(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
|
403
vendor/golang.org/x/tools/internal/gcimporter/iimport.go
generated
vendored
403
vendor/golang.org/x/tools/internal/gcimporter/iimport.go
generated
vendored
|
@ -3,9 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Indexed package import.
|
||||
// See cmd/compile/internal/gc/iexport.go for the export data format.
|
||||
|
||||
// This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go.
|
||||
// See iexport.go for the export data format.
|
||||
|
||||
package gcimporter
|
||||
|
||||
|
@ -21,7 +19,9 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/internal/typeparams"
|
||||
"golang.org/x/tools/go/types/objectpath"
|
||||
"golang.org/x/tools/internal/aliases"
|
||||
"golang.org/x/tools/internal/typesinternal"
|
||||
)
|
||||
|
||||
type intReader struct {
|
||||
|
@ -51,6 +51,7 @@ const (
|
|||
iexportVersionPosCol = 1
|
||||
iexportVersionGo1_18 = 2
|
||||
iexportVersionGenerics = 2
|
||||
iexportVersion = iexportVersionGenerics
|
||||
|
||||
iexportVersionCurrent = 2
|
||||
)
|
||||
|
@ -78,6 +79,20 @@ const (
|
|||
typeParamType
|
||||
instanceType
|
||||
unionType
|
||||
aliasType
|
||||
)
|
||||
|
||||
// Object tags
|
||||
const (
|
||||
varTag = 'V'
|
||||
funcTag = 'F'
|
||||
genericFuncTag = 'G'
|
||||
constTag = 'C'
|
||||
aliasTag = 'A'
|
||||
genericAliasTag = 'B'
|
||||
typeParamTag = 'P'
|
||||
typeTag = 'T'
|
||||
genericTypeTag = 'U'
|
||||
)
|
||||
|
||||
// IImportData imports a package from the serialized package data
|
||||
|
@ -85,7 +100,7 @@ const (
|
|||
// If the export data version is not recognized or the format is otherwise
|
||||
// compromised, an error is returned.
|
||||
func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
|
||||
pkgs, err := iimportCommon(fset, imports, data, false, path, nil)
|
||||
pkgs, err := iimportCommon(fset, GetPackagesFromMap(imports), data, false, path, false, nil)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
@ -94,10 +109,49 @@ func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||
|
||||
// IImportBundle imports a set of packages from the serialized package bundle.
|
||||
func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
|
||||
return iimportCommon(fset, imports, data, true, "", nil)
|
||||
return iimportCommon(fset, GetPackagesFromMap(imports), data, true, "", false, nil)
|
||||
}
|
||||
|
||||
func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) {
|
||||
// A GetPackagesFunc function obtains the non-nil symbols for a set of
|
||||
// packages, creating and recursively importing them as needed. An
|
||||
// implementation should store each package symbol is in the Pkg
|
||||
// field of the items array.
|
||||
//
|
||||
// Any error causes importing to fail. This can be used to quickly read
|
||||
// the import manifest of an export data file without fully decoding it.
|
||||
type GetPackagesFunc = func(items []GetPackagesItem) error
|
||||
|
||||
// A GetPackagesItem is a request from the importer for the package
|
||||
// symbol of the specified name and path.
|
||||
type GetPackagesItem struct {
|
||||
Name, Path string
|
||||
Pkg *types.Package // to be filled in by GetPackagesFunc call
|
||||
|
||||
// private importer state
|
||||
pathOffset uint64
|
||||
nameIndex map[string]uint64
|
||||
}
|
||||
|
||||
// GetPackagesFromMap returns a GetPackagesFunc that retrieves
|
||||
// packages from the given map of package path to package.
|
||||
//
|
||||
// The returned function may mutate m: each requested package that is not
|
||||
// found is created with types.NewPackage and inserted into m.
|
||||
func GetPackagesFromMap(m map[string]*types.Package) GetPackagesFunc {
|
||||
return func(items []GetPackagesItem) error {
|
||||
for i, item := range items {
|
||||
pkg, ok := m[item.Path]
|
||||
if !ok {
|
||||
pkg = types.NewPackage(item.Path, item.Name)
|
||||
m[item.Path] = pkg
|
||||
}
|
||||
items[i].Pkg = pkg
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, bundle bool, path string, shallow bool, reportf ReportFunc) (pkgs []*types.Package, err error) {
|
||||
const currentVersion = iexportVersionCurrent
|
||||
version := int64(-1)
|
||||
if !debug {
|
||||
|
@ -108,7 +162,7 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
} else if version > currentVersion {
|
||||
err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
|
||||
} else {
|
||||
err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
|
||||
err = fmt.Errorf("internal error while importing %q (%v); please report an issue", path, e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -117,11 +171,8 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
r := &intReader{bytes.NewReader(data), path}
|
||||
|
||||
if bundle {
|
||||
bundleVersion := r.uint64()
|
||||
switch bundleVersion {
|
||||
case bundleVersion:
|
||||
default:
|
||||
errorf("unknown bundle format version %d", bundleVersion)
|
||||
if v := r.uint64(); v != bundleVersion {
|
||||
errorf("unknown bundle format version %d", v)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,20 +188,36 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
}
|
||||
|
||||
sLen := int64(r.uint64())
|
||||
var fLen int64
|
||||
var fileOffset []uint64
|
||||
if shallow {
|
||||
// Shallow mode uses a different position encoding.
|
||||
fLen = int64(r.uint64())
|
||||
fileOffset = make([]uint64, r.uint64())
|
||||
for i := range fileOffset {
|
||||
fileOffset[i] = r.uint64()
|
||||
}
|
||||
}
|
||||
dLen := int64(r.uint64())
|
||||
|
||||
whence, _ := r.Seek(0, io.SeekCurrent)
|
||||
stringData := data[whence : whence+sLen]
|
||||
declData := data[whence+sLen : whence+sLen+dLen]
|
||||
r.Seek(sLen+dLen, io.SeekCurrent)
|
||||
fileData := data[whence+sLen : whence+sLen+fLen]
|
||||
declData := data[whence+sLen+fLen : whence+sLen+fLen+dLen]
|
||||
r.Seek(sLen+fLen+dLen, io.SeekCurrent)
|
||||
|
||||
p := iimporter{
|
||||
version: int(version),
|
||||
ipath: path,
|
||||
insert: insert,
|
||||
aliases: aliases.Enabled(),
|
||||
shallow: shallow,
|
||||
reportf: reportf,
|
||||
|
||||
stringData: stringData,
|
||||
stringCache: make(map[uint64]string),
|
||||
fileOffset: fileOffset,
|
||||
fileData: fileData,
|
||||
fileCache: make([]*token.File, len(fileOffset)),
|
||||
pkgCache: make(map[uint64]*types.Package),
|
||||
|
||||
declData: declData,
|
||||
|
@ -171,8 +238,10 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
p.typCache[uint64(i)] = pt
|
||||
}
|
||||
|
||||
pkgList := make([]*types.Package, r.uint64())
|
||||
for i := range pkgList {
|
||||
// Gather the relevant packages from the manifest.
|
||||
items := make([]GetPackagesItem, r.uint64())
|
||||
uniquePkgPaths := make(map[string]bool)
|
||||
for i := range items {
|
||||
pkgPathOff := r.uint64()
|
||||
pkgPath := p.stringAt(pkgPathOff)
|
||||
pkgName := p.stringAt(r.uint64())
|
||||
|
@ -181,30 +250,48 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
if pkgPath == "" {
|
||||
pkgPath = path
|
||||
}
|
||||
pkg := imports[pkgPath]
|
||||
if pkg == nil {
|
||||
pkg = types.NewPackage(pkgPath, pkgName)
|
||||
imports[pkgPath] = pkg
|
||||
} else if pkg.Name() != pkgName {
|
||||
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
|
||||
}
|
||||
if i == 0 && !bundle {
|
||||
p.localpkg = pkg
|
||||
}
|
||||
|
||||
p.pkgCache[pkgPathOff] = pkg
|
||||
items[i].Name = pkgName
|
||||
items[i].Path = pkgPath
|
||||
items[i].pathOffset = pkgPathOff
|
||||
|
||||
// Read index for package.
|
||||
nameIndex := make(map[string]uint64)
|
||||
nSyms := r.uint64()
|
||||
// In shallow mode we don't expect an index for other packages.
|
||||
assert(nSyms == 0 || p.localpkg == pkg || p.insert == nil)
|
||||
// In shallow mode, only the current package (i=0) has an index.
|
||||
assert(!(shallow && i > 0 && nSyms != 0))
|
||||
for ; nSyms > 0; nSyms-- {
|
||||
name := p.stringAt(r.uint64())
|
||||
nameIndex[name] = r.uint64()
|
||||
}
|
||||
|
||||
p.pkgIndex[pkg] = nameIndex
|
||||
items[i].nameIndex = nameIndex
|
||||
|
||||
uniquePkgPaths[pkgPath] = true
|
||||
}
|
||||
// Debugging #63822; hypothesis: there are duplicate PkgPaths.
|
||||
if len(uniquePkgPaths) != len(items) {
|
||||
reportf("found duplicate PkgPaths while reading export data manifest: %v", items)
|
||||
}
|
||||
|
||||
// Request packages all at once from the client,
|
||||
// enabling a parallel implementation.
|
||||
if err := getPackages(items); err != nil {
|
||||
return nil, err // don't wrap this error
|
||||
}
|
||||
|
||||
// Check the results and complete the index.
|
||||
pkgList := make([]*types.Package, len(items))
|
||||
for i, item := range items {
|
||||
pkg := item.Pkg
|
||||
if pkg == nil {
|
||||
errorf("internal error: getPackages returned nil package for %q", item.Path)
|
||||
} else if pkg.Path() != item.Path {
|
||||
errorf("internal error: getPackages returned wrong path %q, want %q", pkg.Path(), item.Path)
|
||||
} else if pkg.Name() != item.Name {
|
||||
errorf("internal error: getPackages returned wrong name %s for package %q, want %s", pkg.Name(), item.Path, item.Name)
|
||||
}
|
||||
p.pkgCache[item.pathOffset] = pkg
|
||||
p.pkgIndex[pkg] = item.nameIndex
|
||||
pkgList[i] = pkg
|
||||
}
|
||||
|
||||
|
@ -251,23 +338,30 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
}
|
||||
|
||||
// SetConstraint can't be called if the constraint type is not yet complete.
|
||||
// When type params are created in the 'P' case of (*importReader).obj(),
|
||||
// When type params are created in the typeParamTag case of (*importReader).obj(),
|
||||
// the associated constraint type may not be complete due to recursion.
|
||||
// Therefore, we defer calling SetConstraint there, and call it here instead
|
||||
// after all types are complete.
|
||||
for _, d := range p.later {
|
||||
typeparams.SetTypeParamConstraint(d.t, d.constraint)
|
||||
d.t.SetConstraint(d.constraint)
|
||||
}
|
||||
|
||||
for _, typ := range p.interfaceList {
|
||||
typ.Complete()
|
||||
}
|
||||
|
||||
// Workaround for golang/go#61561. See the doc for instanceList for details.
|
||||
for _, typ := range p.instanceList {
|
||||
if iface, _ := typ.Underlying().(*types.Interface); iface != nil {
|
||||
iface.Complete()
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
type setConstraintArgs struct {
|
||||
t *typeparams.TypeParam
|
||||
t *types.TypeParam
|
||||
constraint types.Type
|
||||
}
|
||||
|
||||
|
@ -275,11 +369,15 @@ type iimporter struct {
|
|||
version int
|
||||
ipath string
|
||||
|
||||
localpkg *types.Package
|
||||
insert func(pkg *types.Package, name string) // "shallow" mode only
|
||||
aliases bool
|
||||
shallow bool
|
||||
reportf ReportFunc // if non-nil, used to report bugs
|
||||
|
||||
stringData []byte
|
||||
stringCache map[uint64]string
|
||||
fileOffset []uint64 // fileOffset[i] is offset in fileData for info about file encoded as i
|
||||
fileData []byte
|
||||
fileCache []*token.File // memoized decoding of file encoded as i
|
||||
pkgCache map[uint64]*types.Package
|
||||
|
||||
declData []byte
|
||||
|
@ -290,6 +388,12 @@ type iimporter struct {
|
|||
fake fakeFileSet
|
||||
interfaceList []*types.Interface
|
||||
|
||||
// Workaround for the go/types bug golang/go#61561: instances produced during
|
||||
// instantiation may contain incomplete interfaces. Here we only complete the
|
||||
// underlying type of the instance, which is the most common case but doesn't
|
||||
// handle parameterized interface literals defined deeper in the type.
|
||||
instanceList []types.Type // instances for later completion (see golang/go#61561)
|
||||
|
||||
// Arguments for calls to SetConstraint that are deferred due to recursive types
|
||||
later []setConstraintArgs
|
||||
|
||||
|
@ -321,13 +425,9 @@ func (p *iimporter) doDecl(pkg *types.Package, name string) {
|
|||
|
||||
off, ok := p.pkgIndex[pkg][name]
|
||||
if !ok {
|
||||
// In "shallow" mode, call back to the application to
|
||||
// find the object and insert it into the package scope.
|
||||
if p.insert != nil {
|
||||
assert(pkg != p.localpkg)
|
||||
p.insert(pkg, name) // "can't fail"
|
||||
return
|
||||
}
|
||||
// In deep mode, the index should be complete. In shallow
|
||||
// mode, we should have already recursively loaded necessary
|
||||
// dependencies so the above Lookup succeeds.
|
||||
errorf("%v.%v not in index", pkg, name)
|
||||
}
|
||||
|
||||
|
@ -352,6 +452,55 @@ func (p *iimporter) stringAt(off uint64) string {
|
|||
return s
|
||||
}
|
||||
|
||||
func (p *iimporter) fileAt(index uint64) *token.File {
|
||||
file := p.fileCache[index]
|
||||
if file == nil {
|
||||
off := p.fileOffset[index]
|
||||
file = p.decodeFile(intReader{bytes.NewReader(p.fileData[off:]), p.ipath})
|
||||
p.fileCache[index] = file
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
func (p *iimporter) decodeFile(rd intReader) *token.File {
|
||||
filename := p.stringAt(rd.uint64())
|
||||
size := int(rd.uint64())
|
||||
file := p.fake.fset.AddFile(filename, -1, size)
|
||||
|
||||
// SetLines requires a nondecreasing sequence.
|
||||
// Because it is common for clients to derive the interval
|
||||
// [start, start+len(name)] from a start position, and we
|
||||
// want to ensure that the end offset is on the same line,
|
||||
// we fill in the gaps of the sparse encoding with values
|
||||
// that strictly increase by the largest possible amount.
|
||||
// This allows us to avoid having to record the actual end
|
||||
// offset of each needed line.
|
||||
|
||||
lines := make([]int, int(rd.uint64()))
|
||||
var index, offset int
|
||||
for i, n := 0, int(rd.uint64()); i < n; i++ {
|
||||
index += int(rd.uint64())
|
||||
offset += int(rd.uint64())
|
||||
lines[index] = offset
|
||||
|
||||
// Ensure monotonicity between points.
|
||||
for j := index - 1; j > 0 && lines[j] == 0; j-- {
|
||||
lines[j] = lines[j+1] - 1
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure monotonicity after last point.
|
||||
for j := len(lines) - 1; j > 0 && lines[j] == 0; j-- {
|
||||
size--
|
||||
lines[j] = size
|
||||
}
|
||||
|
||||
if !file.SetLines(lines) {
|
||||
errorf("SetLines failed: %d", lines) // can't happen
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
func (p *iimporter) pkgAt(off uint64) *types.Package {
|
||||
if pkg, ok := p.pkgCache[off]; ok {
|
||||
return pkg
|
||||
|
@ -390,7 +539,7 @@ func canReuse(def *types.Named, rhs types.Type) bool {
|
|||
if def == nil {
|
||||
return true
|
||||
}
|
||||
iface, _ := rhs.(*types.Interface)
|
||||
iface, _ := types.Unalias(rhs).(*types.Interface)
|
||||
if iface == nil {
|
||||
return true
|
||||
}
|
||||
|
@ -407,40 +556,56 @@ type importReader struct {
|
|||
prevColumn int64
|
||||
}
|
||||
|
||||
// markBlack is redefined in iimport_go123.go, to work around golang/go#69912.
|
||||
//
|
||||
// If TypeNames are not marked black (in the sense of go/types cycle
|
||||
// detection), they may be mutated when dot-imported. Fix this by punching a
|
||||
// hole through the type, when compiling with Go 1.23. (The bug has been fixed
|
||||
// for 1.24, but the fix was not worth back-porting).
|
||||
var markBlack = func(name *types.TypeName) {}
|
||||
|
||||
func (r *importReader) obj(name string) {
|
||||
tag := r.byte()
|
||||
pos := r.pos()
|
||||
|
||||
switch tag {
|
||||
case 'A':
|
||||
case aliasTag, genericAliasTag:
|
||||
var tparams []*types.TypeParam
|
||||
if tag == genericAliasTag {
|
||||
tparams = r.tparamList()
|
||||
}
|
||||
typ := r.typ()
|
||||
obj := aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ, tparams)
|
||||
markBlack(obj) // workaround for golang/go#69912
|
||||
r.declare(obj)
|
||||
|
||||
r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
|
||||
|
||||
case 'C':
|
||||
case constTag:
|
||||
typ, val := r.value()
|
||||
|
||||
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
||||
|
||||
case 'F', 'G':
|
||||
var tparams []*typeparams.TypeParam
|
||||
if tag == 'G' {
|
||||
case funcTag, genericFuncTag:
|
||||
var tparams []*types.TypeParam
|
||||
if tag == genericFuncTag {
|
||||
tparams = r.tparamList()
|
||||
}
|
||||
sig := r.signature(nil, nil, tparams)
|
||||
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
||||
|
||||
case 'T', 'U':
|
||||
case typeTag, genericTypeTag:
|
||||
// Types can be recursive. We need to setup a stub
|
||||
// declaration before recursing.
|
||||
obj := types.NewTypeName(pos, r.currPkg, name, nil)
|
||||
named := types.NewNamed(obj, nil, nil)
|
||||
|
||||
markBlack(obj) // workaround for golang/go#69912
|
||||
|
||||
// Declare obj before calling r.tparamList, so the new type name is recognized
|
||||
// if used in the constraint of one of its own typeparams (see #48280).
|
||||
r.declare(obj)
|
||||
if tag == 'U' {
|
||||
if tag == genericTypeTag {
|
||||
tparams := r.tparamList()
|
||||
typeparams.SetForNamed(named, tparams)
|
||||
named.SetTypeParams(tparams)
|
||||
}
|
||||
|
||||
underlying := r.p.typAt(r.uint64(), named).Underlying()
|
||||
|
@ -455,14 +620,13 @@ func (r *importReader) obj(name string) {
|
|||
// If the receiver has any targs, set those as the
|
||||
// rparams of the method (since those are the
|
||||
// typeparams being used in the method sig/body).
|
||||
base := baseType(recv.Type())
|
||||
assert(base != nil)
|
||||
targs := typeparams.NamedTypeArgs(base)
|
||||
var rparams []*typeparams.TypeParam
|
||||
_, recvNamed := typesinternal.ReceiverNamed(recv)
|
||||
targs := recvNamed.TypeArgs()
|
||||
var rparams []*types.TypeParam
|
||||
if targs.Len() > 0 {
|
||||
rparams = make([]*typeparams.TypeParam, targs.Len())
|
||||
rparams = make([]*types.TypeParam, targs.Len())
|
||||
for i := range rparams {
|
||||
rparams[i] = targs.At(i).(*typeparams.TypeParam)
|
||||
rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)
|
||||
}
|
||||
}
|
||||
msig := r.signature(recv, rparams, nil)
|
||||
|
@ -471,7 +635,7 @@ func (r *importReader) obj(name string) {
|
|||
}
|
||||
}
|
||||
|
||||
case 'P':
|
||||
case typeParamTag:
|
||||
// We need to "declare" a typeparam in order to have a name that
|
||||
// can be referenced recursively (if needed) in the type param's
|
||||
// bound.
|
||||
|
@ -480,7 +644,7 @@ func (r *importReader) obj(name string) {
|
|||
}
|
||||
name0 := tparamName(name)
|
||||
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
|
||||
t := typeparams.NewTypeParam(tn, nil)
|
||||
t := types.NewTypeParam(tn, nil)
|
||||
|
||||
// To handle recursive references to the typeparam within its
|
||||
// bound, save the partial type in tparamIndex before reading the bounds.
|
||||
|
@ -492,11 +656,11 @@ func (r *importReader) obj(name string) {
|
|||
}
|
||||
constraint := r.typ()
|
||||
if implicit {
|
||||
iface, _ := constraint.(*types.Interface)
|
||||
iface, _ := types.Unalias(constraint).(*types.Interface)
|
||||
if iface == nil {
|
||||
errorf("non-interface constraint marked implicit")
|
||||
}
|
||||
typeparams.MarkImplicit(iface)
|
||||
iface.MarkImplicit()
|
||||
}
|
||||
// The constraint type may not be complete, if we
|
||||
// are in the middle of a type recursion involving type
|
||||
|
@ -504,7 +668,7 @@ func (r *importReader) obj(name string) {
|
|||
// completely set up all types in ImportData.
|
||||
r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
|
||||
|
||||
case 'V':
|
||||
case varTag:
|
||||
typ := r.typ()
|
||||
|
||||
r.declare(types.NewVar(pos, r.currPkg, name, typ))
|
||||
|
@ -645,6 +809,10 @@ func (r *importReader) qualifiedIdent() (*types.Package, string) {
|
|||
}
|
||||
|
||||
func (r *importReader) pos() token.Pos {
|
||||
if r.p.shallow {
|
||||
// precise offsets are encoded only in shallow mode
|
||||
return r.posv2()
|
||||
}
|
||||
if r.p.version >= iexportVersionPosCol {
|
||||
r.posv1()
|
||||
} else {
|
||||
|
@ -681,12 +849,21 @@ func (r *importReader) posv1() {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *importReader) posv2() token.Pos {
|
||||
file := r.uint64()
|
||||
if file == 0 {
|
||||
return token.NoPos
|
||||
}
|
||||
tf := r.p.fileAt(file - 1)
|
||||
return tf.Pos(int(r.uint64()))
|
||||
}
|
||||
|
||||
func (r *importReader) typ() types.Type {
|
||||
return r.p.typAt(r.uint64(), nil)
|
||||
}
|
||||
|
||||
func isInterface(t types.Type) bool {
|
||||
_, ok := t.(*types.Interface)
|
||||
_, ok := types.Unalias(t).(*types.Interface)
|
||||
return ok
|
||||
}
|
||||
|
||||
|
@ -696,7 +873,7 @@ func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
|
|||
func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||
k := r.kind()
|
||||
if debug {
|
||||
r.p.trace("importing type %d (base: %s)", k, base)
|
||||
r.p.trace("importing type %d (base: %v)", k, base)
|
||||
r.p.indent++
|
||||
defer func() {
|
||||
r.p.indent--
|
||||
|
@ -708,7 +885,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||
errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
|
||||
return nil
|
||||
|
||||
case definedType:
|
||||
case aliasType, definedType:
|
||||
pkg, name := r.qualifiedIdent()
|
||||
r.p.doDecl(pkg, name)
|
||||
return pkg.Scope().Lookup(name).(*types.TypeName).Type()
|
||||
|
@ -734,13 +911,28 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||
fields := make([]*types.Var, r.uint64())
|
||||
tags := make([]string, len(fields))
|
||||
for i := range fields {
|
||||
var field *types.Var
|
||||
if r.p.shallow {
|
||||
field, _ = r.objectPathObject().(*types.Var)
|
||||
}
|
||||
|
||||
fpos := r.pos()
|
||||
fname := r.ident()
|
||||
ftyp := r.typ()
|
||||
emb := r.bool()
|
||||
tag := r.string()
|
||||
|
||||
fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
|
||||
// Either this is not a shallow import, the field is local, or the
|
||||
// encoded objectPath failed to produce an object (a bug).
|
||||
//
|
||||
// Even in this last, buggy case, fall back on creating a new field. As
|
||||
// discussed in iexport.go, this is not correct, but mostly works and is
|
||||
// preferable to failing (for now at least).
|
||||
if field == nil {
|
||||
field = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
|
||||
}
|
||||
|
||||
fields[i] = field
|
||||
tags[i] = tag
|
||||
}
|
||||
return types.NewStruct(fields, tags)
|
||||
|
@ -756,6 +948,11 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||
|
||||
methods := make([]*types.Func, r.uint64())
|
||||
for i := range methods {
|
||||
var method *types.Func
|
||||
if r.p.shallow {
|
||||
method, _ = r.objectPathObject().(*types.Func)
|
||||
}
|
||||
|
||||
mpos := r.pos()
|
||||
mname := r.ident()
|
||||
|
||||
|
@ -765,12 +962,15 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||
if base != nil {
|
||||
recv = types.NewVar(token.NoPos, r.currPkg, "", base)
|
||||
}
|
||||
|
||||
msig := r.signature(recv, nil, nil)
|
||||
methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
|
||||
|
||||
if method == nil {
|
||||
method = types.NewFunc(mpos, r.currPkg, mname, msig)
|
||||
}
|
||||
methods[i] = method
|
||||
}
|
||||
|
||||
typ := newInterface(methods, embeddeds)
|
||||
typ := types.NewInterfaceType(methods, embeddeds)
|
||||
r.p.interfaceList = append(r.p.interfaceList, typ)
|
||||
return typ
|
||||
|
||||
|
@ -804,18 +1004,21 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||
// The imported instantiated type doesn't include any methods, so
|
||||
// we must always use the methods of the base (orig) type.
|
||||
// TODO provide a non-nil *Environment
|
||||
t, _ := typeparams.Instantiate(nil, baseType, targs, false)
|
||||
t, _ := types.Instantiate(nil, baseType, targs, false)
|
||||
|
||||
// Workaround for golang/go#61561. See the doc for instanceList for details.
|
||||
r.p.instanceList = append(r.p.instanceList, t)
|
||||
return t
|
||||
|
||||
case unionType:
|
||||
if r.p.version < iexportVersionGenerics {
|
||||
errorf("unexpected instantiation type")
|
||||
}
|
||||
terms := make([]*typeparams.Term, r.uint64())
|
||||
terms := make([]*types.Term, r.uint64())
|
||||
for i := range terms {
|
||||
terms[i] = typeparams.NewTerm(r.bool(), r.typ())
|
||||
terms[i] = types.NewTerm(r.bool(), r.typ())
|
||||
}
|
||||
return typeparams.NewUnion(terms)
|
||||
return types.NewUnion(terms)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -823,23 +1026,43 @@ func (r *importReader) kind() itag {
|
|||
return itag(r.uint64())
|
||||
}
|
||||
|
||||
func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature {
|
||||
// objectPathObject is the inverse of exportWriter.objectPath.
|
||||
//
|
||||
// In shallow mode, certain fields and methods may need to be looked up in an
|
||||
// imported package. See the doc for exportWriter.objectPath for a full
|
||||
// explanation.
|
||||
func (r *importReader) objectPathObject() types.Object {
|
||||
objPath := objectpath.Path(r.string())
|
||||
if objPath == "" {
|
||||
return nil
|
||||
}
|
||||
pkg := r.pkg()
|
||||
obj, err := objectpath.Object(pkg, objPath)
|
||||
if err != nil {
|
||||
if r.p.reportf != nil {
|
||||
r.p.reportf("failed to find object for objectPath %q: %v", objPath, err)
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func (r *importReader) signature(recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {
|
||||
params := r.paramList()
|
||||
results := r.paramList()
|
||||
variadic := params.Len() > 0 && r.bool()
|
||||
return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic)
|
||||
return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
|
||||
}
|
||||
|
||||
func (r *importReader) tparamList() []*typeparams.TypeParam {
|
||||
func (r *importReader) tparamList() []*types.TypeParam {
|
||||
n := r.uint64()
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
xs := make([]*typeparams.TypeParam, n)
|
||||
xs := make([]*types.TypeParam, n)
|
||||
for i := range xs {
|
||||
// Note: the standard library importer is tolerant of nil types here,
|
||||
// though would panic in SetTypeParams.
|
||||
xs[i] = r.typ().(*typeparams.TypeParam)
|
||||
xs[i] = types.Unalias(r.typ()).(*types.TypeParam)
|
||||
}
|
||||
return xs
|
||||
}
|
||||
|
@ -887,12 +1110,8 @@ func (r *importReader) byte() byte {
|
|||
return x
|
||||
}
|
||||
|
||||
func baseType(typ types.Type) *types.Named {
|
||||
// pointer receivers are never types.Named types
|
||||
if p, _ := typ.(*types.Pointer); p != nil {
|
||||
typ = p.Elem()
|
||||
}
|
||||
// receiver base types are always (possibly generic) types.Named types
|
||||
n, _ := typ.(*types.Named)
|
||||
return n
|
||||
}
|
||||
type byPath []*types.Package
|
||||
|
||||
func (a byPath) Len() int { return len(a) }
|
||||
func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }
|
||||
|
|
53
vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go
generated
vendored
Normal file
53
vendor/golang.org/x/tools/internal/gcimporter/iimport_go122.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.22 && !go1.24
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// TODO(rfindley): delete this workaround once go1.24 is assured.
|
||||
|
||||
func init() {
|
||||
// Update markBlack so that it correctly sets the color
|
||||
// of imported TypeNames.
|
||||
//
|
||||
// See the doc comment for markBlack for details.
|
||||
|
||||
type color uint32
|
||||
const (
|
||||
white color = iota
|
||||
black
|
||||
grey
|
||||
)
|
||||
type object struct {
|
||||
_ *types.Scope
|
||||
_ token.Pos
|
||||
_ *types.Package
|
||||
_ string
|
||||
_ types.Type
|
||||
_ uint32
|
||||
color_ color
|
||||
_ token.Pos
|
||||
}
|
||||
type typeName struct {
|
||||
object
|
||||
}
|
||||
|
||||
// If the size of types.TypeName changes, this will fail to compile.
|
||||
const delta = int64(unsafe.Sizeof(typeName{})) - int64(unsafe.Sizeof(types.TypeName{}))
|
||||
var _ [-delta * delta]int
|
||||
|
||||
markBlack = func(obj *types.TypeName) {
|
||||
type uP = unsafe.Pointer
|
||||
var ptr *typeName
|
||||
*(*uP)(uP(&ptr)) = uP(obj)
|
||||
ptr.color_ = black
|
||||
}
|
||||
}
|
22
vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go
generated
vendored
22
vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go
generated
vendored
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.11
|
||||
// +build !go1.11
|
||||
|
||||
package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
||||
named := make([]*types.Named, len(embeddeds))
|
||||
for i, e := range embeddeds {
|
||||
var ok bool
|
||||
named[i], ok = e.(*types.Named)
|
||||
if !ok {
|
||||
panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11")
|
||||
}
|
||||
}
|
||||
return types.NewInterface(methods, named)
|
||||
}
|
14
vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go
generated
vendored
14
vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.11
|
||||
// +build go1.11
|
||||
|
||||
package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
||||
return types.NewInterfaceType(methods, embeddeds)
|
||||
}
|
91
vendor/golang.org/x/tools/internal/gcimporter/predeclared.go
generated
vendored
Normal file
91
vendor/golang.org/x/tools/internal/gcimporter/predeclared.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// predecl is a cache for the predeclared types in types.Universe.
|
||||
//
|
||||
// Cache a distinct result based on the runtime value of any.
|
||||
// The pointer value of the any type varies based on GODEBUG settings.
|
||||
var predeclMu sync.Mutex
|
||||
var predecl map[types.Type][]types.Type
|
||||
|
||||
func predeclared() []types.Type {
|
||||
anyt := types.Universe.Lookup("any").Type()
|
||||
|
||||
predeclMu.Lock()
|
||||
defer predeclMu.Unlock()
|
||||
|
||||
if pre, ok := predecl[anyt]; ok {
|
||||
return pre
|
||||
}
|
||||
|
||||
if predecl == nil {
|
||||
predecl = make(map[types.Type][]types.Type)
|
||||
}
|
||||
|
||||
decls := []types.Type{ // basic types
|
||||
types.Typ[types.Bool],
|
||||
types.Typ[types.Int],
|
||||
types.Typ[types.Int8],
|
||||
types.Typ[types.Int16],
|
||||
types.Typ[types.Int32],
|
||||
types.Typ[types.Int64],
|
||||
types.Typ[types.Uint],
|
||||
types.Typ[types.Uint8],
|
||||
types.Typ[types.Uint16],
|
||||
types.Typ[types.Uint32],
|
||||
types.Typ[types.Uint64],
|
||||
types.Typ[types.Uintptr],
|
||||
types.Typ[types.Float32],
|
||||
types.Typ[types.Float64],
|
||||
types.Typ[types.Complex64],
|
||||
types.Typ[types.Complex128],
|
||||
types.Typ[types.String],
|
||||
|
||||
// basic type aliases
|
||||
types.Universe.Lookup("byte").Type(),
|
||||
types.Universe.Lookup("rune").Type(),
|
||||
|
||||
// error
|
||||
types.Universe.Lookup("error").Type(),
|
||||
|
||||
// untyped types
|
||||
types.Typ[types.UntypedBool],
|
||||
types.Typ[types.UntypedInt],
|
||||
types.Typ[types.UntypedRune],
|
||||
types.Typ[types.UntypedFloat],
|
||||
types.Typ[types.UntypedComplex],
|
||||
types.Typ[types.UntypedString],
|
||||
types.Typ[types.UntypedNil],
|
||||
|
||||
// package unsafe
|
||||
types.Typ[types.UnsafePointer],
|
||||
|
||||
// invalid type
|
||||
types.Typ[types.Invalid], // only appears in packages with errors
|
||||
|
||||
// used internally by gc; never used by this package or in .a files
|
||||
anyType{},
|
||||
|
||||
// comparable
|
||||
types.Universe.Lookup("comparable").Type(),
|
||||
|
||||
// any
|
||||
anyt,
|
||||
}
|
||||
|
||||
predecl[anyt] = decls
|
||||
return decls
|
||||
}
|
||||
|
||||
type anyType struct{}
|
||||
|
||||
func (t anyType) Underlying() types.Type { return t }
|
||||
func (t anyType) String() string { return "any" }
|
30
vendor/golang.org/x/tools/internal/gcimporter/support.go
generated
vendored
Normal file
30
vendor/golang.org/x/tools/internal/gcimporter/support.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Copy of $GOROOT/src/cmd/internal/archive.ReadHeader.
|
||||
func readArchiveHeader(b *bufio.Reader, name string) int {
|
||||
// architecture-independent object file output
|
||||
const HeaderSize = 60
|
||||
|
||||
var buf [HeaderSize]byte
|
||||
if _, err := io.ReadFull(b, buf[:]); err != nil {
|
||||
return -1
|
||||
}
|
||||
aname := strings.Trim(string(buf[0:16]), " ")
|
||||
if !strings.HasPrefix(aname, name) {
|
||||
return -1
|
||||
}
|
||||
asize := strings.Trim(string(buf[48:58]), " ")
|
||||
i, _ := strconv.Atoi(asize)
|
||||
return i
|
||||
}
|
16
vendor/golang.org/x/tools/internal/gcimporter/support_go117.go
generated
vendored
16
vendor/golang.org/x/tools/internal/gcimporter/support_go117.go
generated
vendored
|
@ -1,16 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
const iexportVersion = iexportVersionGo1_11
|
||||
|
||||
func additionalPredeclared() []types.Type {
|
||||
return nil
|
||||
}
|
37
vendor/golang.org/x/tools/internal/gcimporter/support_go118.go
generated
vendored
37
vendor/golang.org/x/tools/internal/gcimporter/support_go118.go
generated
vendored
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
const iexportVersion = iexportVersionGenerics
|
||||
|
||||
// additionalPredeclared returns additional predeclared types in go.1.18.
|
||||
func additionalPredeclared() []types.Type {
|
||||
return []types.Type{
|
||||
// comparable
|
||||
types.Universe.Lookup("comparable").Type(),
|
||||
|
||||
// any
|
||||
types.Universe.Lookup("any").Type(),
|
||||
}
|
||||
}
|
||||
|
||||
// See cmd/compile/internal/types.SplitVargenSuffix.
|
||||
func splitVargenSuffix(name string) (base, suffix string) {
|
||||
i := len(name)
|
||||
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
|
||||
i--
|
||||
}
|
||||
const dot = "·"
|
||||
if i >= len(dot) && name[i-len(dot):i] == dot {
|
||||
i -= len(dot)
|
||||
return name[:i], name[i:]
|
||||
}
|
||||
return name, ""
|
||||
}
|
10
vendor/golang.org/x/tools/internal/gcimporter/unified_no.go
generated
vendored
10
vendor/golang.org/x/tools/internal/gcimporter/unified_no.go
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !(go1.18 && goexperiment.unified)
|
||||
// +build !go1.18 !goexperiment.unified
|
||||
|
||||
package gcimporter
|
||||
|
||||
const unifiedIR = false
|
10
vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go
generated
vendored
10
vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18 && goexperiment.unified
|
||||
// +build go1.18,goexperiment.unified
|
||||
|
||||
package gcimporter
|
||||
|
||||
const unifiedIR = true
|
19
vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go
generated
vendored
19
vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||
err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data")
|
||||
return
|
||||
}
|
247
vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go
generated
vendored
247
vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go
generated
vendored
|
@ -4,16 +4,15 @@
|
|||
|
||||
// Derived from go/internal/gcimporter/ureader.go
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/internal/aliases"
|
||||
"golang.org/x/tools/internal/pkgbits"
|
||||
)
|
||||
|
||||
|
@ -26,6 +25,7 @@ type pkgReader struct {
|
|||
|
||||
ctxt *types.Context
|
||||
imports map[string]*types.Package // previously imported packages, indexed by path
|
||||
aliases bool // create types.Alias nodes
|
||||
|
||||
// lazily initialized arrays corresponding to the unified IR
|
||||
// PosBase, Pkg, and Type sections, respectively.
|
||||
|
@ -51,8 +51,7 @@ func (pr *pkgReader) later(fn func()) {
|
|||
|
||||
// See cmd/compile/internal/noder.derivedInfo.
|
||||
type derivedInfo struct {
|
||||
idx pkgbits.Index
|
||||
needed bool
|
||||
idx pkgbits.Index
|
||||
}
|
||||
|
||||
// See cmd/compile/internal/noder.typeInfo.
|
||||
|
@ -62,8 +61,15 @@ type typeInfo struct {
|
|||
}
|
||||
|
||||
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||
if !debug {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
err = fmt.Errorf("internal error in importing %q (%v); please report an issue", path, x)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
s := string(data)
|
||||
s = s[:strings.LastIndex(s, "\n$$\n")]
|
||||
input := pkgbits.NewPkgDecoder(path, s)
|
||||
pkg = readUnifiedPackage(fset, nil, imports, input)
|
||||
return
|
||||
|
@ -91,6 +97,7 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st
|
|||
|
||||
ctxt: ctxt,
|
||||
imports: imports,
|
||||
aliases: aliases.Enabled(),
|
||||
|
||||
posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),
|
||||
pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
|
||||
|
@ -100,13 +107,17 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st
|
|||
|
||||
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
||||
pkg := r.pkg()
|
||||
r.Bool() // has init
|
||||
if r.Version().Has(pkgbits.HasInit) {
|
||||
r.Bool()
|
||||
}
|
||||
|
||||
for i, n := 0, r.Len(); i < n; i++ {
|
||||
// As if r.obj(), but avoiding the Scope.Lookup call,
|
||||
// to avoid eager loading of imports.
|
||||
r.Sync(pkgbits.SyncObject)
|
||||
assert(!r.Bool())
|
||||
if r.Version().Has(pkgbits.DerivedFuncInstance) {
|
||||
assert(!r.Bool())
|
||||
}
|
||||
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||
assert(r.Len() == 0)
|
||||
}
|
||||
|
@ -121,6 +132,16 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st
|
|||
iface.Complete()
|
||||
}
|
||||
|
||||
// Imports() of pkg are all of the transitive packages that were loaded.
|
||||
var imps []*types.Package
|
||||
for _, imp := range pr.pkgs {
|
||||
if imp != nil && imp != pkg {
|
||||
imps = append(imps, imp)
|
||||
}
|
||||
}
|
||||
sort.Sort(byPath(imps))
|
||||
pkg.SetImports(imps)
|
||||
|
||||
pkg.MarkComplete()
|
||||
return pkg
|
||||
}
|
||||
|
@ -145,7 +166,7 @@ type readerDict struct {
|
|||
// tparams is a slice of the constructed TypeParams for the element.
|
||||
tparams []*types.TypeParam
|
||||
|
||||
// devived is a slice of types derived from tparams, which may be
|
||||
// derived is a slice of types derived from tparams, which may be
|
||||
// instantiated while reading the current element.
|
||||
derived []derivedInfo
|
||||
derivedTypes []types.Type // lazily instantiated from derived
|
||||
|
@ -158,6 +179,17 @@ func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pk
|
|||
}
|
||||
}
|
||||
|
||||
func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
|
||||
return &reader{
|
||||
Decoder: pr.TempDecoder(k, idx, marker),
|
||||
p: pr,
|
||||
}
|
||||
}
|
||||
|
||||
func (pr *pkgReader) retireReader(r *reader) {
|
||||
pr.RetireDecoder(&r.Decoder)
|
||||
}
|
||||
|
||||
// @@@ Positions
|
||||
|
||||
func (r *reader) pos() token.Pos {
|
||||
|
@ -182,26 +214,29 @@ func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {
|
|||
return b
|
||||
}
|
||||
|
||||
r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
|
||||
var filename string
|
||||
{
|
||||
r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
|
||||
|
||||
// Within types2, position bases have a lot more details (e.g.,
|
||||
// keeping track of where //line directives appeared exactly).
|
||||
//
|
||||
// For go/types, we just track the file name.
|
||||
// Within types2, position bases have a lot more details (e.g.,
|
||||
// keeping track of where //line directives appeared exactly).
|
||||
//
|
||||
// For go/types, we just track the file name.
|
||||
|
||||
filename := r.String()
|
||||
filename = r.String()
|
||||
|
||||
if r.Bool() { // file base
|
||||
// Was: "b = token.NewTrimmedFileBase(filename, true)"
|
||||
} else { // line base
|
||||
pos := r.pos()
|
||||
line := r.Uint()
|
||||
col := r.Uint()
|
||||
if r.Bool() { // file base
|
||||
// Was: "b = token.NewTrimmedFileBase(filename, true)"
|
||||
} else { // line base
|
||||
pos := r.pos()
|
||||
line := r.Uint()
|
||||
col := r.Uint()
|
||||
|
||||
// Was: "b = token.NewLineBase(pos, filename, true, line, col)"
|
||||
_, _, _ = pos, line, col
|
||||
// Was: "b = token.NewLineBase(pos, filename, true, line, col)"
|
||||
_, _, _ = pos, line, col
|
||||
}
|
||||
pr.retireReader(r)
|
||||
}
|
||||
|
||||
b := filename
|
||||
pr.posBases[idx] = b
|
||||
return b
|
||||
|
@ -229,7 +264,12 @@ func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package {
|
|||
func (r *reader) doPkg() *types.Package {
|
||||
path := r.String()
|
||||
switch path {
|
||||
case "":
|
||||
// cmd/compile emits path="main" for main packages because
|
||||
// that's the linker symbol prefix it used; but we need
|
||||
// the package's path as it would be reported by go list,
|
||||
// hence "main" below.
|
||||
// See test at go/packages.TestMainPackagePathInModeTypes.
|
||||
case "", "main":
|
||||
path = r.p.PkgPath()
|
||||
case "builtin":
|
||||
return nil // universe
|
||||
|
@ -246,39 +286,9 @@ func (r *reader) doPkg() *types.Package {
|
|||
pkg := types.NewPackage(path, name)
|
||||
r.p.imports[path] = pkg
|
||||
|
||||
imports := make([]*types.Package, r.Len())
|
||||
for i := range imports {
|
||||
imports[i] = r.pkg()
|
||||
}
|
||||
pkg.SetImports(flattenImports(imports))
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
||||
// flattenImports returns the transitive closure of all imported
|
||||
// packages rooted from pkgs.
|
||||
func flattenImports(pkgs []*types.Package) []*types.Package {
|
||||
var res []*types.Package
|
||||
|
||||
seen := make(map[*types.Package]bool)
|
||||
var add func(pkg *types.Package)
|
||||
add = func(pkg *types.Package) {
|
||||
if seen[pkg] {
|
||||
return
|
||||
}
|
||||
seen[pkg] = true
|
||||
res = append(res, pkg)
|
||||
for _, imp := range pkg.Imports() {
|
||||
add(imp)
|
||||
}
|
||||
}
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
add(pkg)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// @@@ Types
|
||||
|
||||
func (r *reader) typ() types.Type {
|
||||
|
@ -307,12 +317,15 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {
|
|||
return typ
|
||||
}
|
||||
|
||||
r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
|
||||
r.dict = dict
|
||||
|
||||
typ := r.doTyp()
|
||||
assert(typ != nil)
|
||||
var typ types.Type
|
||||
{
|
||||
r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
|
||||
r.dict = dict
|
||||
|
||||
typ = r.doTyp()
|
||||
assert(typ != nil)
|
||||
pr.retireReader(r)
|
||||
}
|
||||
// See comment in pkgReader.typIdx explaining how this happens.
|
||||
if prev := *where; prev != nil {
|
||||
return prev
|
||||
|
@ -464,7 +477,9 @@ func (r *reader) param() *types.Var {
|
|||
func (r *reader) obj() (types.Object, []types.Type) {
|
||||
r.Sync(pkgbits.SyncObject)
|
||||
|
||||
assert(!r.Bool())
|
||||
if r.Version().Has(pkgbits.DerivedFuncInstance) {
|
||||
assert(!r.Bool())
|
||||
}
|
||||
|
||||
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||
obj := pkgScope(pkg).Lookup(name)
|
||||
|
@ -478,12 +493,19 @@ func (r *reader) obj() (types.Object, []types.Type) {
|
|||
}
|
||||
|
||||
func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
||||
rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
|
||||
|
||||
objPkg, objName := rname.qualifiedIdent()
|
||||
assert(objName != "")
|
||||
var objPkg *types.Package
|
||||
var objName string
|
||||
var tag pkgbits.CodeObj
|
||||
{
|
||||
rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
|
||||
|
||||
tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
|
||||
objPkg, objName = rname.qualifiedIdent()
|
||||
assert(objName != "")
|
||||
|
||||
tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
|
||||
pr.retireReader(rname)
|
||||
}
|
||||
|
||||
if tag == pkgbits.ObjStub {
|
||||
assert(objPkg == nil || objPkg == types.Unsafe)
|
||||
|
@ -511,8 +533,12 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
|||
|
||||
case pkgbits.ObjAlias:
|
||||
pos := r.pos()
|
||||
var tparams []*types.TypeParam
|
||||
if r.Version().Has(pkgbits.AliasTypeParamNames) {
|
||||
tparams = r.typeParamNames()
|
||||
}
|
||||
typ := r.typ()
|
||||
declare(types.NewTypeName(pos, objPkg, objName, typ))
|
||||
declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ, tparams))
|
||||
|
||||
case pkgbits.ObjConst:
|
||||
pos := r.pos()
|
||||
|
@ -535,22 +561,11 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
|||
|
||||
named.SetTypeParams(r.typeParamNames())
|
||||
|
||||
rhs := r.typ()
|
||||
pk := r.p
|
||||
pk.laterFor(named, func() {
|
||||
// First be sure that the rhs is initialized, if it needs to be initialized.
|
||||
delete(pk.laterFors, named) // prevent cycles
|
||||
if i, ok := pk.laterFors[rhs]; ok {
|
||||
f := pk.laterFns[i]
|
||||
pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op
|
||||
f() // initialize RHS
|
||||
}
|
||||
underlying := rhs.Underlying()
|
||||
|
||||
setUnderlying := func(underlying types.Type) {
|
||||
// If the underlying type is an interface, we need to
|
||||
// duplicate its methods so we can replace the receiver
|
||||
// parameter's type (#49906).
|
||||
if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
|
||||
if iface, ok := types.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
|
||||
methods := make([]*types.Func, iface.NumExplicitMethods())
|
||||
for i := range methods {
|
||||
fn := iface.ExplicitMethod(i)
|
||||
|
@ -571,7 +586,31 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
|||
}
|
||||
|
||||
named.SetUnderlying(underlying)
|
||||
})
|
||||
}
|
||||
|
||||
// Since go.dev/cl/455279, we can assume rhs.Underlying() will
|
||||
// always be non-nil. However, to temporarily support users of
|
||||
// older snapshot releases, we continue to fallback to the old
|
||||
// behavior for now.
|
||||
//
|
||||
// TODO(mdempsky): Remove fallback code and simplify after
|
||||
// allowing time for snapshot users to upgrade.
|
||||
rhs := r.typ()
|
||||
if underlying := rhs.Underlying(); underlying != nil {
|
||||
setUnderlying(underlying)
|
||||
} else {
|
||||
pk := r.p
|
||||
pk.laterFor(named, func() {
|
||||
// First be sure that the rhs is initialized, if it needs to be initialized.
|
||||
delete(pk.laterFors, named) // prevent cycles
|
||||
if i, ok := pk.laterFors[rhs]; ok {
|
||||
f := pk.laterFns[i]
|
||||
pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op
|
||||
f() // initialize RHS
|
||||
}
|
||||
setUnderlying(rhs.Underlying())
|
||||
})
|
||||
}
|
||||
|
||||
for i, n := 0, r.Len(); i < n; i++ {
|
||||
named.AddMethod(r.method())
|
||||
|
@ -588,25 +627,31 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
|||
}
|
||||
|
||||
func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
|
||||
r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
|
||||
|
||||
var dict readerDict
|
||||
|
||||
if implicits := r.Len(); implicits != 0 {
|
||||
errorf("unexpected object with %v implicit type parameter(s)", implicits)
|
||||
}
|
||||
{
|
||||
r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
|
||||
if implicits := r.Len(); implicits != 0 {
|
||||
errorf("unexpected object with %v implicit type parameter(s)", implicits)
|
||||
}
|
||||
|
||||
dict.bounds = make([]typeInfo, r.Len())
|
||||
for i := range dict.bounds {
|
||||
dict.bounds[i] = r.typInfo()
|
||||
}
|
||||
dict.bounds = make([]typeInfo, r.Len())
|
||||
for i := range dict.bounds {
|
||||
dict.bounds[i] = r.typInfo()
|
||||
}
|
||||
|
||||
dict.derived = make([]derivedInfo, r.Len())
|
||||
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
||||
for i := range dict.derived {
|
||||
dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
|
||||
}
|
||||
dict.derived = make([]derivedInfo, r.Len())
|
||||
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
||||
for i := range dict.derived {
|
||||
dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)}
|
||||
if r.Version().Has(pkgbits.DerivedInfoNeeded) {
|
||||
assert(!r.Bool())
|
||||
}
|
||||
}
|
||||
|
||||
pr.retireReader(r)
|
||||
}
|
||||
// function references follow, but reader doesn't need those
|
||||
|
||||
return &dict
|
||||
|
@ -696,3 +741,17 @@ func pkgScope(pkg *types.Package) *types.Scope {
|
|||
}
|
||||
return types.Universe
|
||||
}
|
||||
|
||||
// See cmd/compile/internal/types.SplitVargenSuffix.
|
||||
func splitVargenSuffix(name string) (base, suffix string) {
|
||||
i := len(name)
|
||||
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
|
||||
i--
|
||||
}
|
||||
const dot = "·"
|
||||
if i >= len(dot) && name[i-len(dot):i] == dot {
|
||||
i -= len(dot)
|
||||
return name[:i], name[i:]
|
||||
}
|
||||
return name, ""
|
||||
}
|
||||
|
|
289
vendor/golang.org/x/tools/internal/gocommand/invoke.go
generated
vendored
289
vendor/golang.org/x/tools/internal/gocommand/invoke.go
generated
vendored
|
@ -8,10 +8,14 @@ package gocommand
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
@ -19,9 +23,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
exec "golang.org/x/sys/execabs"
|
||||
|
||||
"golang.org/x/tools/internal/event"
|
||||
"golang.org/x/tools/internal/event/keys"
|
||||
"golang.org/x/tools/internal/event/label"
|
||||
)
|
||||
|
||||
// An Runner will run go command invocations and serialize
|
||||
|
@ -51,9 +55,22 @@ func (runner *Runner) initialize() {
|
|||
// 1.14: go: updating go.mod: existing contents have changed since last read
|
||||
var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`)
|
||||
|
||||
// event keys for go command invocations
|
||||
var (
|
||||
verb = keys.NewString("verb", "go command verb")
|
||||
directory = keys.NewString("directory", "")
|
||||
)
|
||||
|
||||
func invLabels(inv Invocation) []label.Label {
|
||||
return []label.Label{verb.Of(inv.Verb), directory.Of(inv.WorkingDir)}
|
||||
}
|
||||
|
||||
// Run is a convenience wrapper around RunRaw.
|
||||
// It returns only stdout and a "friendly" error.
|
||||
func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, error) {
|
||||
ctx, done := event.Start(ctx, "gocommand.Runner.Run", invLabels(inv)...)
|
||||
defer done()
|
||||
|
||||
stdout, _, friendly, _ := runner.RunRaw(ctx, inv)
|
||||
return stdout, friendly
|
||||
}
|
||||
|
@ -61,13 +78,19 @@ func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, e
|
|||
// RunPiped runs the invocation serially, always waiting for any concurrent
|
||||
// invocations to complete first.
|
||||
func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) error {
|
||||
ctx, done := event.Start(ctx, "gocommand.Runner.RunPiped", invLabels(inv)...)
|
||||
defer done()
|
||||
|
||||
_, err := runner.runPiped(ctx, inv, stdout, stderr)
|
||||
return err
|
||||
}
|
||||
|
||||
// RunRaw runs the invocation, serializing requests only if they fight over
|
||||
// go.mod changes.
|
||||
// Postcondition: both error results have same nilness.
|
||||
func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
||||
ctx, done := event.Start(ctx, "gocommand.Runner.RunRaw", invLabels(inv)...)
|
||||
defer done()
|
||||
// Make sure the runner is always initialized.
|
||||
runner.initialize()
|
||||
|
||||
|
@ -75,23 +98,24 @@ func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer
|
|||
stdout, stderr, friendlyErr, err := runner.runConcurrent(ctx, inv)
|
||||
|
||||
// If we encounter a load concurrency error, we need to retry serially.
|
||||
if friendlyErr == nil || !modConcurrencyError.MatchString(friendlyErr.Error()) {
|
||||
return stdout, stderr, friendlyErr, err
|
||||
}
|
||||
event.Error(ctx, "Load concurrency error, will retry serially", err)
|
||||
if friendlyErr != nil && modConcurrencyError.MatchString(friendlyErr.Error()) {
|
||||
event.Error(ctx, "Load concurrency error, will retry serially", err)
|
||||
|
||||
// Run serially by calling runPiped.
|
||||
stdout.Reset()
|
||||
stderr.Reset()
|
||||
friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr)
|
||||
}
|
||||
|
||||
// Run serially by calling runPiped.
|
||||
stdout.Reset()
|
||||
stderr.Reset()
|
||||
friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr)
|
||||
return stdout, stderr, friendlyErr, err
|
||||
}
|
||||
|
||||
// Postcondition: both error results have same nilness.
|
||||
func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
||||
// Wait for 1 worker to become available.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, nil, nil, ctx.Err()
|
||||
return nil, nil, ctx.Err(), ctx.Err()
|
||||
case runner.inFlight <- struct{}{}:
|
||||
defer func() { <-runner.inFlight }()
|
||||
}
|
||||
|
@ -101,6 +125,7 @@ func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes
|
|||
return stdout, stderr, friendlyErr, err
|
||||
}
|
||||
|
||||
// Postcondition: both error results have same nilness.
|
||||
func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) (error, error) {
|
||||
// Make sure the runner is always initialized.
|
||||
runner.initialize()
|
||||
|
@ -109,7 +134,7 @@ func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stde
|
|||
// runPiped commands.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
return ctx.Err(), ctx.Err()
|
||||
case runner.serialized <- struct{}{}:
|
||||
defer func() { <-runner.serialized }()
|
||||
}
|
||||
|
@ -119,7 +144,7 @@ func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stde
|
|||
for i := 0; i < maxInFlight; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
return ctx.Err(), ctx.Err()
|
||||
case runner.inFlight <- struct{}{}:
|
||||
// Make sure we always "return" any workers we took.
|
||||
defer func() { <-runner.inFlight }()
|
||||
|
@ -136,12 +161,17 @@ type Invocation struct {
|
|||
BuildFlags []string
|
||||
|
||||
// If ModFlag is set, the go command is invoked with -mod=ModFlag.
|
||||
// TODO(rfindley): remove, in favor of Args.
|
||||
ModFlag string
|
||||
|
||||
// If ModFile is set, the go command is invoked with -modfile=ModFile.
|
||||
// TODO(rfindley): remove, in favor of Args.
|
||||
ModFile string
|
||||
|
||||
// If Overlay is set, the go command is invoked with -overlay=Overlay.
|
||||
// Overlay is the name of the JSON overlay file that describes
|
||||
// unsaved editor buffers; see [WriteOverlays].
|
||||
// If set, the go command is invoked with -overlay=Overlay.
|
||||
// TODO(rfindley): remove, in favor of Args.
|
||||
Overlay string
|
||||
|
||||
// If CleanEnv is set, the invocation will run only with the environment
|
||||
|
@ -152,6 +182,7 @@ type Invocation struct {
|
|||
Logf func(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// Postcondition: both error results have same nilness.
|
||||
func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io.Writer) (friendlyError error, rawError error) {
|
||||
rawError = i.run(ctx, stdout, stderr)
|
||||
if rawError != nil {
|
||||
|
@ -168,12 +199,14 @@ func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io
|
|||
return
|
||||
}
|
||||
|
||||
func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
||||
log := i.Logf
|
||||
if log == nil {
|
||||
log = func(string, ...interface{}) {}
|
||||
// logf logs if i.Logf is non-nil.
|
||||
func (i *Invocation) logf(format string, args ...any) {
|
||||
if i.Logf != nil {
|
||||
i.Logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
||||
goArgs := []string{i.Verb}
|
||||
|
||||
appendModFile := func() {
|
||||
|
@ -215,12 +248,24 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
|||
cmd := exec.Command("go", goArgs...)
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
// On darwin the cwd gets resolved to the real path, which breaks anything that
|
||||
// expects the working directory to keep the original path, including the
|
||||
|
||||
// https://go.dev/issue/59541: don't wait forever copying stderr
|
||||
// after the command has exited.
|
||||
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
|
||||
// soon as ctx is done. However, we also don't want to wait around forever
|
||||
// for stderr. Give a much-longer-than-reasonable delay and then assume that
|
||||
// something has wedged in the kernel or runtime.
|
||||
cmd.WaitDelay = 30 * time.Second
|
||||
|
||||
// The cwd gets resolved to the real path. On Darwin, where
|
||||
// /tmp is a symlink, this breaks anything that expects the
|
||||
// working directory to keep the original path, including the
|
||||
// go command when dealing with modules.
|
||||
// The Go stdlib has a special feature where if the cwd and the PWD are the
|
||||
// same node then it trusts the PWD, so by setting it in the env for the child
|
||||
// process we fix up all the paths returned by the go command.
|
||||
//
|
||||
// os.Getwd has a special feature where if the cwd and the PWD
|
||||
// are the same node then it trusts the PWD, so by setting it
|
||||
// in the env for the child process we fix up all the paths
|
||||
// returned by the go command.
|
||||
if !i.CleanEnv {
|
||||
cmd.Env = os.Environ()
|
||||
}
|
||||
|
@ -229,7 +274,13 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
|||
cmd.Env = append(cmd.Env, "PWD="+i.WorkingDir)
|
||||
cmd.Dir = i.WorkingDir
|
||||
}
|
||||
defer func(start time.Time) { log("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now())
|
||||
|
||||
debugStr := cmdDebugStr(cmd)
|
||||
i.logf("starting %v", debugStr)
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
i.logf("%s for %v", time.Since(start), debugStr)
|
||||
}()
|
||||
|
||||
return runCmdContext(ctx, cmd)
|
||||
}
|
||||
|
@ -242,10 +293,86 @@ var DebugHangingGoCommands = false
|
|||
|
||||
// runCmdContext is like exec.CommandContext except it sends os.Interrupt
|
||||
// before os.Kill.
|
||||
func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
|
||||
if err := cmd.Start(); err != nil {
|
||||
func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
|
||||
// If cmd.Stdout is not an *os.File, the exec package will create a pipe and
|
||||
// copy it to the Writer in a goroutine until the process has finished and
|
||||
// either the pipe reaches EOF or command's WaitDelay expires.
|
||||
//
|
||||
// However, the output from 'go list' can be quite large, and we don't want to
|
||||
// keep reading (and allocating buffers) if we've already decided we don't
|
||||
// care about the output. We don't want to wait for the process to finish, and
|
||||
// we don't wait to wait for the WaitDelay to expire either.
|
||||
//
|
||||
// Instead, if cmd.Stdout requires a copying goroutine we explicitly replace
|
||||
// it with a pipe (which is an *os.File), which we can close in order to stop
|
||||
// copying output as soon as we realize we don't care about it.
|
||||
var stdoutW *os.File
|
||||
if cmd.Stdout != nil {
|
||||
if _, ok := cmd.Stdout.(*os.File); !ok {
|
||||
var stdoutR *os.File
|
||||
stdoutR, stdoutW, err = os.Pipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prevStdout := cmd.Stdout
|
||||
cmd.Stdout = stdoutW
|
||||
|
||||
stdoutErr := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := io.Copy(prevStdout, stdoutR)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("copying stdout: %w", err)
|
||||
}
|
||||
stdoutErr <- err
|
||||
}()
|
||||
defer func() {
|
||||
// We started a goroutine to copy a stdout pipe.
|
||||
// Wait for it to finish, or terminate it if need be.
|
||||
var err2 error
|
||||
select {
|
||||
case err2 = <-stdoutErr:
|
||||
stdoutR.Close()
|
||||
case <-ctx.Done():
|
||||
stdoutR.Close()
|
||||
// Per https://pkg.go.dev/os#File.Close, the call to stdoutR.Close
|
||||
// should cause the Read call in io.Copy to unblock and return
|
||||
// immediately, but we still need to receive from stdoutErr to confirm
|
||||
// that it has happened.
|
||||
<-stdoutErr
|
||||
err2 = ctx.Err()
|
||||
}
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
// Per https://pkg.go.dev/os/exec#Cmd, “If Stdout and Stderr are the
|
||||
// same writer, and have a type that can be compared with ==, at most
|
||||
// one goroutine at a time will call Write.”
|
||||
//
|
||||
// Since we're starting a goroutine that writes to cmd.Stdout, we must
|
||||
// also update cmd.Stderr so that it still holds.
|
||||
func() {
|
||||
defer func() { recover() }()
|
||||
if cmd.Stderr == prevStdout {
|
||||
cmd.Stderr = cmd.Stdout
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
err = cmd.Start()
|
||||
if stdoutW != nil {
|
||||
// The child process has inherited the pipe file,
|
||||
// so close the copy held in this process.
|
||||
stdoutW.Close()
|
||||
stdoutW = nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resChan := make(chan error, 1)
|
||||
go func() {
|
||||
resChan <- cmd.Wait()
|
||||
|
@ -253,12 +380,15 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
|
|||
|
||||
// If we're interested in debugging hanging Go commands, stop waiting after a
|
||||
// minute and panic with interesting information.
|
||||
if DebugHangingGoCommands {
|
||||
debug := DebugHangingGoCommands
|
||||
if debug {
|
||||
timer := time.NewTimer(1 * time.Minute)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-time.After(1 * time.Minute):
|
||||
HandleHangingGoCommand(cmd.Process)
|
||||
case <-timer.C:
|
||||
HandleHangingGoCommand(startTime, cmd)
|
||||
case <-ctx.Done():
|
||||
}
|
||||
} else {
|
||||
|
@ -270,34 +400,29 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
|
|||
}
|
||||
|
||||
// Cancelled. Interrupt and see if it ends voluntarily.
|
||||
cmd.Process.Signal(os.Interrupt)
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-time.After(time.Second):
|
||||
if err := cmd.Process.Signal(os.Interrupt); err == nil {
|
||||
// (We used to wait only 1s but this proved
|
||||
// fragile on loaded builder machines.)
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-timer.C:
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't shut down in response to interrupt. Kill it hard.
|
||||
// TODO(rfindley): per advice from bcmills@, it may be better to send SIGQUIT
|
||||
// on certain platforms, such as unix.
|
||||
if err := cmd.Process.Kill(); err != nil && DebugHangingGoCommands {
|
||||
// Don't panic here as this reliably fails on windows with EINVAL.
|
||||
if err := cmd.Process.Kill(); err != nil && !errors.Is(err, os.ErrProcessDone) && debug {
|
||||
log.Printf("error killing the Go command: %v", err)
|
||||
}
|
||||
|
||||
// See above: don't wait indefinitely if we're debugging hanging Go commands.
|
||||
if DebugHangingGoCommands {
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-time.After(10 * time.Second): // a shorter wait as resChan should return quickly following Kill
|
||||
HandleHangingGoCommand(cmd.Process)
|
||||
}
|
||||
}
|
||||
return <-resChan
|
||||
}
|
||||
|
||||
func HandleHangingGoCommand(proc *os.Process) {
|
||||
func HandleHangingGoCommand(start time.Time, cmd *exec.Cmd) {
|
||||
switch runtime.GOOS {
|
||||
case "linux", "darwin", "freebsd", "netbsd":
|
||||
fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND
|
||||
|
@ -330,7 +455,7 @@ See golang/go#54461 for more details.`)
|
|||
panic(fmt.Sprintf("running %s: %v", listFiles, err))
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("detected hanging go command (pid %d): see golang/go#54461 for more details", proc.Pid))
|
||||
panic(fmt.Sprintf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid))
|
||||
}
|
||||
|
||||
func cmdDebugStr(cmd *exec.Cmd) string {
|
||||
|
@ -354,3 +479,73 @@ func cmdDebugStr(cmd *exec.Cmd) string {
|
|||
}
|
||||
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
|
||||
}
|
||||
|
||||
// WriteOverlays writes each value in the overlay (see the Overlay
|
||||
// field of go/packages.Config) to a temporary file and returns the name
|
||||
// of a JSON file describing the mapping that is suitable for the "go
|
||||
// list -overlay" flag.
|
||||
//
|
||||
// On success, the caller must call the cleanup function exactly once
|
||||
// when the files are no longer needed.
|
||||
func WriteOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error) {
|
||||
// Do nothing if there are no overlays in the config.
|
||||
if len(overlay) == 0 {
|
||||
return "", func() {}, nil
|
||||
}
|
||||
|
||||
dir, err := os.MkdirTemp("", "gocommand-*")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
// The caller must clean up this directory,
|
||||
// unless this function returns an error.
|
||||
// (The cleanup operand of each return
|
||||
// statement below is ignored.)
|
||||
defer func() {
|
||||
cleanup = func() {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
if err != nil {
|
||||
cleanup()
|
||||
cleanup = nil
|
||||
}
|
||||
}()
|
||||
|
||||
// Write each map entry to a temporary file.
|
||||
overlays := make(map[string]string)
|
||||
for k, v := range overlay {
|
||||
// Use a unique basename for each file (001-foo.go),
|
||||
// to avoid creating nested directories.
|
||||
base := fmt.Sprintf("%d-%s", 1+len(overlays), filepath.Base(k))
|
||||
filename := filepath.Join(dir, base)
|
||||
err := os.WriteFile(filename, v, 0666)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
overlays[k] = filename
|
||||
}
|
||||
|
||||
// Write the JSON overlay file that maps logical file names to temp files.
|
||||
//
|
||||
// OverlayJSON is the format overlay files are expected to be in.
|
||||
// The Replace map maps from overlaid paths to replacement paths:
|
||||
// the Go command will forward all reads trying to open
|
||||
// each overlaid path to its replacement path, or consider the overlaid
|
||||
// path not to exist if the replacement path is empty.
|
||||
//
|
||||
// From golang/go#39958.
|
||||
type OverlayJSON struct {
|
||||
Replace map[string]string `json:"replace,omitempty"`
|
||||
}
|
||||
b, err := json.Marshal(OverlayJSON{Replace: overlays})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
filename = filepath.Join(dir, "overlay.json")
|
||||
if err := os.WriteFile(filename, b, 0666); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return filename, nil, nil
|
||||
}
|
||||
|
|
54
vendor/golang.org/x/tools/internal/gocommand/vendor.go
generated
vendored
54
vendor/golang.org/x/tools/internal/gocommand/vendor.go
generated
vendored
|
@ -107,3 +107,57 @@ func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*Modul
|
|||
}
|
||||
return mod, lines[4] == "go1.14", nil
|
||||
}
|
||||
|
||||
// WorkspaceVendorEnabled reports whether workspace vendoring is enabled. It takes a *Runner to execute Go commands
|
||||
// with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,
|
||||
// of which only Verb and Args are modified to run the appropriate Go command.
|
||||
// Inspired by setDefaultBuildMod in modload/init.go
|
||||
func WorkspaceVendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, []*ModuleJSON, error) {
|
||||
inv.Verb = "env"
|
||||
inv.Args = []string{"GOWORK"}
|
||||
stdout, err := r.Run(ctx, inv)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
goWork := string(bytes.TrimSpace(stdout.Bytes()))
|
||||
if fi, err := os.Stat(filepath.Join(filepath.Dir(goWork), "vendor")); err == nil && fi.IsDir() {
|
||||
mainMods, err := getWorkspaceMainModules(ctx, inv, r)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, mainMods, nil
|
||||
}
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
// getWorkspaceMainModules gets the main modules' information.
|
||||
// This is the information needed to figure out if vendoring should be enabled.
|
||||
func getWorkspaceMainModules(ctx context.Context, inv Invocation, r *Runner) ([]*ModuleJSON, error) {
|
||||
const format = `{{.Path}}
|
||||
{{.Dir}}
|
||||
{{.GoMod}}
|
||||
{{.GoVersion}}
|
||||
`
|
||||
inv.Verb = "list"
|
||||
inv.Args = []string{"-m", "-f", format}
|
||||
stdout, err := r.Run(ctx, inv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.Split(strings.TrimSuffix(stdout.String(), "\n"), "\n")
|
||||
if len(lines) < 4 {
|
||||
return nil, fmt.Errorf("unexpected stdout: %q", stdout.String())
|
||||
}
|
||||
mods := make([]*ModuleJSON, 0, len(lines)/4)
|
||||
for i := 0; i < len(lines); i += 4 {
|
||||
mods = append(mods, &ModuleJSON{
|
||||
Path: lines[i],
|
||||
Dir: lines[i+1],
|
||||
GoMod: lines[i+2],
|
||||
GoVersion: lines[i+3],
|
||||
Main: true,
|
||||
})
|
||||
}
|
||||
return mods, nil
|
||||
}
|
||||
|
|
41
vendor/golang.org/x/tools/internal/gocommand/version.go
generated
vendored
41
vendor/golang.org/x/tools/internal/gocommand/version.go
generated
vendored
|
@ -7,6 +7,7 @@ package gocommand
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -22,21 +23,11 @@ import (
|
|||
func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {
|
||||
inv.Verb = "list"
|
||||
inv.Args = []string{"-e", "-f", `{{context.ReleaseTags}}`, `--`, `unsafe`}
|
||||
inv.Env = append(append([]string{}, inv.Env...), "GO111MODULE=off")
|
||||
// Unset any unneeded flags, and remove them from BuildFlags, if they're
|
||||
// present.
|
||||
inv.ModFile = ""
|
||||
inv.BuildFlags = nil // This is not a build command.
|
||||
inv.ModFlag = ""
|
||||
var buildFlags []string
|
||||
for _, flag := range inv.BuildFlags {
|
||||
// Flags can be prefixed by one or two dashes.
|
||||
f := strings.TrimPrefix(strings.TrimPrefix(flag, "-"), "-")
|
||||
if strings.HasPrefix(f, "mod=") || strings.HasPrefix(f, "modfile=") {
|
||||
continue
|
||||
}
|
||||
buildFlags = append(buildFlags, flag)
|
||||
}
|
||||
inv.BuildFlags = buildFlags
|
||||
inv.ModFile = ""
|
||||
inv.Env = append(inv.Env[:len(inv.Env):len(inv.Env)], "GO111MODULE=off")
|
||||
|
||||
stdoutBytes, err := r.Run(ctx, inv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -56,3 +47,25 @@ func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {
|
|||
}
|
||||
return 0, fmt.Errorf("no parseable ReleaseTags in %v", tags)
|
||||
}
|
||||
|
||||
// GoVersionOutput returns the complete output of the go version command.
|
||||
func GoVersionOutput(ctx context.Context, inv Invocation, r *Runner) (string, error) {
|
||||
inv.Verb = "version"
|
||||
goVersion, err := r.Run(ctx, inv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return goVersion.String(), nil
|
||||
}
|
||||
|
||||
// ParseGoVersionOutput extracts the Go version string
|
||||
// from the output of the "go version" command.
|
||||
// Given an unrecognized form, it returns an empty string.
|
||||
func ParseGoVersionOutput(data string) string {
|
||||
re := regexp.MustCompile(`^go version (go\S+|devel \S+)`)
|
||||
m := re.FindStringSubmatch(data)
|
||||
if len(m) != 2 {
|
||||
return "" // unrecognized version
|
||||
}
|
||||
return m[1]
|
||||
}
|
||||
|
|
71
vendor/golang.org/x/tools/internal/goroot/importcfg.go
generated
vendored
71
vendor/golang.org/x/tools/internal/goroot/importcfg.go
generated
vendored
|
@ -1,71 +0,0 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package goroot is a copy of package internal/goroot
|
||||
// in the main GO repot. It provides a utility to produce
|
||||
// an importcfg and import path to package file map mapping
|
||||
// standard library packages to the locations of their export
|
||||
// data files.
|
||||
package goroot
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Importcfg returns an importcfg file to be passed to the
|
||||
// Go compiler that contains the cached paths for the .a files for the
|
||||
// standard library.
|
||||
func Importcfg() (string, error) {
|
||||
var icfg bytes.Buffer
|
||||
|
||||
m, err := PkgfileMap()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fmt.Fprintf(&icfg, "# import config")
|
||||
for importPath, export := range m {
|
||||
if importPath != "unsafe" && export != "" { // unsafe
|
||||
fmt.Fprintf(&icfg, "\npackagefile %s=%s", importPath, export)
|
||||
}
|
||||
}
|
||||
s := icfg.String()
|
||||
return s, nil
|
||||
}
|
||||
|
||||
var (
|
||||
stdlibPkgfileMap map[string]string
|
||||
stdlibPkgfileErr error
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// PkgfileMap returns a map of package paths to the location on disk
|
||||
// of the .a file for the package.
|
||||
// The caller must not modify the map.
|
||||
func PkgfileMap() (map[string]string, error) {
|
||||
once.Do(func() {
|
||||
m := make(map[string]string)
|
||||
output, err := exec.Command("go", "list", "-export", "-e", "-f", "{{.ImportPath}} {{.Export}}", "std", "cmd").Output()
|
||||
if err != nil {
|
||||
stdlibPkgfileErr = err
|
||||
}
|
||||
for _, line := range strings.Split(string(output), "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
sp := strings.SplitN(line, " ", 2)
|
||||
if len(sp) != 2 {
|
||||
err = fmt.Errorf("determining pkgfile map: invalid line in go list output: %q", line)
|
||||
return
|
||||
}
|
||||
importPath, export := sp[0], sp[1]
|
||||
m[importPath] = export
|
||||
}
|
||||
stdlibPkgfileMap = m
|
||||
})
|
||||
return stdlibPkgfileMap, stdlibPkgfileErr
|
||||
}
|
10
vendor/golang.org/x/tools/internal/packagesinternal/packages.go
generated
vendored
10
vendor/golang.org/x/tools/internal/packagesinternal/packages.go
generated
vendored
|
@ -5,11 +5,6 @@
|
|||
// Package packagesinternal exposes internal-only fields from go/packages.
|
||||
package packagesinternal
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/gocommand"
|
||||
)
|
||||
|
||||
var GetForTest = func(p interface{}) string { return "" }
|
||||
var GetDepsErrors = func(p interface{}) []*PackageError { return nil }
|
||||
|
||||
type PackageError struct {
|
||||
|
@ -18,13 +13,8 @@ type PackageError struct {
|
|||
Err string // the error itself
|
||||
}
|
||||
|
||||
var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil }
|
||||
|
||||
var SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {}
|
||||
|
||||
var TypecheckCgo int
|
||||
var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
|
||||
var ForTest int // must be set as a LoadMode to call GetForTest
|
||||
|
||||
var SetModFlag = func(config interface{}, value string) {}
|
||||
var SetModFile = func(config interface{}, value string) {}
|
||||
|
|
137
vendor/golang.org/x/tools/internal/pkgbits/decoder.go
generated
vendored
137
vendor/golang.org/x/tools/internal/pkgbits/decoder.go
generated
vendored
|
@ -6,6 +6,7 @@ package pkgbits
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
|
@ -20,7 +21,7 @@ import (
|
|||
// export data.
|
||||
type PkgDecoder struct {
|
||||
// version is the file format version.
|
||||
version uint32
|
||||
version Version
|
||||
|
||||
// sync indicates whether the file uses sync markers.
|
||||
sync bool
|
||||
|
@ -52,6 +53,8 @@ type PkgDecoder struct {
|
|||
// For example, section K's end positions start at elemEndsEnds[K-1]
|
||||
// (or 0, if K==0) and end at elemEndsEnds[K].
|
||||
elemEndsEnds [numRelocs]uint32
|
||||
|
||||
scratchRelocEnt []RelocEnt
|
||||
}
|
||||
|
||||
// PkgPath returns the package path for the package
|
||||
|
@ -65,8 +68,6 @@ func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync }
|
|||
// NewPkgDecoder returns a PkgDecoder initialized to read the Unified
|
||||
// IR export data from input. pkgPath is the package path for the
|
||||
// compilation unit that produced the export data.
|
||||
//
|
||||
// TODO(mdempsky): Remove pkgPath parameter; unneeded since CL 391014.
|
||||
func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
||||
pr := PkgDecoder{
|
||||
pkgPath: pkgPath,
|
||||
|
@ -77,14 +78,15 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
|||
|
||||
r := strings.NewReader(input)
|
||||
|
||||
assert(binary.Read(r, binary.LittleEndian, &pr.version) == nil)
|
||||
var ver uint32
|
||||
assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
|
||||
pr.version = Version(ver)
|
||||
|
||||
switch pr.version {
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported version: %v", pr.version))
|
||||
case 0:
|
||||
// no flags
|
||||
case 1:
|
||||
if pr.version >= numVersions {
|
||||
panic(fmt.Errorf("cannot decode %q, export data version %d is greater than maximum supported version %d", pkgPath, pr.version, numVersions-1))
|
||||
}
|
||||
|
||||
if pr.version.Has(Flags) {
|
||||
var flags uint32
|
||||
assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
|
||||
pr.sync = flags&flagSyncMarkers != 0
|
||||
|
@ -99,7 +101,9 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
|||
assert(err == nil)
|
||||
|
||||
pr.elemData = input[pos:]
|
||||
assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
||||
|
||||
const fingerprintSize = 8
|
||||
assert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
||||
|
||||
return pr
|
||||
}
|
||||
|
@ -133,7 +137,7 @@ func (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int {
|
|||
absIdx += int(pr.elemEndsEnds[k-1])
|
||||
}
|
||||
if absIdx >= int(pr.elemEndsEnds[k]) {
|
||||
errorf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
|
||||
panicf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
|
||||
}
|
||||
return absIdx
|
||||
}
|
||||
|
@ -165,6 +169,21 @@ func (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Deco
|
|||
return r
|
||||
}
|
||||
|
||||
// TempDecoder returns a Decoder for the given (section, index) pair,
|
||||
// and decodes the given SyncMarker from the element bitstream.
|
||||
// If possible the Decoder should be RetireDecoder'd when it is no longer
|
||||
// needed, this will avoid heap allocations.
|
||||
func (pr *PkgDecoder) TempDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {
|
||||
r := pr.TempDecoderRaw(k, idx)
|
||||
r.Sync(marker)
|
||||
return r
|
||||
}
|
||||
|
||||
func (pr *PkgDecoder) RetireDecoder(d *Decoder) {
|
||||
pr.scratchRelocEnt = d.Relocs
|
||||
d.Relocs = nil
|
||||
}
|
||||
|
||||
// NewDecoderRaw returns a Decoder for the given (section, index) pair.
|
||||
//
|
||||
// Most callers should use NewDecoder instead.
|
||||
|
@ -175,9 +194,7 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
|
|||
Idx: idx,
|
||||
}
|
||||
|
||||
// TODO(mdempsky) r.data.Reset(...) after #44505 is resolved.
|
||||
r.Data = *strings.NewReader(pr.DataIdx(k, idx))
|
||||
|
||||
r.Data.Reset(pr.DataIdx(k, idx))
|
||||
r.Sync(SyncRelocs)
|
||||
r.Relocs = make([]RelocEnt, r.Len())
|
||||
for i := range r.Relocs {
|
||||
|
@ -188,6 +205,30 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
|
|||
return r
|
||||
}
|
||||
|
||||
func (pr *PkgDecoder) TempDecoderRaw(k RelocKind, idx Index) Decoder {
|
||||
r := Decoder{
|
||||
common: pr,
|
||||
k: k,
|
||||
Idx: idx,
|
||||
}
|
||||
|
||||
r.Data.Reset(pr.DataIdx(k, idx))
|
||||
r.Sync(SyncRelocs)
|
||||
l := r.Len()
|
||||
if cap(pr.scratchRelocEnt) >= l {
|
||||
r.Relocs = pr.scratchRelocEnt[:l]
|
||||
pr.scratchRelocEnt = nil
|
||||
} else {
|
||||
r.Relocs = make([]RelocEnt, l)
|
||||
}
|
||||
for i := range r.Relocs {
|
||||
r.Sync(SyncReloc)
|
||||
r.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// A Decoder provides methods for decoding an individual element's
|
||||
// bitstream data.
|
||||
type Decoder struct {
|
||||
|
@ -202,16 +243,44 @@ type Decoder struct {
|
|||
|
||||
func (r *Decoder) checkErr(err error) {
|
||||
if err != nil {
|
||||
errorf("unexpected decoding error: %w", err)
|
||||
panicf("unexpected decoding error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Decoder) rawUvarint() uint64 {
|
||||
x, err := binary.ReadUvarint(&r.Data)
|
||||
x, err := readUvarint(&r.Data)
|
||||
r.checkErr(err)
|
||||
return x
|
||||
}
|
||||
|
||||
// readUvarint is a type-specialized copy of encoding/binary.ReadUvarint.
|
||||
// This avoids the interface conversion and thus has better escape properties,
|
||||
// which flows up the stack.
|
||||
func readUvarint(r *strings.Reader) (uint64, error) {
|
||||
var x uint64
|
||||
var s uint
|
||||
for i := 0; i < binary.MaxVarintLen64; i++ {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
if i > 0 && err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return x, err
|
||||
}
|
||||
if b < 0x80 {
|
||||
if i == binary.MaxVarintLen64-1 && b > 1 {
|
||||
return x, overflow
|
||||
}
|
||||
return x | uint64(b)<<s, nil
|
||||
}
|
||||
x |= uint64(b&0x7f) << s
|
||||
s += 7
|
||||
}
|
||||
return x, overflow
|
||||
}
|
||||
|
||||
var overflow = errors.New("pkgbits: readUvarint overflows a 64-bit integer")
|
||||
|
||||
func (r *Decoder) rawVarint() int64 {
|
||||
ux := r.rawUvarint()
|
||||
|
||||
|
@ -303,7 +372,7 @@ func (r *Decoder) Int64() int64 {
|
|||
return r.rawVarint()
|
||||
}
|
||||
|
||||
// Int64 decodes and returns a uint64 value from the element bitstream.
|
||||
// Uint64 decodes and returns a uint64 value from the element bitstream.
|
||||
func (r *Decoder) Uint64() uint64 {
|
||||
r.Sync(SyncUint64)
|
||||
return r.rawUvarint()
|
||||
|
@ -410,8 +479,12 @@ func (r *Decoder) bigFloat() *big.Float {
|
|||
// PeekPkgPath returns the package path for the specified package
|
||||
// index.
|
||||
func (pr *PkgDecoder) PeekPkgPath(idx Index) string {
|
||||
r := pr.NewDecoder(RelocPkg, idx, SyncPkgDef)
|
||||
path := r.String()
|
||||
var path string
|
||||
{
|
||||
r := pr.TempDecoder(RelocPkg, idx, SyncPkgDef)
|
||||
path = r.String()
|
||||
pr.RetireDecoder(&r)
|
||||
}
|
||||
if path == "" {
|
||||
path = pr.pkgPath
|
||||
}
|
||||
|
@ -421,14 +494,26 @@ func (pr *PkgDecoder) PeekPkgPath(idx Index) string {
|
|||
// PeekObj returns the package path, object name, and CodeObj for the
|
||||
// specified object index.
|
||||
func (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) {
|
||||
r := pr.NewDecoder(RelocName, idx, SyncObject1)
|
||||
r.Sync(SyncSym)
|
||||
r.Sync(SyncPkg)
|
||||
path := pr.PeekPkgPath(r.Reloc(RelocPkg))
|
||||
name := r.String()
|
||||
var ridx Index
|
||||
var name string
|
||||
var rcode int
|
||||
{
|
||||
r := pr.TempDecoder(RelocName, idx, SyncObject1)
|
||||
r.Sync(SyncSym)
|
||||
r.Sync(SyncPkg)
|
||||
ridx = r.Reloc(RelocPkg)
|
||||
name = r.String()
|
||||
rcode = r.Code(SyncCodeObj)
|
||||
pr.RetireDecoder(&r)
|
||||
}
|
||||
|
||||
path := pr.PeekPkgPath(ridx)
|
||||
assert(name != "")
|
||||
|
||||
tag := CodeObj(r.Code(SyncCodeObj))
|
||||
tag := CodeObj(rcode)
|
||||
|
||||
return path, name, tag
|
||||
}
|
||||
|
||||
// Version reports the version of the bitstream.
|
||||
func (w *Decoder) Version() Version { return w.common.version }
|
||||
|
|
45
vendor/golang.org/x/tools/internal/pkgbits/encoder.go
generated
vendored
45
vendor/golang.org/x/tools/internal/pkgbits/encoder.go
generated
vendored
|
@ -12,18 +12,15 @@ import (
|
|||
"io"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// currentVersion is the current version number.
|
||||
//
|
||||
// - v0: initial prototype
|
||||
//
|
||||
// - v1: adds the flags uint32 word
|
||||
const currentVersion uint32 = 1
|
||||
|
||||
// A PkgEncoder provides methods for encoding a package's Unified IR
|
||||
// export data.
|
||||
type PkgEncoder struct {
|
||||
// version of the bitstream.
|
||||
version Version
|
||||
|
||||
// elems holds the bitstream for previously encoded elements.
|
||||
elems [numRelocs][]string
|
||||
|
||||
|
@ -47,8 +44,9 @@ func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
|
|||
// export data files, but can help diagnosing desync errors in
|
||||
// higher-level Unified IR reader/writer code. If syncFrames is
|
||||
// negative, then sync markers are omitted entirely.
|
||||
func NewPkgEncoder(syncFrames int) PkgEncoder {
|
||||
func NewPkgEncoder(version Version, syncFrames int) PkgEncoder {
|
||||
return PkgEncoder{
|
||||
version: version,
|
||||
stringsIdx: make(map[string]Index),
|
||||
syncFrames: syncFrames,
|
||||
}
|
||||
|
@ -64,13 +62,15 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {
|
|||
assert(binary.Write(out, binary.LittleEndian, x) == nil)
|
||||
}
|
||||
|
||||
writeUint32(currentVersion)
|
||||
writeUint32(uint32(pw.version))
|
||||
|
||||
var flags uint32
|
||||
if pw.SyncMarkers() {
|
||||
flags |= flagSyncMarkers
|
||||
if pw.version.Has(Flags) {
|
||||
var flags uint32
|
||||
if pw.SyncMarkers() {
|
||||
flags |= flagSyncMarkers
|
||||
}
|
||||
writeUint32(flags)
|
||||
}
|
||||
writeUint32(flags)
|
||||
|
||||
// Write elemEndsEnds.
|
||||
var sum uint32
|
||||
|
@ -159,7 +159,7 @@ type Encoder struct {
|
|||
|
||||
// Flush finalizes the element's bitstream and returns its Index.
|
||||
func (w *Encoder) Flush() Index {
|
||||
var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved
|
||||
var sb strings.Builder
|
||||
|
||||
// Backup the data so we write the relocations at the front.
|
||||
var tmp bytes.Buffer
|
||||
|
@ -189,7 +189,7 @@ func (w *Encoder) Flush() Index {
|
|||
|
||||
func (w *Encoder) checkErr(err error) {
|
||||
if err != nil {
|
||||
errorf("unexpected encoding error: %v", err)
|
||||
panicf("unexpected encoding error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,7 @@ func (w *Encoder) Len(x int) { assert(x >= 0); w.Uint64(uint64(x)) }
|
|||
// Int encodes and writes an int value into the element bitstream.
|
||||
func (w *Encoder) Int(x int) { w.Int64(int64(x)) }
|
||||
|
||||
// Len encodes and writes a uint value into the element bitstream.
|
||||
// Uint encodes and writes a uint value into the element bitstream.
|
||||
func (w *Encoder) Uint(x uint) { w.Uint64(uint64(x)) }
|
||||
|
||||
// Reloc encodes and writes a relocation for the given (section,
|
||||
|
@ -320,8 +320,14 @@ func (w *Encoder) Code(c Code) {
|
|||
// section (if not already present), and then writing a relocation
|
||||
// into the element bitstream.
|
||||
func (w *Encoder) String(s string) {
|
||||
w.StringRef(w.p.StringIdx(s))
|
||||
}
|
||||
|
||||
// StringRef writes a reference to the given index, which must be a
|
||||
// previously encoded string value.
|
||||
func (w *Encoder) StringRef(idx Index) {
|
||||
w.Sync(SyncString)
|
||||
w.Reloc(RelocString, w.p.StringIdx(s))
|
||||
w.Reloc(RelocString, idx)
|
||||
}
|
||||
|
||||
// Strings encodes and writes a variable-length slice of strings into
|
||||
|
@ -348,7 +354,7 @@ func (w *Encoder) Value(val constant.Value) {
|
|||
func (w *Encoder) scalar(val constant.Value) {
|
||||
switch v := constant.Val(val).(type) {
|
||||
default:
|
||||
errorf("unhandled %v (%v)", val, val.Kind())
|
||||
panicf("unhandled %v (%v)", val, val.Kind())
|
||||
case bool:
|
||||
w.Code(ValBool)
|
||||
w.Bool(v)
|
||||
|
@ -381,3 +387,6 @@ func (w *Encoder) bigFloat(v *big.Float) {
|
|||
b := v.Append(nil, 'p', -1)
|
||||
w.String(string(b)) // TODO: More efficient encoding.
|
||||
}
|
||||
|
||||
// Version reports the version of the bitstream.
|
||||
func (w *Encoder) Version() Version { return w.p.version }
|
||||
|
|
21
vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go
generated
vendored
21
vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.7
|
||||
// +build !go1.7
|
||||
|
||||
// TODO(mdempsky): Remove after #44505 is resolved
|
||||
|
||||
package pkgbits
|
||||
|
||||
import "runtime"
|
||||
|
||||
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
||||
for _, pc := range pcs {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
file, line := fn.FileLine(pc)
|
||||
|
||||
visit(file, line, fn.Name(), pc-fn.Entry())
|
||||
}
|
||||
}
|
28
vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go
generated
vendored
28
vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go
generated
vendored
|
@ -1,28 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7
|
||||
// +build go1.7
|
||||
|
||||
package pkgbits
|
||||
|
||||
import "runtime"
|
||||
|
||||
// walkFrames calls visit for each call frame represented by pcs.
|
||||
//
|
||||
// pcs should be a slice of PCs, as returned by runtime.Callers.
|
||||
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
||||
if len(pcs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
frames := runtime.CallersFrames(pcs)
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry)
|
||||
if !more {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
2
vendor/golang.org/x/tools/internal/pkgbits/support.go
generated
vendored
2
vendor/golang.org/x/tools/internal/pkgbits/support.go
generated
vendored
|
@ -12,6 +12,6 @@ func assert(b bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func errorf(format string, args ...interface{}) {
|
||||
func panicf(format string, args ...any) {
|
||||
panic(fmt.Errorf(format, args...))
|
||||
}
|
||||
|
|
23
vendor/golang.org/x/tools/internal/pkgbits/sync.go
generated
vendored
23
vendor/golang.org/x/tools/internal/pkgbits/sync.go
generated
vendored
|
@ -6,6 +6,7 @@ package pkgbits
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -23,6 +24,24 @@ func fmtFrames(pcs ...uintptr) []string {
|
|||
|
||||
type frameVisitor func(file string, line int, name string, offset uintptr)
|
||||
|
||||
// walkFrames calls visit for each call frame represented by pcs.
|
||||
//
|
||||
// pcs should be a slice of PCs, as returned by runtime.Callers.
|
||||
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
||||
if len(pcs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
frames := runtime.CallersFrames(pcs)
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry)
|
||||
if !more {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SyncMarker is an enum type that represents markers that may be
|
||||
// written to export data to ensure the reader and writer stay
|
||||
// synchronized.
|
||||
|
@ -110,4 +129,8 @@ const (
|
|||
SyncStmtsEnd
|
||||
SyncLabel
|
||||
SyncOptLabel
|
||||
|
||||
SyncMultiExpr
|
||||
SyncRType
|
||||
SyncConvRTTI
|
||||
)
|
||||
|
|
7
vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go
generated
vendored
7
vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go
generated
vendored
|
@ -74,11 +74,14 @@ func _() {
|
|||
_ = x[SyncStmtsEnd-64]
|
||||
_ = x[SyncLabel-65]
|
||||
_ = x[SyncOptLabel-66]
|
||||
_ = x[SyncMultiExpr-67]
|
||||
_ = x[SyncRType-68]
|
||||
_ = x[SyncConvRTTI-69]
|
||||
}
|
||||
|
||||
const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabel"
|
||||
const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabelMultiExprRTypeConvRTTI"
|
||||
|
||||
var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458}
|
||||
var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458, 467, 472, 480}
|
||||
|
||||
func (i SyncMarker) String() string {
|
||||
i -= 1
|
||||
|
|
85
vendor/golang.org/x/tools/internal/pkgbits/version.go
generated
vendored
Normal file
85
vendor/golang.org/x/tools/internal/pkgbits/version.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pkgbits
|
||||
|
||||
// Version indicates a version of a unified IR bitstream.
|
||||
// Each Version indicates the addition, removal, or change of
|
||||
// new data in the bitstream.
|
||||
//
|
||||
// These are serialized to disk and the interpretation remains fixed.
|
||||
type Version uint32
|
||||
|
||||
const (
|
||||
// V0: initial prototype.
|
||||
//
|
||||
// All data that is not assigned a Field is in version V0
|
||||
// and has not been deprecated.
|
||||
V0 Version = iota
|
||||
|
||||
// V1: adds the Flags uint32 word
|
||||
V1
|
||||
|
||||
// V2: removes unused legacy fields and supports type parameters for aliases.
|
||||
// - remove the legacy "has init" bool from the public root
|
||||
// - remove obj's "derived func instance" bool
|
||||
// - add a TypeParamNames field to ObjAlias
|
||||
// - remove derived info "needed" bool
|
||||
V2
|
||||
|
||||
numVersions = iota
|
||||
)
|
||||
|
||||
// Field denotes a unit of data in the serialized unified IR bitstream.
|
||||
// It is conceptually a like field in a structure.
|
||||
//
|
||||
// We only really need Fields when the data may or may not be present
|
||||
// in a stream based on the Version of the bitstream.
|
||||
//
|
||||
// Unlike much of pkgbits, Fields are not serialized and
|
||||
// can change values as needed.
|
||||
type Field int
|
||||
|
||||
const (
|
||||
// Flags in a uint32 in the header of a bitstream
|
||||
// that is used to indicate whether optional features are enabled.
|
||||
Flags Field = iota
|
||||
|
||||
// Deprecated: HasInit was a bool indicating whether a package
|
||||
// has any init functions.
|
||||
HasInit
|
||||
|
||||
// Deprecated: DerivedFuncInstance was a bool indicating
|
||||
// whether an object was a function instance.
|
||||
DerivedFuncInstance
|
||||
|
||||
// ObjAlias has a list of TypeParamNames.
|
||||
AliasTypeParamNames
|
||||
|
||||
// Deprecated: DerivedInfoNeeded was a bool indicating
|
||||
// whether a type was a derived type.
|
||||
DerivedInfoNeeded
|
||||
|
||||
numFields = iota
|
||||
)
|
||||
|
||||
// introduced is the version a field was added.
|
||||
var introduced = [numFields]Version{
|
||||
Flags: V1,
|
||||
AliasTypeParamNames: V2,
|
||||
}
|
||||
|
||||
// removed is the version a field was removed in or 0 for fields
|
||||
// that have not yet been deprecated.
|
||||
// (So removed[f]-1 is the last version it is included in.)
|
||||
var removed = [numFields]Version{
|
||||
HasInit: V2,
|
||||
DerivedFuncInstance: V2,
|
||||
DerivedInfoNeeded: V2,
|
||||
}
|
||||
|
||||
// Has reports whether field f is present in a bitstream at version v.
|
||||
func (v Version) Has(f Field) bool {
|
||||
return introduced[f] <= v && (v < removed[f] || removed[f] == V0)
|
||||
}
|
17650
vendor/golang.org/x/tools/internal/stdlib/manifest.go
generated
vendored
Normal file
17650
vendor/golang.org/x/tools/internal/stdlib/manifest.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
97
vendor/golang.org/x/tools/internal/stdlib/stdlib.go
generated
vendored
Normal file
97
vendor/golang.org/x/tools/internal/stdlib/stdlib.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run generate.go
|
||||
|
||||
// Package stdlib provides a table of all exported symbols in the
|
||||
// standard library, along with the version at which they first
|
||||
// appeared.
|
||||
package stdlib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Symbol struct {
|
||||
Name string
|
||||
Kind Kind
|
||||
Version Version // Go version that first included the symbol
|
||||
}
|
||||
|
||||
// A Kind indicates the kind of a symbol:
|
||||
// function, variable, constant, type, and so on.
|
||||
type Kind int8
|
||||
|
||||
const (
|
||||
Invalid Kind = iota // Example name:
|
||||
Type // "Buffer"
|
||||
Func // "Println"
|
||||
Var // "EOF"
|
||||
Const // "Pi"
|
||||
Field // "Point.X"
|
||||
Method // "(*Buffer).Grow"
|
||||
)
|
||||
|
||||
func (kind Kind) String() string {
|
||||
return [...]string{
|
||||
Invalid: "invalid",
|
||||
Type: "type",
|
||||
Func: "func",
|
||||
Var: "var",
|
||||
Const: "const",
|
||||
Field: "field",
|
||||
Method: "method",
|
||||
}[kind]
|
||||
}
|
||||
|
||||
// A Version represents a version of Go of the form "go1.%d".
|
||||
type Version int8
|
||||
|
||||
// String returns a version string of the form "go1.23", without allocating.
|
||||
func (v Version) String() string { return versions[v] }
|
||||
|
||||
var versions [30]string // (increase constant as needed)
|
||||
|
||||
func init() {
|
||||
for i := range versions {
|
||||
versions[i] = fmt.Sprintf("go1.%d", i)
|
||||
}
|
||||
}
|
||||
|
||||
// HasPackage reports whether the specified package path is part of
|
||||
// the standard library's public API.
|
||||
func HasPackage(path string) bool {
|
||||
_, ok := PackageSymbols[path]
|
||||
return ok
|
||||
}
|
||||
|
||||
// SplitField splits the field symbol name into type and field
|
||||
// components. It must be called only on Field symbols.
|
||||
//
|
||||
// Example: "File.Package" -> ("File", "Package")
|
||||
func (sym *Symbol) SplitField() (typename, name string) {
|
||||
if sym.Kind != Field {
|
||||
panic("not a field")
|
||||
}
|
||||
typename, name, _ = strings.Cut(sym.Name, ".")
|
||||
return
|
||||
}
|
||||
|
||||
// SplitMethod splits the method symbol name into pointer, receiver,
|
||||
// and method components. It must be called only on Method symbols.
|
||||
//
|
||||
// Example: "(*Buffer).Grow" -> (true, "Buffer", "Grow")
|
||||
func (sym *Symbol) SplitMethod() (ptr bool, recv, name string) {
|
||||
if sym.Kind != Method {
|
||||
panic("not a method")
|
||||
}
|
||||
recv, name, _ = strings.Cut(sym.Name, ".")
|
||||
recv = recv[len("(") : len(recv)-len(")")]
|
||||
ptr = recv[0] == '*'
|
||||
if ptr {
|
||||
recv = recv[len("*"):]
|
||||
}
|
||||
return
|
||||
}
|
127
vendor/golang.org/x/tools/internal/typeparams/common.go
generated
vendored
127
vendor/golang.org/x/tools/internal/typeparams/common.go
generated
vendored
|
@ -2,20 +2,10 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package typeparams contains common utilities for writing tools that interact
|
||||
// with generic Go code, as introduced with Go 1.18.
|
||||
//
|
||||
// Many of the types and functions in this package are proxies for the new APIs
|
||||
// introduced in the standard library with Go 1.18. For example, the
|
||||
// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec
|
||||
// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go
|
||||
// versions older than 1.18 these helpers are implemented as stubs, allowing
|
||||
// users of this package to write code that handles generic constructs inline,
|
||||
// even if the Go version being used to compile does not support generics.
|
||||
//
|
||||
// Additionally, this package contains common utilities for working with the
|
||||
// new generic constructs, to supplement the standard library APIs. Notably,
|
||||
// the StructuralTerms API computes a minimal representation of the structural
|
||||
// Package typeparams contains common utilities for writing tools that
|
||||
// interact with generic Go code, as introduced with Go 1.18. It
|
||||
// supplements the standard library APIs. Notably, the StructuralTerms
|
||||
// API computes a minimal representation of the structural
|
||||
// restrictions on a type parameter.
|
||||
//
|
||||
// An external version of these APIs is available in the
|
||||
|
@ -41,7 +31,7 @@ func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Ex
|
|||
switch e := n.(type) {
|
||||
case *ast.IndexExpr:
|
||||
return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
|
||||
case *IndexListExpr:
|
||||
case *ast.IndexListExpr:
|
||||
return e.X, e.Lbrack, e.Indices, e.Rbrack
|
||||
}
|
||||
return nil, token.NoPos, nil, token.NoPos
|
||||
|
@ -62,7 +52,7 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke
|
|||
Rbrack: rbrack,
|
||||
}
|
||||
default:
|
||||
return &IndexListExpr{
|
||||
return &ast.IndexListExpr{
|
||||
X: x,
|
||||
Lbrack: lbrack,
|
||||
Indices: indices,
|
||||
|
@ -71,109 +61,8 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke
|
|||
}
|
||||
}
|
||||
|
||||
// IsTypeParam reports whether t is a type parameter.
|
||||
// IsTypeParam reports whether t is a type parameter (or an alias of one).
|
||||
func IsTypeParam(t types.Type) bool {
|
||||
_, ok := t.(*TypeParam)
|
||||
_, ok := types.Unalias(t).(*types.TypeParam)
|
||||
return ok
|
||||
}
|
||||
|
||||
// OriginMethod returns the origin method associated with the method fn.
|
||||
// For methods on a non-generic receiver base type, this is just
|
||||
// fn. However, for methods with a generic receiver, OriginMethod returns the
|
||||
// corresponding method in the method set of the origin type.
|
||||
//
|
||||
// As a special case, if fn is not a method (has no receiver), OriginMethod
|
||||
// returns fn.
|
||||
func OriginMethod(fn *types.Func) *types.Func {
|
||||
recv := fn.Type().(*types.Signature).Recv()
|
||||
if recv == nil {
|
||||
|
||||
return fn
|
||||
}
|
||||
base := recv.Type()
|
||||
p, isPtr := base.(*types.Pointer)
|
||||
if isPtr {
|
||||
base = p.Elem()
|
||||
}
|
||||
named, isNamed := base.(*types.Named)
|
||||
if !isNamed {
|
||||
// Receiver is a *types.Interface.
|
||||
return fn
|
||||
}
|
||||
if ForNamed(named).Len() == 0 {
|
||||
// Receiver base has no type parameters, so we can avoid the lookup below.
|
||||
return fn
|
||||
}
|
||||
orig := NamedTypeOrigin(named)
|
||||
gfn, _, _ := types.LookupFieldOrMethod(orig, true, fn.Pkg(), fn.Name())
|
||||
return gfn.(*types.Func)
|
||||
}
|
||||
|
||||
// GenericAssignableTo is a generalization of types.AssignableTo that
|
||||
// implements the following rule for uninstantiated generic types:
|
||||
//
|
||||
// If V and T are generic named types, then V is considered assignable to T if,
|
||||
// for every possible instantation of V[A_1, ..., A_N], the instantiation
|
||||
// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N].
|
||||
//
|
||||
// If T has structural constraints, they must be satisfied by V.
|
||||
//
|
||||
// For example, consider the following type declarations:
|
||||
//
|
||||
// type Interface[T any] interface {
|
||||
// Accept(T)
|
||||
// }
|
||||
//
|
||||
// type Container[T any] struct {
|
||||
// Element T
|
||||
// }
|
||||
//
|
||||
// func (c Container[T]) Accept(t T) { c.Element = t }
|
||||
//
|
||||
// In this case, GenericAssignableTo reports that instantiations of Container
|
||||
// are assignable to the corresponding instantiation of Interface.
|
||||
func GenericAssignableTo(ctxt *Context, V, T types.Type) bool {
|
||||
// If V and T are not both named, or do not have matching non-empty type
|
||||
// parameter lists, fall back on types.AssignableTo.
|
||||
|
||||
VN, Vnamed := V.(*types.Named)
|
||||
TN, Tnamed := T.(*types.Named)
|
||||
if !Vnamed || !Tnamed {
|
||||
return types.AssignableTo(V, T)
|
||||
}
|
||||
|
||||
vtparams := ForNamed(VN)
|
||||
ttparams := ForNamed(TN)
|
||||
if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || NamedTypeArgs(VN).Len() != 0 || NamedTypeArgs(TN).Len() != 0 {
|
||||
return types.AssignableTo(V, T)
|
||||
}
|
||||
|
||||
// V and T have the same (non-zero) number of type params. Instantiate both
|
||||
// with the type parameters of V. This must always succeed for V, and will
|
||||
// succeed for T if and only if the type set of each type parameter of V is a
|
||||
// subset of the type set of the corresponding type parameter of T, meaning
|
||||
// that every instantiation of V corresponds to a valid instantiation of T.
|
||||
|
||||
// Minor optimization: ensure we share a context across the two
|
||||
// instantiations below.
|
||||
if ctxt == nil {
|
||||
ctxt = NewContext()
|
||||
}
|
||||
|
||||
var targs []types.Type
|
||||
for i := 0; i < vtparams.Len(); i++ {
|
||||
targs = append(targs, vtparams.At(i))
|
||||
}
|
||||
|
||||
vinst, err := Instantiate(ctxt, V, targs, true)
|
||||
if err != nil {
|
||||
panic("type parameters should satisfy their own constraints")
|
||||
}
|
||||
|
||||
tinst, err := Instantiate(ctxt, T, targs, true)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return types.AssignableTo(vinst, tinst)
|
||||
}
|
||||
|
|
58
vendor/golang.org/x/tools/internal/typeparams/coretype.go
generated
vendored
58
vendor/golang.org/x/tools/internal/typeparams/coretype.go
generated
vendored
|
@ -5,6 +5,7 @@
|
|||
package typeparams
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
|
@ -17,7 +18,7 @@ func CoreType(T types.Type) types.Type {
|
|||
return U // for non-interface types,
|
||||
}
|
||||
|
||||
terms, err := _NormalTerms(U)
|
||||
terms, err := NormalTerms(U)
|
||||
if len(terms) == 0 || err != nil {
|
||||
// len(terms) -> empty type set of interface.
|
||||
// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.
|
||||
|
@ -63,7 +64,7 @@ func CoreType(T types.Type) types.Type {
|
|||
return ch
|
||||
}
|
||||
|
||||
// _NormalTerms returns a slice of terms representing the normalized structural
|
||||
// NormalTerms returns a slice of terms representing the normalized structural
|
||||
// type restrictions of a type, if any.
|
||||
//
|
||||
// For all types other than *types.TypeParam, *types.Interface, and
|
||||
|
@ -81,42 +82,69 @@ func CoreType(T types.Type) types.Type {
|
|||
// restrictions may be arbitrarily complex. For example, consider the
|
||||
// following:
|
||||
//
|
||||
// type A interface{ ~string|~[]byte }
|
||||
// type A interface{ ~string|~[]byte }
|
||||
//
|
||||
// type B interface{ int|string }
|
||||
// type B interface{ int|string }
|
||||
//
|
||||
// type C interface { ~string|~int }
|
||||
// type C interface { ~string|~int }
|
||||
//
|
||||
// type T[P interface{ A|B; C }] int
|
||||
// type T[P interface{ A|B; C }] int
|
||||
//
|
||||
// In this example, the structural type restriction of P is ~string|int: A|B
|
||||
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
||||
// which when intersected with C (~string|~int) yields ~string|int.
|
||||
//
|
||||
// _NormalTerms computes these expansions and reductions, producing a
|
||||
// NormalTerms computes these expansions and reductions, producing a
|
||||
// "normalized" form of the embeddings. A structural restriction is normalized
|
||||
// if it is a single union containing no interface terms, and is minimal in the
|
||||
// sense that removing any term changes the set of types satisfying the
|
||||
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
||||
// is exactly one such normalized form.
|
||||
//
|
||||
// Because the minimal representation always takes this form, _NormalTerms
|
||||
// Because the minimal representation always takes this form, NormalTerms
|
||||
// returns a slice of tilde terms corresponding to the terms of the union in
|
||||
// the normalized structural restriction. An error is returned if the type is
|
||||
// invalid, exceeds complexity bounds, or has an empty type set. In the latter
|
||||
// case, _NormalTerms returns ErrEmptyTypeSet.
|
||||
// case, NormalTerms returns ErrEmptyTypeSet.
|
||||
//
|
||||
// _NormalTerms makes no guarantees about the order of terms, except that it
|
||||
// NormalTerms makes no guarantees about the order of terms, except that it
|
||||
// is deterministic.
|
||||
func _NormalTerms(typ types.Type) ([]*Term, error) {
|
||||
switch typ := typ.(type) {
|
||||
case *TypeParam:
|
||||
func NormalTerms(typ types.Type) ([]*types.Term, error) {
|
||||
switch typ := typ.Underlying().(type) {
|
||||
case *types.TypeParam:
|
||||
return StructuralTerms(typ)
|
||||
case *Union:
|
||||
case *types.Union:
|
||||
return UnionTermSet(typ)
|
||||
case *types.Interface:
|
||||
return InterfaceTermSet(typ)
|
||||
default:
|
||||
return []*Term{NewTerm(false, typ)}, nil
|
||||
return []*types.Term{types.NewTerm(false, typ)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Deref returns the type of the variable pointed to by t,
|
||||
// if t's core type is a pointer; otherwise it returns t.
|
||||
//
|
||||
// Do not assume that Deref(T)==T implies T is not a pointer:
|
||||
// consider "type T *T", for example.
|
||||
//
|
||||
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||
// creates an import cycle. Move there when we melt this package down.
|
||||
func Deref(t types.Type) types.Type {
|
||||
if ptr, ok := CoreType(t).(*types.Pointer); ok {
|
||||
return ptr.Elem()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// MustDeref returns the type of the variable pointed to by t.
|
||||
// It panics if t's core type is not a pointer.
|
||||
//
|
||||
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||
// creates an import cycle. Move there when we melt this package down.
|
||||
func MustDeref(t types.Type) types.Type {
|
||||
if ptr, ok := CoreType(t).(*types.Pointer); ok {
|
||||
return ptr.Elem()
|
||||
}
|
||||
panic(fmt.Sprintf("%v is not a pointer", t))
|
||||
}
|
||||
|
|
12
vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go
generated
vendored
12
vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go
generated
vendored
|
@ -1,12 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
// Enabled reports whether type parameters are enabled in the current build
|
||||
// environment.
|
||||
const Enabled = false
|
15
vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go
generated
vendored
15
vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go
generated
vendored
|
@ -1,15 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
// Note: this constant is in a separate file as this is the only acceptable
|
||||
// diff between the <1.18 API of this package and the 1.18 API.
|
||||
|
||||
// Enabled reports whether type parameters are enabled in the current build
|
||||
// environment.
|
||||
const Enabled = true
|
131
vendor/golang.org/x/tools/internal/typeparams/free.go
generated
vendored
Normal file
131
vendor/golang.org/x/tools/internal/typeparams/free.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/internal/aliases"
|
||||
)
|
||||
|
||||
// Free is a memoization of the set of free type parameters within a
|
||||
// type. It makes a sequence of calls to [Free.Has] for overlapping
|
||||
// types more efficient. The zero value is ready for use.
|
||||
//
|
||||
// NOTE: Adapted from go/types/infer.go. If it is later exported, factor.
|
||||
type Free struct {
|
||||
seen map[types.Type]bool
|
||||
}
|
||||
|
||||
// Has reports whether the specified type has a free type parameter.
|
||||
func (w *Free) Has(typ types.Type) (res bool) {
|
||||
// detect cycles
|
||||
if x, ok := w.seen[typ]; ok {
|
||||
return x
|
||||
}
|
||||
if w.seen == nil {
|
||||
w.seen = make(map[types.Type]bool)
|
||||
}
|
||||
w.seen[typ] = false
|
||||
defer func() {
|
||||
w.seen[typ] = res
|
||||
}()
|
||||
|
||||
switch t := typ.(type) {
|
||||
case nil, *types.Basic: // TODO(gri) should nil be handled here?
|
||||
break
|
||||
|
||||
case *types.Alias:
|
||||
if aliases.TypeParams(t).Len() > aliases.TypeArgs(t).Len() {
|
||||
return true // This is an uninstantiated Alias.
|
||||
}
|
||||
// The expansion of an alias can have free type parameters,
|
||||
// whether or not the alias itself has type parameters:
|
||||
//
|
||||
// func _[K comparable]() {
|
||||
// type Set = map[K]bool // free(Set) = {K}
|
||||
// type MapTo[V] = map[K]V // free(Map[foo]) = {V}
|
||||
// }
|
||||
//
|
||||
// So, we must Unalias.
|
||||
return w.Has(types.Unalias(t))
|
||||
|
||||
case *types.Array:
|
||||
return w.Has(t.Elem())
|
||||
|
||||
case *types.Slice:
|
||||
return w.Has(t.Elem())
|
||||
|
||||
case *types.Struct:
|
||||
for i, n := 0, t.NumFields(); i < n; i++ {
|
||||
if w.Has(t.Field(i).Type()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *types.Pointer:
|
||||
return w.Has(t.Elem())
|
||||
|
||||
case *types.Tuple:
|
||||
n := t.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
if w.Has(t.At(i).Type()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *types.Signature:
|
||||
// t.tparams may not be nil if we are looking at a signature
|
||||
// of a generic function type (or an interface method) that is
|
||||
// part of the type we're testing. We don't care about these type
|
||||
// parameters.
|
||||
// Similarly, the receiver of a method may declare (rather than
|
||||
// use) type parameters, we don't care about those either.
|
||||
// Thus, we only need to look at the input and result parameters.
|
||||
return w.Has(t.Params()) || w.Has(t.Results())
|
||||
|
||||
case *types.Interface:
|
||||
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||
if w.Has(t.Method(i).Type()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
terms, err := InterfaceTermSet(t)
|
||||
if err != nil {
|
||||
return false // ill typed
|
||||
}
|
||||
for _, term := range terms {
|
||||
if w.Has(term.Type()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *types.Map:
|
||||
return w.Has(t.Key()) || w.Has(t.Elem())
|
||||
|
||||
case *types.Chan:
|
||||
return w.Has(t.Elem())
|
||||
|
||||
case *types.Named:
|
||||
args := t.TypeArgs()
|
||||
if params := t.TypeParams(); params.Len() > args.Len() {
|
||||
return true // this is an uninstantiated named type.
|
||||
}
|
||||
for i, n := 0, args.Len(); i < n; i++ {
|
||||
if w.Has(args.At(i)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return w.Has(t.Underlying()) // recurse for types local to parameterized functions
|
||||
|
||||
case *types.TypeParam:
|
||||
return true
|
||||
|
||||
default:
|
||||
panic(t) // unreachable
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
20
vendor/golang.org/x/tools/internal/typeparams/normalize.go
generated
vendored
20
vendor/golang.org/x/tools/internal/typeparams/normalize.go
generated
vendored
|
@ -60,7 +60,7 @@ var ErrEmptyTypeSet = errors.New("empty type set")
|
|||
//
|
||||
// StructuralTerms makes no guarantees about the order of terms, except that it
|
||||
// is deterministic.
|
||||
func StructuralTerms(tparam *TypeParam) ([]*Term, error) {
|
||||
func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) {
|
||||
constraint := tparam.Constraint()
|
||||
if constraint == nil {
|
||||
return nil, fmt.Errorf("%s has nil constraint", tparam)
|
||||
|
@ -78,7 +78,7 @@ func StructuralTerms(tparam *TypeParam) ([]*Term, error) {
|
|||
//
|
||||
// See the documentation of StructuralTerms for more information on
|
||||
// normalization.
|
||||
func InterfaceTermSet(iface *types.Interface) ([]*Term, error) {
|
||||
func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) {
|
||||
return computeTermSet(iface)
|
||||
}
|
||||
|
||||
|
@ -88,11 +88,11 @@ func InterfaceTermSet(iface *types.Interface) ([]*Term, error) {
|
|||
//
|
||||
// See the documentation of StructuralTerms for more information on
|
||||
// normalization.
|
||||
func UnionTermSet(union *Union) ([]*Term, error) {
|
||||
func UnionTermSet(union *types.Union) ([]*types.Term, error) {
|
||||
return computeTermSet(union)
|
||||
}
|
||||
|
||||
func computeTermSet(typ types.Type) ([]*Term, error) {
|
||||
func computeTermSet(typ types.Type) ([]*types.Term, error) {
|
||||
tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -103,9 +103,9 @@ func computeTermSet(typ types.Type) ([]*Term, error) {
|
|||
if tset.terms.isAll() {
|
||||
return nil, nil
|
||||
}
|
||||
var terms []*Term
|
||||
var terms []*types.Term
|
||||
for _, term := range tset.terms {
|
||||
terms = append(terms, NewTerm(term.tilde, term.typ))
|
||||
terms = append(terms, types.NewTerm(term.tilde, term.typ))
|
||||
}
|
||||
return terms, nil
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||
tset.terms = allTermlist
|
||||
for i := 0; i < u.NumEmbeddeds(); i++ {
|
||||
embedded := u.EmbeddedType(i)
|
||||
if _, ok := embedded.Underlying().(*TypeParam); ok {
|
||||
if _, ok := embedded.Underlying().(*types.TypeParam); ok {
|
||||
return nil, fmt.Errorf("invalid embedded type %T", embedded)
|
||||
}
|
||||
tset2, err := computeTermSetInternal(embedded, seen, depth+1)
|
||||
|
@ -171,7 +171,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||
}
|
||||
tset.terms = tset.terms.intersect(tset2.terms)
|
||||
}
|
||||
case *Union:
|
||||
case *types.Union:
|
||||
// The term set of a union is the union of term sets of its terms.
|
||||
tset.terms = nil
|
||||
for i := 0; i < u.Len(); i++ {
|
||||
|
@ -184,7 +184,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||
return nil, err
|
||||
}
|
||||
terms = tset2.terms
|
||||
case *TypeParam, *Union:
|
||||
case *types.TypeParam, *types.Union:
|
||||
// A stand-alone type parameter or union is not permitted as union
|
||||
// term.
|
||||
return nil, fmt.Errorf("invalid union term %T", t)
|
||||
|
@ -199,7 +199,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||
return nil, fmt.Errorf("exceeded max term count %d", maxTermCount)
|
||||
}
|
||||
}
|
||||
case *TypeParam:
|
||||
case *types.TypeParam:
|
||||
panic("unreachable")
|
||||
default:
|
||||
// For all other types, the term set is just a single non-tilde term
|
||||
|
|
2
vendor/golang.org/x/tools/internal/typeparams/termlist.go
generated
vendored
2
vendor/golang.org/x/tools/internal/typeparams/termlist.go
generated
vendored
|
@ -30,7 +30,7 @@ func (xl termlist) String() string {
|
|||
var buf bytes.Buffer
|
||||
for i, x := range xl {
|
||||
if i > 0 {
|
||||
buf.WriteString(" ∪ ")
|
||||
buf.WriteString(" | ")
|
||||
}
|
||||
buf.WriteString(x.String())
|
||||
}
|
||||
|
|
197
vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
generated
vendored
197
vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
generated
vendored
|
@ -1,197 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func unsupported() {
|
||||
panic("type parameters are unsupported at this go version")
|
||||
}
|
||||
|
||||
// IndexListExpr is a placeholder type, as type parameters are not supported at
|
||||
// this Go version. Its methods panic on use.
|
||||
type IndexListExpr struct {
|
||||
ast.Expr
|
||||
X ast.Expr // expression
|
||||
Lbrack token.Pos // position of "["
|
||||
Indices []ast.Expr // index expressions
|
||||
Rbrack token.Pos // position of "]"
|
||||
}
|
||||
|
||||
// ForTypeSpec returns an empty field list, as type parameters on not supported
|
||||
// at this Go version.
|
||||
func ForTypeSpec(*ast.TypeSpec) *ast.FieldList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForFuncType returns an empty field list, as type parameters are not
|
||||
// supported at this Go version.
|
||||
func ForFuncType(*ast.FuncType) *ast.FieldList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TypeParam is a placeholder type, as type parameters are not supported at
|
||||
// this Go version. Its methods panic on use.
|
||||
type TypeParam struct{ types.Type }
|
||||
|
||||
func (*TypeParam) Index() int { unsupported(); return 0 }
|
||||
func (*TypeParam) Constraint() types.Type { unsupported(); return nil }
|
||||
func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil }
|
||||
|
||||
// TypeParamList is a placeholder for an empty type parameter list.
|
||||
type TypeParamList struct{}
|
||||
|
||||
func (*TypeParamList) Len() int { return 0 }
|
||||
func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil }
|
||||
|
||||
// TypeList is a placeholder for an empty type list.
|
||||
type TypeList struct{}
|
||||
|
||||
func (*TypeList) Len() int { return 0 }
|
||||
func (*TypeList) At(int) types.Type { unsupported(); return nil }
|
||||
|
||||
// NewTypeParam is unsupported at this Go version, and panics.
|
||||
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
|
||||
unsupported()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTypeParamConstraint is unsupported at this Go version, and panics.
|
||||
func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
// NewSignatureType calls types.NewSignature, panicking if recvTypeParams or
|
||||
// typeParams is non-empty.
|
||||
func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
|
||||
if len(recvTypeParams) != 0 || len(typeParams) != 0 {
|
||||
panic("signatures cannot have type parameters at this Go version")
|
||||
}
|
||||
return types.NewSignature(recv, params, results, variadic)
|
||||
}
|
||||
|
||||
// ForSignature returns an empty slice.
|
||||
func ForSignature(*types.Signature) *TypeParamList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecvTypeParams returns a nil slice.
|
||||
func RecvTypeParams(sig *types.Signature) *TypeParamList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsComparable returns false, as no interfaces are type-restricted at this Go
|
||||
// version.
|
||||
func IsComparable(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsMethodSet returns true, as no interfaces are type-restricted at this Go
|
||||
// version.
|
||||
func IsMethodSet(*types.Interface) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsImplicit returns false, as no interfaces are implicit at this Go version.
|
||||
func IsImplicit(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// MarkImplicit does nothing, because this Go version does not have implicit
|
||||
// interfaces.
|
||||
func MarkImplicit(*types.Interface) {}
|
||||
|
||||
// ForNamed returns an empty type parameter list, as type parameters are not
|
||||
// supported at this Go version.
|
||||
func ForNamed(*types.Named) *TypeParamList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetForNamed panics if tparams is non-empty.
|
||||
func SetForNamed(_ *types.Named, tparams []*TypeParam) {
|
||||
if len(tparams) > 0 {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
// NamedTypeArgs returns nil.
|
||||
func NamedTypeArgs(*types.Named) *TypeList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NamedTypeOrigin is the identity method at this Go version.
|
||||
func NamedTypeOrigin(named *types.Named) types.Type {
|
||||
return named
|
||||
}
|
||||
|
||||
// Term holds information about a structural type restriction.
|
||||
type Term struct {
|
||||
tilde bool
|
||||
typ types.Type
|
||||
}
|
||||
|
||||
func (m *Term) Tilde() bool { return m.tilde }
|
||||
func (m *Term) Type() types.Type { return m.typ }
|
||||
func (m *Term) String() string {
|
||||
pre := ""
|
||||
if m.tilde {
|
||||
pre = "~"
|
||||
}
|
||||
return pre + m.typ.String()
|
||||
}
|
||||
|
||||
// NewTerm is unsupported at this Go version, and panics.
|
||||
func NewTerm(tilde bool, typ types.Type) *Term {
|
||||
return &Term{tilde, typ}
|
||||
}
|
||||
|
||||
// Union is a placeholder type, as type parameters are not supported at this Go
|
||||
// version. Its methods panic on use.
|
||||
type Union struct{ types.Type }
|
||||
|
||||
func (*Union) Len() int { return 0 }
|
||||
func (*Union) Term(i int) *Term { unsupported(); return nil }
|
||||
|
||||
// NewUnion is unsupported at this Go version, and panics.
|
||||
func NewUnion(terms []*Term) *Union {
|
||||
unsupported()
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitInstanceInfo is a noop at this Go version.
|
||||
func InitInstanceInfo(*types.Info) {}
|
||||
|
||||
// Instance is a placeholder type, as type parameters are not supported at this
|
||||
// Go version.
|
||||
type Instance struct {
|
||||
TypeArgs *TypeList
|
||||
Type types.Type
|
||||
}
|
||||
|
||||
// GetInstances returns a nil map, as type parameters are not supported at this
|
||||
// Go version.
|
||||
func GetInstances(info *types.Info) map[*ast.Ident]Instance { return nil }
|
||||
|
||||
// Context is a placeholder type, as type parameters are not supported at
|
||||
// this Go version.
|
||||
type Context struct{}
|
||||
|
||||
// NewContext returns a placeholder Context instance.
|
||||
func NewContext() *Context {
|
||||
return &Context{}
|
||||
}
|
||||
|
||||
// Instantiate is unsupported on this Go version, and panics.
|
||||
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
|
||||
unsupported()
|
||||
return nil, nil
|
||||
}
|
151
vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
generated
vendored
151
vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
generated
vendored
|
@ -1,151 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// IndexListExpr is an alias for ast.IndexListExpr.
|
||||
type IndexListExpr = ast.IndexListExpr
|
||||
|
||||
// ForTypeSpec returns n.TypeParams.
|
||||
func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
return n.TypeParams
|
||||
}
|
||||
|
||||
// ForFuncType returns n.TypeParams.
|
||||
func ForFuncType(n *ast.FuncType) *ast.FieldList {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
return n.TypeParams
|
||||
}
|
||||
|
||||
// TypeParam is an alias for types.TypeParam
|
||||
type TypeParam = types.TypeParam
|
||||
|
||||
// TypeParamList is an alias for types.TypeParamList
|
||||
type TypeParamList = types.TypeParamList
|
||||
|
||||
// TypeList is an alias for types.TypeList
|
||||
type TypeList = types.TypeList
|
||||
|
||||
// NewTypeParam calls types.NewTypeParam.
|
||||
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
|
||||
return types.NewTypeParam(name, constraint)
|
||||
}
|
||||
|
||||
// SetTypeParamConstraint calls tparam.SetConstraint(constraint).
|
||||
func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
|
||||
tparam.SetConstraint(constraint)
|
||||
}
|
||||
|
||||
// NewSignatureType calls types.NewSignatureType.
|
||||
func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
|
||||
return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic)
|
||||
}
|
||||
|
||||
// ForSignature returns sig.TypeParams()
|
||||
func ForSignature(sig *types.Signature) *TypeParamList {
|
||||
return sig.TypeParams()
|
||||
}
|
||||
|
||||
// RecvTypeParams returns sig.RecvTypeParams().
|
||||
func RecvTypeParams(sig *types.Signature) *TypeParamList {
|
||||
return sig.RecvTypeParams()
|
||||
}
|
||||
|
||||
// IsComparable calls iface.IsComparable().
|
||||
func IsComparable(iface *types.Interface) bool {
|
||||
return iface.IsComparable()
|
||||
}
|
||||
|
||||
// IsMethodSet calls iface.IsMethodSet().
|
||||
func IsMethodSet(iface *types.Interface) bool {
|
||||
return iface.IsMethodSet()
|
||||
}
|
||||
|
||||
// IsImplicit calls iface.IsImplicit().
|
||||
func IsImplicit(iface *types.Interface) bool {
|
||||
return iface.IsImplicit()
|
||||
}
|
||||
|
||||
// MarkImplicit calls iface.MarkImplicit().
|
||||
func MarkImplicit(iface *types.Interface) {
|
||||
iface.MarkImplicit()
|
||||
}
|
||||
|
||||
// ForNamed extracts the (possibly empty) type parameter object list from
|
||||
// named.
|
||||
func ForNamed(named *types.Named) *TypeParamList {
|
||||
return named.TypeParams()
|
||||
}
|
||||
|
||||
// SetForNamed sets the type params tparams on n. Each tparam must be of
|
||||
// dynamic type *types.TypeParam.
|
||||
func SetForNamed(n *types.Named, tparams []*TypeParam) {
|
||||
n.SetTypeParams(tparams)
|
||||
}
|
||||
|
||||
// NamedTypeArgs returns named.TypeArgs().
|
||||
func NamedTypeArgs(named *types.Named) *TypeList {
|
||||
return named.TypeArgs()
|
||||
}
|
||||
|
||||
// NamedTypeOrigin returns named.Orig().
|
||||
func NamedTypeOrigin(named *types.Named) types.Type {
|
||||
return named.Origin()
|
||||
}
|
||||
|
||||
// Term is an alias for types.Term.
|
||||
type Term = types.Term
|
||||
|
||||
// NewTerm calls types.NewTerm.
|
||||
func NewTerm(tilde bool, typ types.Type) *Term {
|
||||
return types.NewTerm(tilde, typ)
|
||||
}
|
||||
|
||||
// Union is an alias for types.Union
|
||||
type Union = types.Union
|
||||
|
||||
// NewUnion calls types.NewUnion.
|
||||
func NewUnion(terms []*Term) *Union {
|
||||
return types.NewUnion(terms)
|
||||
}
|
||||
|
||||
// InitInstanceInfo initializes info to record information about type and
|
||||
// function instances.
|
||||
func InitInstanceInfo(info *types.Info) {
|
||||
info.Instances = make(map[*ast.Ident]types.Instance)
|
||||
}
|
||||
|
||||
// Instance is an alias for types.Instance.
|
||||
type Instance = types.Instance
|
||||
|
||||
// GetInstances returns info.Instances.
|
||||
func GetInstances(info *types.Info) map[*ast.Ident]Instance {
|
||||
return info.Instances
|
||||
}
|
||||
|
||||
// Context is an alias for types.Context.
|
||||
type Context = types.Context
|
||||
|
||||
// NewContext calls types.NewContext.
|
||||
func NewContext() *Context {
|
||||
return types.NewContext()
|
||||
}
|
||||
|
||||
// Instantiate calls types.Instantiate.
|
||||
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
|
||||
return types.Instantiate(ctxt, typ, targs, validate)
|
||||
}
|
9
vendor/golang.org/x/tools/internal/typeparams/typeterm.go
generated
vendored
9
vendor/golang.org/x/tools/internal/typeparams/typeterm.go
generated
vendored
|
@ -10,11 +10,10 @@ import "go/types"
|
|||
|
||||
// A term describes elementary type sets:
|
||||
//
|
||||
// ∅: (*term)(nil) == ∅ // set of no types (empty set)
|
||||
// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse)
|
||||
// T: &term{false, T} == {T} // set of type T
|
||||
// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t
|
||||
//
|
||||
// ∅: (*term)(nil) == ∅ // set of no types (empty set)
|
||||
// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse)
|
||||
// T: &term{false, T} == {T} // set of type T
|
||||
// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t
|
||||
type term struct {
|
||||
tilde bool // valid if typ != nil
|
||||
typ types.Type
|
||||
|
|
133
vendor/golang.org/x/tools/internal/typesinternal/element.go
generated
vendored
Normal file
133
vendor/golang.org/x/tools/internal/typesinternal/element.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/types/typeutil"
|
||||
)
|
||||
|
||||
// ForEachElement calls f for type T and each type reachable from its
|
||||
// type through reflection. It does this by recursively stripping off
|
||||
// type constructors; in addition, for each named type N, the type *N
|
||||
// is added to the result as it may have additional methods.
|
||||
//
|
||||
// The caller must provide an initially empty set used to de-duplicate
|
||||
// identical types, potentially across multiple calls to ForEachElement.
|
||||
// (Its final value holds all the elements seen, matching the arguments
|
||||
// passed to f.)
|
||||
//
|
||||
// TODO(adonovan): share/harmonize with go/callgraph/rta.
|
||||
func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T types.Type, f func(types.Type)) {
|
||||
var visit func(T types.Type, skip bool)
|
||||
visit = func(T types.Type, skip bool) {
|
||||
if !skip {
|
||||
if seen, _ := rtypes.Set(T, true).(bool); seen {
|
||||
return // de-dup
|
||||
}
|
||||
|
||||
f(T) // notify caller of new element type
|
||||
}
|
||||
|
||||
// Recursion over signatures of each method.
|
||||
tmset := msets.MethodSet(T)
|
||||
for i := 0; i < tmset.Len(); i++ {
|
||||
sig := tmset.At(i).Type().(*types.Signature)
|
||||
// It is tempting to call visit(sig, false)
|
||||
// but, as noted in golang.org/cl/65450043,
|
||||
// the Signature.Recv field is ignored by
|
||||
// types.Identical and typeutil.Map, which
|
||||
// is confusing at best.
|
||||
//
|
||||
// More importantly, the true signature rtype
|
||||
// reachable from a method using reflection
|
||||
// has no receiver but an extra ordinary parameter.
|
||||
// For the Read method of io.Reader we want:
|
||||
// func(Reader, []byte) (int, error)
|
||||
// but here sig is:
|
||||
// func([]byte) (int, error)
|
||||
// with .Recv = Reader (though it is hard to
|
||||
// notice because it doesn't affect Signature.String
|
||||
// or types.Identical).
|
||||
//
|
||||
// TODO(adonovan): construct and visit the correct
|
||||
// non-method signature with an extra parameter
|
||||
// (though since unnamed func types have no methods
|
||||
// there is essentially no actual demand for this).
|
||||
//
|
||||
// TODO(adonovan): document whether or not it is
|
||||
// safe to skip non-exported methods (as RTA does).
|
||||
visit(sig.Params(), true) // skip the Tuple
|
||||
visit(sig.Results(), true) // skip the Tuple
|
||||
}
|
||||
|
||||
switch T := T.(type) {
|
||||
case *types.Alias:
|
||||
visit(types.Unalias(T), skip) // emulates the pre-Alias behavior
|
||||
|
||||
case *types.Basic:
|
||||
// nop
|
||||
|
||||
case *types.Interface:
|
||||
// nop---handled by recursion over method set.
|
||||
|
||||
case *types.Pointer:
|
||||
visit(T.Elem(), false)
|
||||
|
||||
case *types.Slice:
|
||||
visit(T.Elem(), false)
|
||||
|
||||
case *types.Chan:
|
||||
visit(T.Elem(), false)
|
||||
|
||||
case *types.Map:
|
||||
visit(T.Key(), false)
|
||||
visit(T.Elem(), false)
|
||||
|
||||
case *types.Signature:
|
||||
if T.Recv() != nil {
|
||||
panic(fmt.Sprintf("Signature %s has Recv %s", T, T.Recv()))
|
||||
}
|
||||
visit(T.Params(), true) // skip the Tuple
|
||||
visit(T.Results(), true) // skip the Tuple
|
||||
|
||||
case *types.Named:
|
||||
// A pointer-to-named type can be derived from a named
|
||||
// type via reflection. It may have methods too.
|
||||
visit(types.NewPointer(T), false)
|
||||
|
||||
// Consider 'type T struct{S}' where S has methods.
|
||||
// Reflection provides no way to get from T to struct{S},
|
||||
// only to S, so the method set of struct{S} is unwanted,
|
||||
// so set 'skip' flag during recursion.
|
||||
visit(T.Underlying(), true) // skip the unnamed type
|
||||
|
||||
case *types.Array:
|
||||
visit(T.Elem(), false)
|
||||
|
||||
case *types.Struct:
|
||||
for i, n := 0, T.NumFields(); i < n; i++ {
|
||||
// TODO(adonovan): document whether or not
|
||||
// it is safe to skip non-exported fields.
|
||||
visit(T.Field(i).Type(), false)
|
||||
}
|
||||
|
||||
case *types.Tuple:
|
||||
for i, n := 0, T.Len(); i < n; i++ {
|
||||
visit(T.At(i).Type(), false)
|
||||
}
|
||||
|
||||
case *types.TypeParam, *types.Union:
|
||||
// forEachReachable must not be called on parameterized types.
|
||||
panic(T)
|
||||
|
||||
default:
|
||||
panic(T)
|
||||
}
|
||||
}
|
||||
visit(T, false)
|
||||
}
|
52
vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
generated
vendored
52
vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
generated
vendored
|
@ -30,6 +30,12 @@ type ErrorCode int
|
|||
// convention that "bad" implies a problem with syntax, and "invalid" implies a
|
||||
// problem with types.
|
||||
|
||||
const (
|
||||
// InvalidSyntaxTree occurs if an invalid syntax tree is provided
|
||||
// to the type checker. It should never happen.
|
||||
InvalidSyntaxTree ErrorCode = -1
|
||||
)
|
||||
|
||||
const (
|
||||
_ ErrorCode = iota
|
||||
|
||||
|
@ -153,15 +159,15 @@ const (
|
|||
|
||||
/* decls > var (+ other variable assignment codes) */
|
||||
|
||||
// UntypedNil occurs when the predeclared (untyped) value nil is used to
|
||||
// UntypedNilUse occurs when the predeclared (untyped) value nil is used to
|
||||
// initialize a variable declared without an explicit type.
|
||||
//
|
||||
// Example:
|
||||
// var x = nil
|
||||
UntypedNil
|
||||
UntypedNilUse
|
||||
|
||||
// WrongAssignCount occurs when the number of values on the right-hand side
|
||||
// of an assignment or or initialization expression does not match the number
|
||||
// of an assignment or initialization expression does not match the number
|
||||
// of variables on the left-hand side.
|
||||
//
|
||||
// Example:
|
||||
|
@ -832,7 +838,7 @@ const (
|
|||
// InvalidCap occurs when an argument to the cap built-in function is not of
|
||||
// supported type.
|
||||
//
|
||||
// See https://golang.org/ref/spec#Lengthand_capacity for information on
|
||||
// See https://golang.org/ref/spec#Length_and_capacity for information on
|
||||
// which underlying types are supported as arguments to cap and len.
|
||||
//
|
||||
// Example:
|
||||
|
@ -853,7 +859,7 @@ const (
|
|||
// InvalidCopy occurs when the arguments are not of slice type or do not
|
||||
// have compatible type.
|
||||
//
|
||||
// See https://golang.org/ref/spec#Appendingand_copying_slices for more
|
||||
// See https://golang.org/ref/spec#Appending_and_copying_slices for more
|
||||
// information on the type requirements for the copy built-in.
|
||||
//
|
||||
// Example:
|
||||
|
@ -891,7 +897,7 @@ const (
|
|||
// InvalidLen occurs when an argument to the len built-in function is not of
|
||||
// supported type.
|
||||
//
|
||||
// See https://golang.org/ref/spec#Lengthand_capacity for information on
|
||||
// See https://golang.org/ref/spec#Length_and_capacity for information on
|
||||
// which underlying types are supported as arguments to cap and len.
|
||||
//
|
||||
// Example:
|
||||
|
@ -908,7 +914,7 @@ const (
|
|||
|
||||
// InvalidMake occurs when make is called with an unsupported type argument.
|
||||
//
|
||||
// See https://golang.org/ref/spec#Makingslices_maps_and_channels for
|
||||
// See https://golang.org/ref/spec#Making_slices_maps_and_channels for
|
||||
// information on the types that may be created using make.
|
||||
//
|
||||
// Example:
|
||||
|
@ -1443,10 +1449,10 @@ const (
|
|||
NotAGenericType
|
||||
|
||||
// WrongTypeArgCount occurs when a type or function is instantiated with an
|
||||
// incorrent number of type arguments, including when a generic type or
|
||||
// incorrect number of type arguments, including when a generic type or
|
||||
// function is used without instantiation.
|
||||
//
|
||||
// Errors inolving failed type inference are assigned other error codes.
|
||||
// Errors involving failed type inference are assigned other error codes.
|
||||
//
|
||||
// Example:
|
||||
// type T[p any] int
|
||||
|
@ -1523,4 +1529,32 @@ const (
|
|||
// Example:
|
||||
// type T[P any] struct{ *P }
|
||||
MisplacedTypeParam
|
||||
|
||||
// InvalidUnsafeSliceData occurs when unsafe.SliceData is called with
|
||||
// an argument that is not of slice type. It also occurs if it is used
|
||||
// in a package compiled for a language version before go1.20.
|
||||
//
|
||||
// Example:
|
||||
// import "unsafe"
|
||||
//
|
||||
// var x int
|
||||
// var _ = unsafe.SliceData(x)
|
||||
InvalidUnsafeSliceData
|
||||
|
||||
// InvalidUnsafeString occurs when unsafe.String is called with
|
||||
// a length argument that is not of integer type, negative, or
|
||||
// out of bounds. It also occurs if it is used in a package
|
||||
// compiled for a language version before go1.20.
|
||||
//
|
||||
// Example:
|
||||
// import "unsafe"
|
||||
//
|
||||
// var b [10]byte
|
||||
// var _ = unsafe.String(&b[0], -1)
|
||||
InvalidUnsafeString
|
||||
|
||||
// InvalidUnsafeStringData occurs if it is used in a package
|
||||
// compiled for a language version before go1.20.
|
||||
_ // not used anymore
|
||||
|
||||
)
|
||||
|
|
26
vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go
generated
vendored
26
vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go
generated
vendored
|
@ -8,6 +8,7 @@ func _() {
|
|||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[InvalidSyntaxTree - -1]
|
||||
_ = x[Test-1]
|
||||
_ = x[BlankPkgName-2]
|
||||
_ = x[MismatchedPkgName-3]
|
||||
|
@ -23,7 +24,7 @@ func _() {
|
|||
_ = x[InvalidConstInit-13]
|
||||
_ = x[InvalidConstVal-14]
|
||||
_ = x[InvalidConstType-15]
|
||||
_ = x[UntypedNil-16]
|
||||
_ = x[UntypedNilUse-16]
|
||||
_ = x[WrongAssignCount-17]
|
||||
_ = x[UnassignableOperand-18]
|
||||
_ = x[NoNewVar-19]
|
||||
|
@ -152,16 +153,27 @@ func _() {
|
|||
_ = x[MisplacedConstraintIface-142]
|
||||
_ = x[InvalidMethodTypeParams-143]
|
||||
_ = x[MisplacedTypeParam-144]
|
||||
_ = x[InvalidUnsafeSliceData-145]
|
||||
_ = x[InvalidUnsafeString-146]
|
||||
}
|
||||
|
||||
const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParam"
|
||||
const (
|
||||
_ErrorCode_name_0 = "InvalidSyntaxTree"
|
||||
_ErrorCode_name_1 = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilUseWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParamInvalidUnsafeSliceDataInvalidUnsafeString"
|
||||
)
|
||||
|
||||
var _ErrorCode_index = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 215, 231, 250, 258, 274, 292, 309, 327, 351, 359, 374, 390, 408, 425, 440, 447, 458, 481, 496, 508, 519, 534, 548, 563, 578, 591, 600, 614, 629, 640, 655, 664, 680, 700, 718, 737, 749, 768, 787, 803, 820, 839, 853, 864, 879, 892, 907, 923, 937, 953, 968, 985, 1003, 1018, 1028, 1038, 1055, 1077, 1091, 1105, 1125, 1143, 1163, 1181, 1204, 1220, 1235, 1248, 1258, 1270, 1281, 1295, 1308, 1319, 1329, 1344, 1355, 1366, 1379, 1395, 1412, 1436, 1453, 1468, 1478, 1487, 1500, 1516, 1532, 1543, 1558, 1574, 1588, 1604, 1618, 1635, 1655, 1668, 1684, 1698, 1715, 1732, 1749, 1764, 1778, 1792, 1803, 1815, 1828, 1845, 1858, 1869, 1882, 1894, 1903, 1910, 1922, 1938, 1956, 1974, 1989, 2006, 2025, 2039, 2059, 2071, 2095, 2118, 2136}
|
||||
var (
|
||||
_ErrorCode_index_1 = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 218, 234, 253, 261, 277, 295, 312, 330, 354, 362, 377, 393, 411, 428, 443, 450, 461, 484, 499, 511, 522, 537, 551, 566, 581, 594, 603, 617, 632, 643, 658, 667, 683, 703, 721, 740, 752, 771, 790, 806, 823, 842, 856, 867, 882, 895, 910, 926, 940, 956, 971, 988, 1006, 1021, 1031, 1041, 1058, 1080, 1094, 1108, 1128, 1146, 1166, 1184, 1207, 1223, 1238, 1251, 1261, 1273, 1284, 1298, 1311, 1322, 1332, 1347, 1358, 1369, 1382, 1398, 1415, 1439, 1456, 1471, 1481, 1490, 1503, 1519, 1535, 1546, 1561, 1577, 1591, 1607, 1621, 1638, 1658, 1671, 1687, 1701, 1718, 1735, 1752, 1767, 1781, 1795, 1806, 1818, 1831, 1848, 1861, 1872, 1885, 1897, 1906, 1913, 1925, 1941, 1959, 1977, 1992, 2009, 2028, 2042, 2062, 2074, 2098, 2121, 2139, 2161, 2180}
|
||||
)
|
||||
|
||||
func (i ErrorCode) String() string {
|
||||
i -= 1
|
||||
if i < 0 || i >= ErrorCode(len(_ErrorCode_index)-1) {
|
||||
return "ErrorCode(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||
switch {
|
||||
case i == -1:
|
||||
return _ErrorCode_name_0
|
||||
case 1 <= i && i <= 146:
|
||||
i -= 1
|
||||
return _ErrorCode_name_1[_ErrorCode_index_1[i]:_ErrorCode_index_1[i+1]]
|
||||
default:
|
||||
return "ErrorCode(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]]
|
||||
}
|
||||
|
|
46
vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
generated
vendored
Normal file
46
vendor/golang.org/x/tools/internal/typesinternal/qualifier.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// FileQualifier returns a [types.Qualifier] function that qualifies
|
||||
// imported symbols appropriately based on the import environment of a given
|
||||
// file.
|
||||
// If the same package is imported multiple times, the last appearance is
|
||||
// recorded.
|
||||
func FileQualifier(f *ast.File, pkg *types.Package) types.Qualifier {
|
||||
// Construct mapping of import paths to their defined names.
|
||||
// It is only necessary to look at renaming imports.
|
||||
imports := make(map[string]string)
|
||||
for _, imp := range f.Imports {
|
||||
if imp.Name != nil && imp.Name.Name != "_" {
|
||||
path, _ := strconv.Unquote(imp.Path.Value)
|
||||
imports[path] = imp.Name.Name
|
||||
}
|
||||
}
|
||||
|
||||
// Define qualifier to replace full package paths with names of the imports.
|
||||
return func(p *types.Package) string {
|
||||
if p == nil || p == pkg {
|
||||
return ""
|
||||
}
|
||||
|
||||
if name, ok := imports[p.Path()]; ok {
|
||||
if name == "." {
|
||||
return ""
|
||||
} else {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no local renaming, fall back to the package name.
|
||||
return p.Name()
|
||||
}
|
||||
}
|
43
vendor/golang.org/x/tools/internal/typesinternal/recv.go
generated
vendored
Normal file
43
vendor/golang.org/x/tools/internal/typesinternal/recv.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// ReceiverNamed returns the named type (if any) associated with the
|
||||
// type of recv, which may be of the form N or *N, or aliases thereof.
|
||||
// It also reports whether a Pointer was present.
|
||||
//
|
||||
// The named result may be nil in ill-typed code.
|
||||
func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
|
||||
t := recv.Type()
|
||||
if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
|
||||
isPtr = true
|
||||
t = ptr.Elem()
|
||||
}
|
||||
named, _ = types.Unalias(t).(*types.Named)
|
||||
return
|
||||
}
|
||||
|
||||
// Unpointer returns T given *T or an alias thereof.
|
||||
// For all other types it is the identity function.
|
||||
// It does not look at underlying types.
|
||||
// The result may be an alias.
|
||||
//
|
||||
// Use this function to strip off the optional pointer on a receiver
|
||||
// in a field or method selection, without losing the named type
|
||||
// (which is needed to compute the method set).
|
||||
//
|
||||
// See also [typeparams.MustDeref], which removes one level of
|
||||
// indirection from the type, regardless of named types (analogous to
|
||||
// a LOAD instruction).
|
||||
func Unpointer(t types.Type) types.Type {
|
||||
if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
|
||||
return ptr.Elem()
|
||||
}
|
||||
return t
|
||||
}
|
89
vendor/golang.org/x/tools/internal/typesinternal/toonew.go
generated
vendored
Normal file
89
vendor/golang.org/x/tools/internal/typesinternal/toonew.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/internal/stdlib"
|
||||
"golang.org/x/tools/internal/versions"
|
||||
)
|
||||
|
||||
// TooNewStdSymbols computes the set of package-level symbols
|
||||
// exported by pkg that are not available at the specified version.
|
||||
// The result maps each symbol to its minimum version.
|
||||
//
|
||||
// The pkg is allowed to contain type errors.
|
||||
func TooNewStdSymbols(pkg *types.Package, version string) map[types.Object]string {
|
||||
disallowed := make(map[types.Object]string)
|
||||
|
||||
// Pass 1: package-level symbols.
|
||||
symbols := stdlib.PackageSymbols[pkg.Path()]
|
||||
for _, sym := range symbols {
|
||||
symver := sym.Version.String()
|
||||
if versions.Before(version, symver) {
|
||||
switch sym.Kind {
|
||||
case stdlib.Func, stdlib.Var, stdlib.Const, stdlib.Type:
|
||||
disallowed[pkg.Scope().Lookup(sym.Name)] = symver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2: fields and methods.
|
||||
//
|
||||
// We allow fields and methods if their associated type is
|
||||
// disallowed, as otherwise we would report false positives
|
||||
// for compatibility shims. Consider:
|
||||
//
|
||||
// //go:build go1.22
|
||||
// type T struct { F std.Real } // correct new API
|
||||
//
|
||||
// //go:build !go1.22
|
||||
// type T struct { F fake } // shim
|
||||
// type fake struct { ... }
|
||||
// func (fake) M () {}
|
||||
//
|
||||
// These alternative declarations of T use either the std.Real
|
||||
// type, introduced in go1.22, or a fake type, for the field
|
||||
// F. (The fakery could be arbitrarily deep, involving more
|
||||
// nested fields and methods than are shown here.) Clients
|
||||
// that use the compatibility shim T will compile with any
|
||||
// version of go, whether older or newer than go1.22, but only
|
||||
// the newer version will use the std.Real implementation.
|
||||
//
|
||||
// Now consider a reference to method M in new(T).F.M() in a
|
||||
// module that requires a minimum of go1.21. The analysis may
|
||||
// occur using a version of Go higher than 1.21, selecting the
|
||||
// first version of T, so the method M is Real.M. This would
|
||||
// spuriously cause the analyzer to report a reference to a
|
||||
// too-new symbol even though this expression compiles just
|
||||
// fine (with the fake implementation) using go1.21.
|
||||
for _, sym := range symbols {
|
||||
symVersion := sym.Version.String()
|
||||
if !versions.Before(version, symVersion) {
|
||||
continue // allowed
|
||||
}
|
||||
|
||||
var obj types.Object
|
||||
switch sym.Kind {
|
||||
case stdlib.Field:
|
||||
typename, name := sym.SplitField()
|
||||
if t := pkg.Scope().Lookup(typename); t != nil && disallowed[t] == "" {
|
||||
obj, _, _ = types.LookupFieldOrMethod(t.Type(), false, pkg, name)
|
||||
}
|
||||
|
||||
case stdlib.Method:
|
||||
ptr, recvname, name := sym.SplitMethod()
|
||||
if t := pkg.Scope().Lookup(recvname); t != nil && disallowed[t] == "" {
|
||||
obj, _, _ = types.LookupFieldOrMethod(t.Type(), ptr, pkg, name)
|
||||
}
|
||||
}
|
||||
if obj != nil {
|
||||
disallowed[obj] = symVersion
|
||||
}
|
||||
}
|
||||
|
||||
return disallowed
|
||||
}
|
72
vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
72
vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
|
@ -11,6 +11,8 @@ import (
|
|||
"go/types"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/tools/internal/aliases"
|
||||
)
|
||||
|
||||
func SetUsesCgo(conf *types.Config) bool {
|
||||
|
@ -49,4 +51,72 @@ func ReadGo116ErrorData(err types.Error) (code ErrorCode, start, end token.Pos,
|
|||
return ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true
|
||||
}
|
||||
|
||||
var SetGoVersion = func(conf *types.Config, version string) bool { return false }
|
||||
// NameRelativeTo returns a types.Qualifier that qualifies members of
|
||||
// all packages other than pkg, using only the package name.
|
||||
// (By contrast, [types.RelativeTo] uses the complete package path,
|
||||
// which is often excessive.)
|
||||
//
|
||||
// If pkg is nil, it is equivalent to [*types.Package.Name].
|
||||
func NameRelativeTo(pkg *types.Package) types.Qualifier {
|
||||
return func(other *types.Package) string {
|
||||
if pkg != nil && pkg == other {
|
||||
return "" // same package; unqualified
|
||||
}
|
||||
return other.Name()
|
||||
}
|
||||
}
|
||||
|
||||
// A NamedOrAlias is a [types.Type] that is named (as
|
||||
// defined by the spec) and capable of bearing type parameters: it
|
||||
// abstracts aliases ([types.Alias]) and defined types
|
||||
// ([types.Named]).
|
||||
//
|
||||
// Every type declared by an explicit "type" declaration is a
|
||||
// NamedOrAlias. (Built-in type symbols may additionally
|
||||
// have type [types.Basic], which is not a NamedOrAlias,
|
||||
// though the spec regards them as "named".)
|
||||
//
|
||||
// NamedOrAlias cannot expose the Origin method, because
|
||||
// [types.Alias.Origin] and [types.Named.Origin] have different
|
||||
// (covariant) result types; use [Origin] instead.
|
||||
type NamedOrAlias interface {
|
||||
types.Type
|
||||
Obj() *types.TypeName
|
||||
// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
|
||||
}
|
||||
|
||||
// TypeParams is a light shim around t.TypeParams().
|
||||
// (go/types.Alias).TypeParams requires >= 1.23.
|
||||
func TypeParams(t NamedOrAlias) *types.TypeParamList {
|
||||
switch t := t.(type) {
|
||||
case *types.Alias:
|
||||
return aliases.TypeParams(t)
|
||||
case *types.Named:
|
||||
return t.TypeParams()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TypeArgs is a light shim around t.TypeArgs().
|
||||
// (go/types.Alias).TypeArgs requires >= 1.23.
|
||||
func TypeArgs(t NamedOrAlias) *types.TypeList {
|
||||
switch t := t.(type) {
|
||||
case *types.Alias:
|
||||
return aliases.TypeArgs(t)
|
||||
case *types.Named:
|
||||
return t.TypeArgs()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Origin returns the generic type of the Named or Alias type t if it
|
||||
// is instantiated, otherwise it returns t.
|
||||
func Origin(t NamedOrAlias) NamedOrAlias {
|
||||
switch t := t.(type) {
|
||||
case *types.Alias:
|
||||
return aliases.Origin(t)
|
||||
case *types.Named:
|
||||
return t.Origin()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
|
19
vendor/golang.org/x/tools/internal/typesinternal/types_118.go
generated
vendored
19
vendor/golang.org/x/tools/internal/typesinternal/types_118.go
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package typesinternal
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SetGoVersion = func(conf *types.Config, version string) bool {
|
||||
conf.GoVersion = version
|
||||
return true
|
||||
}
|
||||
}
|
392
vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
generated
vendored
Normal file
392
vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
generated
vendored
Normal file
|
@ -0,0 +1,392 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ZeroString returns the string representation of the zero value for any type t.
|
||||
// The boolean result indicates whether the type is or contains an invalid type
|
||||
// or a non-basic (constraint) interface type.
|
||||
//
|
||||
// Even for invalid input types, ZeroString may return a partially correct
|
||||
// string representation. The caller should use the returned isValid boolean
|
||||
// to determine the validity of the expression.
|
||||
//
|
||||
// When assigning to a wider type (such as 'any'), it's the caller's
|
||||
// responsibility to handle any necessary type conversions.
|
||||
//
|
||||
// This string can be used on the right-hand side of an assignment where the
|
||||
// left-hand side has that explicit type.
|
||||
// References to named types are qualified by an appropriate (optional)
|
||||
// qualifier function.
|
||||
// Exception: This does not apply to tuples. Their string representation is
|
||||
// informational only and cannot be used in an assignment.
|
||||
//
|
||||
// See [ZeroExpr] for a variant that returns an [ast.Expr].
|
||||
func ZeroString(t types.Type, qual types.Qualifier) (_ string, isValid bool) {
|
||||
switch t := t.(type) {
|
||||
case *types.Basic:
|
||||
switch {
|
||||
case t.Info()&types.IsBoolean != 0:
|
||||
return "false", true
|
||||
case t.Info()&types.IsNumeric != 0:
|
||||
return "0", true
|
||||
case t.Info()&types.IsString != 0:
|
||||
return `""`, true
|
||||
case t.Kind() == types.UnsafePointer:
|
||||
fallthrough
|
||||
case t.Kind() == types.UntypedNil:
|
||||
return "nil", true
|
||||
case t.Kind() == types.Invalid:
|
||||
return "invalid", false
|
||||
default:
|
||||
panic(fmt.Sprintf("ZeroString for unexpected type %v", t))
|
||||
}
|
||||
|
||||
case *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:
|
||||
return "nil", true
|
||||
|
||||
case *types.Interface:
|
||||
if !t.IsMethodSet() {
|
||||
return "invalid", false
|
||||
}
|
||||
return "nil", true
|
||||
|
||||
case *types.Named:
|
||||
switch under := t.Underlying().(type) {
|
||||
case *types.Struct, *types.Array:
|
||||
return types.TypeString(t, qual) + "{}", true
|
||||
default:
|
||||
return ZeroString(under, qual)
|
||||
}
|
||||
|
||||
case *types.Alias:
|
||||
switch t.Underlying().(type) {
|
||||
case *types.Struct, *types.Array:
|
||||
return types.TypeString(t, qual) + "{}", true
|
||||
default:
|
||||
// A type parameter can have alias but alias type's underlying type
|
||||
// can never be a type parameter.
|
||||
// Use types.Unalias to preserve the info of type parameter instead
|
||||
// of call Underlying() going right through and get the underlying
|
||||
// type of the type parameter which is always an interface.
|
||||
return ZeroString(types.Unalias(t), qual)
|
||||
}
|
||||
|
||||
case *types.Array, *types.Struct:
|
||||
return types.TypeString(t, qual) + "{}", true
|
||||
|
||||
case *types.TypeParam:
|
||||
// Assumes func new is not shadowed.
|
||||
return "*new(" + types.TypeString(t, qual) + ")", true
|
||||
|
||||
case *types.Tuple:
|
||||
// Tuples are not normal values.
|
||||
// We are currently format as "(t[0], ..., t[n])". Could be something else.
|
||||
isValid := true
|
||||
components := make([]string, t.Len())
|
||||
for i := 0; i < t.Len(); i++ {
|
||||
comp, ok := ZeroString(t.At(i).Type(), qual)
|
||||
|
||||
components[i] = comp
|
||||
isValid = isValid && ok
|
||||
}
|
||||
return "(" + strings.Join(components, ", ") + ")", isValid
|
||||
|
||||
case *types.Union:
|
||||
// Variables of these types cannot be created, so it makes
|
||||
// no sense to ask for their zero value.
|
||||
panic(fmt.Sprintf("invalid type for a variable: %v", t))
|
||||
|
||||
default:
|
||||
panic(t) // unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
// ZeroExpr returns the ast.Expr representation of the zero value for any type t.
|
||||
// The boolean result indicates whether the type is or contains an invalid type
|
||||
// or a non-basic (constraint) interface type.
|
||||
//
|
||||
// Even for invalid input types, ZeroExpr may return a partially correct ast.Expr
|
||||
// representation. The caller should use the returned isValid boolean to determine
|
||||
// the validity of the expression.
|
||||
//
|
||||
// This function is designed for types suitable for variables and should not be
|
||||
// used with Tuple or Union types.References to named types are qualified by an
|
||||
// appropriate (optional) qualifier function.
|
||||
//
|
||||
// See [ZeroString] for a variant that returns a string.
|
||||
func ZeroExpr(t types.Type, qual types.Qualifier) (_ ast.Expr, isValid bool) {
|
||||
switch t := t.(type) {
|
||||
case *types.Basic:
|
||||
switch {
|
||||
case t.Info()&types.IsBoolean != 0:
|
||||
return &ast.Ident{Name: "false"}, true
|
||||
case t.Info()&types.IsNumeric != 0:
|
||||
return &ast.BasicLit{Kind: token.INT, Value: "0"}, true
|
||||
case t.Info()&types.IsString != 0:
|
||||
return &ast.BasicLit{Kind: token.STRING, Value: `""`}, true
|
||||
case t.Kind() == types.UnsafePointer:
|
||||
fallthrough
|
||||
case t.Kind() == types.UntypedNil:
|
||||
return ast.NewIdent("nil"), true
|
||||
case t.Kind() == types.Invalid:
|
||||
return &ast.BasicLit{Kind: token.STRING, Value: `"invalid"`}, false
|
||||
default:
|
||||
panic(fmt.Sprintf("ZeroExpr for unexpected type %v", t))
|
||||
}
|
||||
|
||||
case *types.Pointer, *types.Slice, *types.Chan, *types.Map, *types.Signature:
|
||||
return ast.NewIdent("nil"), true
|
||||
|
||||
case *types.Interface:
|
||||
if !t.IsMethodSet() {
|
||||
return &ast.BasicLit{Kind: token.STRING, Value: `"invalid"`}, false
|
||||
}
|
||||
return ast.NewIdent("nil"), true
|
||||
|
||||
case *types.Named:
|
||||
switch under := t.Underlying().(type) {
|
||||
case *types.Struct, *types.Array:
|
||||
return &ast.CompositeLit{
|
||||
Type: TypeExpr(t, qual),
|
||||
}, true
|
||||
default:
|
||||
return ZeroExpr(under, qual)
|
||||
}
|
||||
|
||||
case *types.Alias:
|
||||
switch t.Underlying().(type) {
|
||||
case *types.Struct, *types.Array:
|
||||
return &ast.CompositeLit{
|
||||
Type: TypeExpr(t, qual),
|
||||
}, true
|
||||
default:
|
||||
return ZeroExpr(types.Unalias(t), qual)
|
||||
}
|
||||
|
||||
case *types.Array, *types.Struct:
|
||||
return &ast.CompositeLit{
|
||||
Type: TypeExpr(t, qual),
|
||||
}, true
|
||||
|
||||
case *types.TypeParam:
|
||||
return &ast.StarExpr{ // *new(T)
|
||||
X: &ast.CallExpr{
|
||||
// Assumes func new is not shadowed.
|
||||
Fun: ast.NewIdent("new"),
|
||||
Args: []ast.Expr{
|
||||
ast.NewIdent(t.Obj().Name()),
|
||||
},
|
||||
},
|
||||
}, true
|
||||
|
||||
case *types.Tuple:
|
||||
// Unlike ZeroString, there is no ast.Expr can express tuple by
|
||||
// "(t[0], ..., t[n])".
|
||||
panic(fmt.Sprintf("invalid type for a variable: %v", t))
|
||||
|
||||
case *types.Union:
|
||||
// Variables of these types cannot be created, so it makes
|
||||
// no sense to ask for their zero value.
|
||||
panic(fmt.Sprintf("invalid type for a variable: %v", t))
|
||||
|
||||
default:
|
||||
panic(t) // unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
// IsZeroExpr uses simple syntactic heuristics to report whether expr
|
||||
// is a obvious zero value, such as 0, "", nil, or false.
|
||||
// It cannot do better without type information.
|
||||
func IsZeroExpr(expr ast.Expr) bool {
|
||||
switch e := expr.(type) {
|
||||
case *ast.BasicLit:
|
||||
return e.Value == "0" || e.Value == `""`
|
||||
case *ast.Ident:
|
||||
return e.Name == "nil" || e.Name == "false"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// TypeExpr returns syntax for the specified type. References to named types
|
||||
// are qualified by an appropriate (optional) qualifier function.
|
||||
// It may panic for types such as Tuple or Union.
|
||||
func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
|
||||
switch t := t.(type) {
|
||||
case *types.Basic:
|
||||
switch t.Kind() {
|
||||
case types.UnsafePointer:
|
||||
return &ast.SelectorExpr{X: ast.NewIdent(qual(types.NewPackage("unsafe", "unsafe"))), Sel: ast.NewIdent("Pointer")}
|
||||
default:
|
||||
return ast.NewIdent(t.Name())
|
||||
}
|
||||
|
||||
case *types.Pointer:
|
||||
return &ast.UnaryExpr{
|
||||
Op: token.MUL,
|
||||
X: TypeExpr(t.Elem(), qual),
|
||||
}
|
||||
|
||||
case *types.Array:
|
||||
return &ast.ArrayType{
|
||||
Len: &ast.BasicLit{
|
||||
Kind: token.INT,
|
||||
Value: fmt.Sprintf("%d", t.Len()),
|
||||
},
|
||||
Elt: TypeExpr(t.Elem(), qual),
|
||||
}
|
||||
|
||||
case *types.Slice:
|
||||
return &ast.ArrayType{
|
||||
Elt: TypeExpr(t.Elem(), qual),
|
||||
}
|
||||
|
||||
case *types.Map:
|
||||
return &ast.MapType{
|
||||
Key: TypeExpr(t.Key(), qual),
|
||||
Value: TypeExpr(t.Elem(), qual),
|
||||
}
|
||||
|
||||
case *types.Chan:
|
||||
dir := ast.ChanDir(t.Dir())
|
||||
if t.Dir() == types.SendRecv {
|
||||
dir = ast.SEND | ast.RECV
|
||||
}
|
||||
return &ast.ChanType{
|
||||
Dir: dir,
|
||||
Value: TypeExpr(t.Elem(), qual),
|
||||
}
|
||||
|
||||
case *types.Signature:
|
||||
var params []*ast.Field
|
||||
for i := 0; i < t.Params().Len(); i++ {
|
||||
params = append(params, &ast.Field{
|
||||
Type: TypeExpr(t.Params().At(i).Type(), qual),
|
||||
Names: []*ast.Ident{
|
||||
{
|
||||
Name: t.Params().At(i).Name(),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
if t.Variadic() {
|
||||
last := params[len(params)-1]
|
||||
last.Type = &ast.Ellipsis{Elt: last.Type.(*ast.ArrayType).Elt}
|
||||
}
|
||||
var returns []*ast.Field
|
||||
for i := 0; i < t.Results().Len(); i++ {
|
||||
returns = append(returns, &ast.Field{
|
||||
Type: TypeExpr(t.Results().At(i).Type(), qual),
|
||||
})
|
||||
}
|
||||
return &ast.FuncType{
|
||||
Params: &ast.FieldList{
|
||||
List: params,
|
||||
},
|
||||
Results: &ast.FieldList{
|
||||
List: returns,
|
||||
},
|
||||
}
|
||||
|
||||
case *types.TypeParam:
|
||||
pkgName := qual(t.Obj().Pkg())
|
||||
if pkgName == "" || t.Obj().Pkg() == nil {
|
||||
return ast.NewIdent(t.Obj().Name())
|
||||
}
|
||||
return &ast.SelectorExpr{
|
||||
X: ast.NewIdent(pkgName),
|
||||
Sel: ast.NewIdent(t.Obj().Name()),
|
||||
}
|
||||
|
||||
// types.TypeParam also implements interface NamedOrAlias. To differentiate,
|
||||
// case TypeParam need to be present before case NamedOrAlias.
|
||||
// TODO(hxjiang): remove this comment once TypeArgs() is added to interface
|
||||
// NamedOrAlias.
|
||||
case NamedOrAlias:
|
||||
var expr ast.Expr = ast.NewIdent(t.Obj().Name())
|
||||
if pkgName := qual(t.Obj().Pkg()); pkgName != "." && pkgName != "" {
|
||||
expr = &ast.SelectorExpr{
|
||||
X: ast.NewIdent(pkgName),
|
||||
Sel: expr.(*ast.Ident),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(hxjiang): call t.TypeArgs after adding method TypeArgs() to
|
||||
// typesinternal.NamedOrAlias.
|
||||
if hasTypeArgs, ok := t.(interface{ TypeArgs() *types.TypeList }); ok {
|
||||
if typeArgs := hasTypeArgs.TypeArgs(); typeArgs != nil && typeArgs.Len() > 0 {
|
||||
var indices []ast.Expr
|
||||
for i := range typeArgs.Len() {
|
||||
indices = append(indices, TypeExpr(typeArgs.At(i), qual))
|
||||
}
|
||||
expr = &ast.IndexListExpr{
|
||||
X: expr,
|
||||
Indices: indices,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expr
|
||||
|
||||
case *types.Struct:
|
||||
return ast.NewIdent(t.String())
|
||||
|
||||
case *types.Interface:
|
||||
return ast.NewIdent(t.String())
|
||||
|
||||
case *types.Union:
|
||||
if t.Len() == 0 {
|
||||
panic("Union type should have at least one term")
|
||||
}
|
||||
// Same as go/ast, the return expression will put last term in the
|
||||
// Y field at topmost level of BinaryExpr.
|
||||
// For union of type "float32 | float64 | int64", the structure looks
|
||||
// similar to:
|
||||
// {
|
||||
// X: {
|
||||
// X: float32,
|
||||
// Op: |
|
||||
// Y: float64,
|
||||
// }
|
||||
// Op: |,
|
||||
// Y: int64,
|
||||
// }
|
||||
var union ast.Expr
|
||||
for i := range t.Len() {
|
||||
term := t.Term(i)
|
||||
termExpr := TypeExpr(term.Type(), qual)
|
||||
if term.Tilde() {
|
||||
termExpr = &ast.UnaryExpr{
|
||||
Op: token.TILDE,
|
||||
X: termExpr,
|
||||
}
|
||||
}
|
||||
if i == 0 {
|
||||
union = termExpr
|
||||
} else {
|
||||
union = &ast.BinaryExpr{
|
||||
X: union,
|
||||
Op: token.OR,
|
||||
Y: termExpr,
|
||||
}
|
||||
}
|
||||
}
|
||||
return union
|
||||
|
||||
case *types.Tuple:
|
||||
panic("invalid input type types.Tuple")
|
||||
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
43
vendor/golang.org/x/tools/internal/versions/features.go
generated
vendored
Normal file
43
vendor/golang.org/x/tools/internal/versions/features.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package versions
|
||||
|
||||
// This file contains predicates for working with file versions to
|
||||
// decide when a tool should consider a language feature enabled.
|
||||
|
||||
// GoVersions that features in x/tools can be gated to.
|
||||
const (
|
||||
Go1_18 = "go1.18"
|
||||
Go1_19 = "go1.19"
|
||||
Go1_20 = "go1.20"
|
||||
Go1_21 = "go1.21"
|
||||
Go1_22 = "go1.22"
|
||||
)
|
||||
|
||||
// Future is an invalid unknown Go version sometime in the future.
|
||||
// Do not use directly with Compare.
|
||||
const Future = ""
|
||||
|
||||
// AtLeast reports whether the file version v comes after a Go release.
|
||||
//
|
||||
// Use this predicate to enable a behavior once a certain Go release
|
||||
// has happened (and stays enabled in the future).
|
||||
func AtLeast(v, release string) bool {
|
||||
if v == Future {
|
||||
return true // an unknown future version is always after y.
|
||||
}
|
||||
return Compare(Lang(v), Lang(release)) >= 0
|
||||
}
|
||||
|
||||
// Before reports whether the file version v is strictly before a Go release.
|
||||
//
|
||||
// Use this predicate to disable a behavior once a certain Go release
|
||||
// has happened (and stays enabled in the future).
|
||||
func Before(v, release string) bool {
|
||||
if v == Future {
|
||||
return false // an unknown future version happens after y.
|
||||
}
|
||||
return Compare(Lang(v), Lang(release)) < 0
|
||||
}
|
172
vendor/golang.org/x/tools/internal/versions/gover.go
generated
vendored
Normal file
172
vendor/golang.org/x/tools/internal/versions/gover.go
generated
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This is a fork of internal/gover for use by x/tools until
|
||||
// go1.21 and earlier are no longer supported by x/tools.
|
||||
|
||||
package versions
|
||||
|
||||
import "strings"
|
||||
|
||||
// A gover is a parsed Go gover: major[.Minor[.Patch]][kind[pre]]
|
||||
// The numbers are the original decimal strings to avoid integer overflows
|
||||
// and since there is very little actual math. (Probably overflow doesn't matter in practice,
|
||||
// but at the time this code was written, there was an existing test that used
|
||||
// go1.99999999999, which does not fit in an int on 32-bit platforms.
|
||||
// The "big decimal" representation avoids the problem entirely.)
|
||||
type gover struct {
|
||||
major string // decimal
|
||||
minor string // decimal or ""
|
||||
patch string // decimal or ""
|
||||
kind string // "", "alpha", "beta", "rc"
|
||||
pre string // decimal or ""
|
||||
}
|
||||
|
||||
// compare returns -1, 0, or +1 depending on whether
|
||||
// x < y, x == y, or x > y, interpreted as toolchain versions.
|
||||
// The versions x and y must not begin with a "go" prefix: just "1.21" not "go1.21".
|
||||
// Malformed versions compare less than well-formed versions and equal to each other.
|
||||
// The language version "1.21" compares less than the release candidate and eventual releases "1.21rc1" and "1.21.0".
|
||||
func compare(x, y string) int {
|
||||
vx := parse(x)
|
||||
vy := parse(y)
|
||||
|
||||
if c := cmpInt(vx.major, vy.major); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := cmpInt(vx.minor, vy.minor); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := cmpInt(vx.patch, vy.patch); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := strings.Compare(vx.kind, vy.kind); c != 0 { // "" < alpha < beta < rc
|
||||
return c
|
||||
}
|
||||
if c := cmpInt(vx.pre, vy.pre); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// lang returns the Go language version. For example, lang("1.2.3") == "1.2".
|
||||
func lang(x string) string {
|
||||
v := parse(x)
|
||||
if v.minor == "" || v.major == "1" && v.minor == "0" {
|
||||
return v.major
|
||||
}
|
||||
return v.major + "." + v.minor
|
||||
}
|
||||
|
||||
// isValid reports whether the version x is valid.
|
||||
func isValid(x string) bool {
|
||||
return parse(x) != gover{}
|
||||
}
|
||||
|
||||
// parse parses the Go version string x into a version.
|
||||
// It returns the zero version if x is malformed.
|
||||
func parse(x string) gover {
|
||||
var v gover
|
||||
|
||||
// Parse major version.
|
||||
var ok bool
|
||||
v.major, x, ok = cutInt(x)
|
||||
if !ok {
|
||||
return gover{}
|
||||
}
|
||||
if x == "" {
|
||||
// Interpret "1" as "1.0.0".
|
||||
v.minor = "0"
|
||||
v.patch = "0"
|
||||
return v
|
||||
}
|
||||
|
||||
// Parse . before minor version.
|
||||
if x[0] != '.' {
|
||||
return gover{}
|
||||
}
|
||||
|
||||
// Parse minor version.
|
||||
v.minor, x, ok = cutInt(x[1:])
|
||||
if !ok {
|
||||
return gover{}
|
||||
}
|
||||
if x == "" {
|
||||
// Patch missing is same as "0" for older versions.
|
||||
// Starting in Go 1.21, patch missing is different from explicit .0.
|
||||
if cmpInt(v.minor, "21") < 0 {
|
||||
v.patch = "0"
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Parse patch if present.
|
||||
if x[0] == '.' {
|
||||
v.patch, x, ok = cutInt(x[1:])
|
||||
if !ok || x != "" {
|
||||
// Note that we are disallowing prereleases (alpha, beta, rc) for patch releases here (x != "").
|
||||
// Allowing them would be a bit confusing because we already have:
|
||||
// 1.21 < 1.21rc1
|
||||
// But a prerelease of a patch would have the opposite effect:
|
||||
// 1.21.3rc1 < 1.21.3
|
||||
// We've never needed them before, so let's not start now.
|
||||
return gover{}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Parse prerelease.
|
||||
i := 0
|
||||
for i < len(x) && (x[i] < '0' || '9' < x[i]) {
|
||||
if x[i] < 'a' || 'z' < x[i] {
|
||||
return gover{}
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i == 0 {
|
||||
return gover{}
|
||||
}
|
||||
v.kind, x = x[:i], x[i:]
|
||||
if x == "" {
|
||||
return v
|
||||
}
|
||||
v.pre, x, ok = cutInt(x)
|
||||
if !ok || x != "" {
|
||||
return gover{}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// cutInt scans the leading decimal number at the start of x to an integer
|
||||
// and returns that value and the rest of the string.
|
||||
func cutInt(x string) (n, rest string, ok bool) {
|
||||
i := 0
|
||||
for i < len(x) && '0' <= x[i] && x[i] <= '9' {
|
||||
i++
|
||||
}
|
||||
if i == 0 || x[0] == '0' && i != 1 { // no digits or unnecessary leading zero
|
||||
return "", "", false
|
||||
}
|
||||
return x[:i], x[i:], true
|
||||
}
|
||||
|
||||
// cmpInt returns cmp.Compare(x, y) interpreting x and y as decimal numbers.
|
||||
// (Copied from golang.org/x/mod/semver's compareInt.)
|
||||
func cmpInt(x, y string) int {
|
||||
if x == y {
|
||||
return 0
|
||||
}
|
||||
if len(x) < len(y) {
|
||||
return -1
|
||||
}
|
||||
if len(x) > len(y) {
|
||||
return +1
|
||||
}
|
||||
if x < y {
|
||||
return -1
|
||||
} else {
|
||||
return +1
|
||||
}
|
||||
}
|
33
vendor/golang.org/x/tools/internal/versions/types.go
generated
vendored
Normal file
33
vendor/golang.org/x/tools/internal/versions/types.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package versions
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// FileVersion returns a file's Go version.
|
||||
// The reported version is an unknown Future version if a
|
||||
// version cannot be determined.
|
||||
func FileVersion(info *types.Info, file *ast.File) string {
|
||||
// In tools built with Go >= 1.22, the Go version of a file
|
||||
// follow a cascades of sources:
|
||||
// 1) types.Info.FileVersion, which follows the cascade:
|
||||
// 1.a) file version (ast.File.GoVersion),
|
||||
// 1.b) the package version (types.Config.GoVersion), or
|
||||
// 2) is some unknown Future version.
|
||||
//
|
||||
// File versions require a valid package version to be provided to types
|
||||
// in Config.GoVersion. Config.GoVersion is either from the package's module
|
||||
// or the toolchain (go run). This value should be provided by go/packages
|
||||
// or unitchecker.Config.GoVersion.
|
||||
if v := info.FileVersions[file]; IsValid(v) {
|
||||
return v
|
||||
}
|
||||
// Note: we could instead return runtime.Version() [if valid].
|
||||
// This would act as a max version on what a tool can support.
|
||||
return Future
|
||||
}
|
57
vendor/golang.org/x/tools/internal/versions/versions.go
generated
vendored
Normal file
57
vendor/golang.org/x/tools/internal/versions/versions.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package versions
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Note: If we use build tags to use go/versions when go >=1.22,
|
||||
// we run into go.dev/issue/53737. Under some operations users would see an
|
||||
// import of "go/versions" even if they would not compile the file.
|
||||
// For example, during `go get -u ./...` (go.dev/issue/64490) we do not try to include
|
||||
// For this reason, this library just a clone of go/versions for the moment.
|
||||
|
||||
// Lang returns the Go language version for version x.
|
||||
// If x is not a valid version, Lang returns the empty string.
|
||||
// For example:
|
||||
//
|
||||
// Lang("go1.21rc2") = "go1.21"
|
||||
// Lang("go1.21.2") = "go1.21"
|
||||
// Lang("go1.21") = "go1.21"
|
||||
// Lang("go1") = "go1"
|
||||
// Lang("bad") = ""
|
||||
// Lang("1.21") = ""
|
||||
func Lang(x string) string {
|
||||
v := lang(stripGo(x))
|
||||
if v == "" {
|
||||
return ""
|
||||
}
|
||||
return x[:2+len(v)] // "go"+v without allocation
|
||||
}
|
||||
|
||||
// Compare returns -1, 0, or +1 depending on whether
|
||||
// x < y, x == y, or x > y, interpreted as Go versions.
|
||||
// The versions x and y must begin with a "go" prefix: "go1.21" not "1.21".
|
||||
// Invalid versions, including the empty string, compare less than
|
||||
// valid versions and equal to each other.
|
||||
// The language version "go1.21" compares less than the
|
||||
// release candidate and eventual releases "go1.21rc1" and "go1.21.0".
|
||||
// Custom toolchain suffixes are ignored during comparison:
|
||||
// "go1.21.0" and "go1.21.0-bigcorp" are equal.
|
||||
func Compare(x, y string) int { return compare(stripGo(x), stripGo(y)) }
|
||||
|
||||
// IsValid reports whether the version x is valid.
|
||||
func IsValid(x string) bool { return isValid(stripGo(x)) }
|
||||
|
||||
// stripGo converts from a "go1.21" version to a "1.21" version.
|
||||
// If v does not start with "go", stripGo returns the empty string (a known invalid version).
|
||||
func stripGo(v string) string {
|
||||
v, _, _ = strings.Cut(v, "-") // strip -bigcorp suffix.
|
||||
if len(v) < 2 || v[:2] != "go" {
|
||||
return ""
|
||||
}
|
||||
return v[2:]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue