chore(deps): bump github.com/coreos/go-oidc/v3 from 3.4.0 to 3.5.0 (#404)

Bumps [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/coreos/go-oidc/releases)
- [Commits](https://github.com/coreos/go-oidc/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: github.com/coreos/go-oidc/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot]
2023-01-22 16:54:53 -05:00
committed by GitHub
parent 24e207c0c6
commit a82b883276
218 changed files with 18885 additions and 6663 deletions

3
vendor/golang.org/x/tools/AUTHORS generated vendored
View File

@ -1,3 +0,0 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at http://tip.golang.org/AUTHORS.

View File

@ -1,3 +0,0 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

View File

@ -17,32 +17,47 @@
// developer tools, which will then be able to consume both Go 1.7 and
// Go 1.8 export data files, so they will work before and after the
// Go update. (See discussion at https://golang.org/issue/15651.)
//
package gcexportdata // import "golang.org/x/tools/go/gcexportdata"
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"go/token"
"go/types"
"io"
"io/ioutil"
"os/exec"
"golang.org/x/tools/go/internal/gcimporter"
)
// Find returns the name of an object (.o) or archive (.a) file
// containing type information for the specified import path,
// using the workspace layout conventions of go/build.
// using the go command.
// If no file was found, an empty filename is returned.
//
// A relative srcDir is interpreted relative to the current working directory.
//
// Find also returns the package's resolved (canonical) import path,
// reflecting the effects of srcDir and vendoring on importPath.
//
// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
// which is more efficient.
func Find(importPath, srcDir string) (filename, path string) {
return gcimporter.FindPkg(importPath, srcDir)
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
cmd.Dir = srcDir
out, err := cmd.CombinedOutput()
if err != nil {
return "", ""
}
var data struct {
ImportPath string
Export string
}
json.Unmarshal(out, &data)
return data.Export, data.ImportPath
}
// NewReader returns a reader for the export data section of an object
@ -50,11 +65,24 @@ func Find(importPath, srcDir string) (filename, path string) {
// additional trailing data beyond the end of the export data.
func NewReader(r io.Reader) (io.Reader, error) {
buf := bufio.NewReader(r)
_, err := gcimporter.FindExportData(buf)
// If we ever switch to a zip-like archive format with the ToC
// at the end, we can return the correct portion of export data,
// but for now we must return the entire rest of the file.
return buf, err
_, size, err := gcimporter.FindExportData(buf)
if err != nil {
return nil, err
}
if size >= 0 {
// We were given an archive and found the __.PKGDEF in it.
// This tells us the size of the export data, and we don't
// need to return the entire file.
return &io.LimitedReader{
R: buf,
N: size,
}, nil
} else {
// We were given an object file. As such, we don't know how large
// the export data is and must return the entire file.
return buf, nil
}
}
// Read reads export data from in, decodes it, and returns type
@ -88,13 +116,29 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package,
// The indexed export format starts with an 'i'; the older
// binary export format starts with a 'c', 'd', or 'v'
// (from "version"). Select appropriate importer.
if len(data) > 0 && data[0] == 'i' {
_, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path)
return pkg, err
}
if len(data) > 0 {
switch data[0] {
case 'i':
_, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path)
return pkg, err
_, pkg, err := gcimporter.BImportData(fset, imports, data, path)
return pkg, err
case 'v', 'c', 'd':
_, pkg, err := gcimporter.BImportData(fset, imports, data, path)
return pkg, err
case 'u':
_, pkg, err := gcimporter.UImportData(fset, imports, data[1:], path)
return pkg, err
default:
l := len(data)
if l > 10 {
l = 10
}
return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), path)
}
}
return nil, fmt.Errorf("empty export data for %s", path)
}
// Write writes encoded type information for the specified package to out.

View File

@ -23,6 +23,8 @@ import (
// or to control the FileSet or access the imports map populated during
// package loading.
//
// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
// which is more efficient.
func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom {
return importer{fset, imports}
}

View File

@ -34,20 +34,19 @@ import (
// (suspected) format errors, and whenever a change is made to the format.
const debugFormat = false // default: false
// If trace is set, debugging output is printed to std out.
const trace = 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 IMPLEMEMTED 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
// 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

View File

@ -74,9 +74,10 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []
pathList: []string{""}, // empty string is mapped to 0
fake: fakeFileSet{
fset: fset,
files: make(map[string]*token.File),
files: make(map[string]*fileInfo),
},
}
defer p.fake.setLines() // set lines for files in fset
// read version info
var versionstr string
@ -338,37 +339,49 @@ func (p *importer) pos() token.Pos {
// Synthesize a token.Pos
type fakeFileSet struct {
fset *token.FileSet
files map[string]*token.File
files map[string]*fileInfo
}
type fileInfo struct {
file *token.File
lastline int
}
const maxlines = 64 * 1024
func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
// TODO(mdempsky): Make use of column.
// Since we don't know the set of needed file positions, we
// reserve maxlines positions per file.
const maxlines = 64 * 1024
// Since we don't know the set of needed file positions, we reserve maxlines
// positions per file. We delay calling token.File.SetLines until all
// positions have been calculated (by way of fakeFileSet.setLines), so that
// we can avoid setting unnecessary lines. See also golang/go#46586.
f := s.files[file]
if f == nil {
f = s.fset.AddFile(file, -1, maxlines)
f = &fileInfo{file: s.fset.AddFile(file, -1, maxlines)}
s.files[file] = f
// Allocate the fake linebreak indices on first use.
// TODO(adonovan): opt: save ~512KB using a more complex scheme?
fakeLinesOnce.Do(func() {
fakeLines = make([]int, maxlines)
for i := range fakeLines {
fakeLines[i] = i
}
})
f.SetLines(fakeLines)
}
if line > maxlines {
line = 1
}
if line > f.lastline {
f.lastline = line
}
// Treat the file as if it contained only newlines
// and column=1: use the line number as the offset.
return f.Pos(line - 1)
// Return a fake position assuming that f.file consists only of newlines.
return token.Pos(f.file.Base() + line - 1)
}
func (s *fakeFileSet) setLines() {
fakeLinesOnce.Do(func() {
fakeLines = make([]int, maxlines)
for i := range fakeLines {
fakeLines[i] = i
}
})
for _, f := range s.files {
f.file.SetLines(fakeLines[:f.lastline])
}
}
var (

View File

@ -16,7 +16,7 @@ import (
"strings"
)
func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
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)
@ -28,7 +28,8 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
fmt.Printf("header: %s", hdr)
}
s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
size, err = strconv.Atoi(s)
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")
return
@ -42,8 +43,8 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
// 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".
//
func FindExportData(r *bufio.Reader) (hdr string, err error) {
// 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) {
// Read first line to make sure this is an object file.
line, err := r.ReadSlice('\n')
if err != nil {
@ -54,7 +55,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
if string(line) == "!<arch>\n" {
// Archive file. Scan to __.PKGDEF.
var name string
if name, _, err = readGopackHeader(r); err != nil {
if name, size, err = readGopackHeader(r); err != nil {
return
}
@ -70,6 +71,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
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.
@ -86,8 +88,12 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
err = fmt.Errorf("can't find export data (%v)", err)
return
}
size -= int64(len(line))
}
hdr = string(line)
if size < 0 {
size = -1
}
return
}

View File

@ -29,8 +29,14 @@ import (
"text/scanner"
)
// debugging/development support
const debug = false
const (
// Enable debug during development: it adds some additional checks, and
// prevents errors from being recovered.
debug = false
// If trace is set, debugging output is printed to std out.
trace = false
)
var pkgExts = [...]string{".a", ".o"}
@ -39,7 +45,6 @@ var pkgExts = [...]string{".a", ".o"}
// the build.Default build.Context). A relative srcDir is interpreted
// relative to the current working directory.
// If no file was found, an empty filename is returned.
//
func FindPkg(path, srcDir string) (filename, id string) {
if path == "" {
return
@ -103,7 +108,6 @@ func FindPkg(path, srcDir string) (filename, id string) {
// If packages[id] contains the completely imported package, that package
// can be used directly, and there is no need to call this function (but
// there is also no harm but for extra time used).
//
func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) {
// support for parser error handling
defer func() {
@ -127,7 +131,6 @@ func ImportData(packages map[string]*types.Package, filename, id string, data io
// Import imports a gc-generated package given its import path and srcDir, adds
// the corresponding package object to the packages map, and returns the object.
// The packages map must contain all packages already imported.
//
func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) {
var rc io.ReadCloser
var filename, id string
@ -178,8 +181,9 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
defer rc.Close()
var hdr string
var size int64
buf := bufio.NewReader(rc)
if hdr, err = FindExportData(buf); err != nil {
if hdr, size, err = FindExportData(buf); err != nil {
return
}
@ -207,10 +211,27 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
// The indexed export format starts with an 'i'; the older
// binary export format starts with a 'c', 'd', or 'v'
// (from "version"). Select appropriate importer.
if len(data) > 0 && data[0] == 'i' {
_, pkg, err = IImportData(fset, packages, data[1:], id)
} else {
_, pkg, err = BImportData(fset, packages, data, id)
if len(data) > 0 {
switch data[0] {
case 'i':
_, pkg, err := IImportData(fset, packages, data[1:], id)
return pkg, err
case 'v', 'c', 'd':
_, pkg, err := BImportData(fset, packages, data, id)
return pkg, err
case 'u':
_, pkg, err := UImportData(fset, packages, data[1:size], id)
return pkg, err
default:
l := len(data)
if l > 10 {
l = 10
}
return nil, fmt.Errorf("unexpected export data with prefix %q for path %s", string(data[:l]), id)
}
}
default:
@ -342,8 +363,9 @@ func (p *parser) expectKeyword(keyword string) {
// ----------------------------------------------------------------------------
// Qualified and unqualified names
// PackageId = string_lit .
// parsePackageID parses a PackageId:
//
// PackageId = string_lit .
func (p *parser) parsePackageID() string {
id, err := strconv.Unquote(p.expect(scanner.String))
if err != nil {
@ -357,13 +379,16 @@ func (p *parser) parsePackageID() string {
return id
}
// PackageName = ident .
// parsePackageName parse a PackageName:
//
// PackageName = ident .
func (p *parser) parsePackageName() string {
return p.expect(scanner.Ident)
}
// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
// parseDotIdent parses a dotIdentifier:
//
// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
func (p *parser) parseDotIdent() string {
ident := ""
if p.tok != scanner.Int {
@ -380,8 +405,9 @@ func (p *parser) parseDotIdent() string {
return ident
}
// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
// parseQualifiedName parses a QualifiedName:
//
// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
func (p *parser) parseQualifiedName() (id, name string) {
p.expect('@')
id = p.parsePackageID()
@ -404,7 +430,6 @@ func (p *parser) parseQualifiedName() (id, name string) {
// id identifies a package, usually by a canonical package path like
// "encoding/json" but possibly by a non-canonical import path like
// "./json".
//
func (p *parser) getPkg(id, name string) *types.Package {
// package unsafe is not in the packages maps - handle explicitly
if id == "unsafe" {
@ -440,7 +465,6 @@ func (p *parser) getPkg(id, name string) *types.Package {
// parseExportedName is like parseQualifiedName, but
// the package id is resolved to an imported *types.Package.
//
func (p *parser) parseExportedName() (pkg *types.Package, name string) {
id, name := p.parseQualifiedName()
pkg = p.getPkg(id, "")
@ -450,8 +474,9 @@ func (p *parser) parseExportedName() (pkg *types.Package, name string) {
// ----------------------------------------------------------------------------
// Types
// BasicType = identifier .
// parseBasicType parses a BasicType:
//
// BasicType = identifier .
func (p *parser) parseBasicType() types.Type {
id := p.expect(scanner.Ident)
obj := types.Universe.Lookup(id)
@ -462,8 +487,9 @@ func (p *parser) parseBasicType() types.Type {
return nil
}
// ArrayType = "[" int_lit "]" Type .
// parseArrayType parses an ArrayType:
//
// ArrayType = "[" int_lit "]" Type .
func (p *parser) parseArrayType(parent *types.Package) types.Type {
// "[" already consumed and lookahead known not to be "]"
lit := p.expect(scanner.Int)
@ -476,8 +502,9 @@ func (p *parser) parseArrayType(parent *types.Package) types.Type {
return types.NewArray(elem, n)
}
// MapType = "map" "[" Type "]" Type .
// parseMapType parses a MapType:
//
// MapType = "map" "[" Type "]" Type .
func (p *parser) parseMapType(parent *types.Package) types.Type {
p.expectKeyword("map")
p.expect('[')
@ -487,7 +514,9 @@ func (p *parser) parseMapType(parent *types.Package) types.Type {
return types.NewMap(key, elem)
}
// Name = identifier | "?" | QualifiedName .
// parseName parses a Name:
//
// Name = identifier | "?" | QualifiedName .
//
// For unqualified and anonymous names, the returned package is the parent
// package unless parent == nil, in which case the returned package is the
@ -499,7 +528,6 @@ func (p *parser) parseMapType(parent *types.Package) types.Type {
// it doesn't exist yet) unless materializePkg is set (which creates an
// unnamed package with valid package path). In the latter case, a
// subsequent import clause is expected to provide a name for the package.
//
func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) {
pkg = parent
if pkg == nil {
@ -533,8 +561,9 @@ func deref(typ types.Type) types.Type {
return typ
}
// Field = Name Type [ string_lit ] .
// parseField parses a Field:
//
// Field = Name Type [ string_lit ] .
func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
pkg, name := p.parseName(parent, true)
@ -577,9 +606,10 @@ func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
}
// StructType = "struct" "{" [ FieldList ] "}" .
// FieldList = Field { ";" Field } .
// parseStructType parses a StructType:
//
// StructType = "struct" "{" [ FieldList ] "}" .
// FieldList = Field { ";" Field } .
func (p *parser) parseStructType(parent *types.Package) types.Type {
var fields []*types.Var
var tags []string
@ -604,8 +634,9 @@ func (p *parser) parseStructType(parent *types.Package) types.Type {
return types.NewStruct(fields, tags)
}
// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
// parseParameter parses a Parameter:
//
// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
_, name := p.parseName(nil, false)
// remove gc-specific parameter numbering
@ -629,9 +660,10 @@ func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
return
}
// Parameters = "(" [ ParameterList ] ")" .
// ParameterList = { Parameter "," } Parameter .
// parseParameters parses a Parameters:
//
// Parameters = "(" [ ParameterList ] ")" .
// ParameterList = { Parameter "," } Parameter .
func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
p.expect('(')
for p.tok != ')' && p.tok != scanner.EOF {
@ -652,9 +684,10 @@ func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
return
}
// Signature = Parameters [ Result ] .
// Result = Type | Parameters .
// parseSignature parses a Signature:
//
// Signature = Parameters [ Result ] .
// Result = Type | Parameters .
func (p *parser) parseSignature(recv *types.Var) *types.Signature {
params, isVariadic := p.parseParameters()
@ -671,14 +704,15 @@ func (p *parser) parseSignature(recv *types.Var) *types.Signature {
return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic)
}
// InterfaceType = "interface" "{" [ MethodList ] "}" .
// MethodList = Method { ";" Method } .
// Method = Name Signature .
// parseInterfaceType parses an InterfaceType:
//
// InterfaceType = "interface" "{" [ MethodList ] "}" .
// MethodList = Method { ";" Method } .
// Method = Name Signature .
//
// The methods of embedded interfaces are always "inlined"
// by the compiler and thus embedded interfaces are never
// visible in the export data.
//
func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
var methods []*types.Func
@ -699,8 +733,9 @@ func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
return newInterface(methods, nil).Complete()
}
// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
// parseChanType parses a ChanType:
//
// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
func (p *parser) parseChanType(parent *types.Package) types.Type {
dir := types.SendRecv
if p.tok == scanner.Ident {
@ -718,17 +753,18 @@ func (p *parser) parseChanType(parent *types.Package) types.Type {
return types.NewChan(dir, elem)
}
// Type =
// BasicType | TypeName | ArrayType | SliceType | StructType |
// PointerType | FuncType | InterfaceType | MapType | ChanType |
// "(" Type ")" .
// parseType parses a Type:
//
// BasicType = ident .
// TypeName = ExportedName .
// SliceType = "[" "]" Type .
// PointerType = "*" Type .
// FuncType = "func" Signature .
// Type =
// BasicType | TypeName | ArrayType | SliceType | StructType |
// PointerType | FuncType | InterfaceType | MapType | ChanType |
// "(" Type ")" .
//
// BasicType = ident .
// TypeName = ExportedName .
// SliceType = "[" "]" Type .
// PointerType = "*" Type .
// FuncType = "func" Signature .
func (p *parser) parseType(parent *types.Package) types.Type {
switch p.tok {
case scanner.Ident:
@ -780,16 +816,18 @@ func (p *parser) parseType(parent *types.Package) types.Type {
// ----------------------------------------------------------------------------
// Declarations
// ImportDecl = "import" PackageName PackageId .
// parseImportDecl parses an ImportDecl:
//
// ImportDecl = "import" PackageName PackageId .
func (p *parser) parseImportDecl() {
p.expectKeyword("import")
name := p.parsePackageName()
p.getPkg(p.parsePackageID(), name)
}
// int_lit = [ "+" | "-" ] { "0" ... "9" } .
// parseInt parses an int_lit:
//
// int_lit = [ "+" | "-" ] { "0" ... "9" } .
func (p *parser) parseInt() string {
s := ""
switch p.tok {
@ -802,8 +840,9 @@ func (p *parser) parseInt() string {
return s + p.expect(scanner.Int)
}
// number = int_lit [ "p" int_lit ] .
// parseNumber parses a number:
//
// number = int_lit [ "p" int_lit ] .
func (p *parser) parseNumber() (typ *types.Basic, val constant.Value) {
// mantissa
mant := constant.MakeFromLiteral(p.parseInt(), token.INT, 0)
@ -838,13 +877,14 @@ func (p *parser) parseNumber() (typ *types.Basic, val constant.Value) {
return
}
// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
// bool_lit = "true" | "false" .
// complex_lit = "(" float_lit "+" float_lit "i" ")" .
// rune_lit = "(" int_lit "+" int_lit ")" .
// string_lit = `"` { unicode_char } `"` .
// parseConstDecl parses a ConstDecl:
//
// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
// bool_lit = "true" | "false" .
// complex_lit = "(" float_lit "+" float_lit "i" ")" .
// rune_lit = "(" int_lit "+" int_lit ")" .
// string_lit = `"` { unicode_char } `"` .
func (p *parser) parseConstDecl() {
p.expectKeyword("const")
pkg, name := p.parseExportedName()
@ -914,8 +954,9 @@ func (p *parser) parseConstDecl() {
pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val))
}
// TypeDecl = "type" ExportedName Type .
// parseTypeDecl parses a TypeDecl:
//
// TypeDecl = "type" ExportedName Type .
func (p *parser) parseTypeDecl() {
p.expectKeyword("type")
pkg, name := p.parseExportedName()
@ -933,8 +974,9 @@ func (p *parser) parseTypeDecl() {
}
}
// VarDecl = "var" ExportedName Type .
// parseVarDecl parses a VarDecl:
//
// VarDecl = "var" ExportedName Type .
func (p *parser) parseVarDecl() {
p.expectKeyword("var")
pkg, name := p.parseExportedName()
@ -942,9 +984,10 @@ func (p *parser) parseVarDecl() {
pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
}
// Func = Signature [ Body ] .
// Body = "{" ... "}" .
// parseFunc parses a Func:
//
// Func = Signature [ Body ] .
// Body = "{" ... "}" .
func (p *parser) parseFunc(recv *types.Var) *types.Signature {
sig := p.parseSignature(recv)
if p.tok == '{' {
@ -961,9 +1004,10 @@ func (p *parser) parseFunc(recv *types.Var) *types.Signature {
return sig
}
// MethodDecl = "func" Receiver Name Func .
// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
// parseMethodDecl parses a MethodDecl:
//
// MethodDecl = "func" Receiver Name Func .
// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
func (p *parser) parseMethodDecl() {
// "func" already consumed
p.expect('(')
@ -986,8 +1030,9 @@ func (p *parser) parseMethodDecl() {
base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
}
// FuncDecl = "func" ExportedName Func .
// parseFuncDecl parses a FuncDecl:
//
// FuncDecl = "func" ExportedName Func .
func (p *parser) parseFuncDecl() {
// "func" already consumed
pkg, name := p.parseExportedName()
@ -995,8 +1040,9 @@ func (p *parser) parseFuncDecl() {
pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ))
}
// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
// parseDecl parses a Decl:
//
// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
func (p *parser) parseDecl() {
if p.tok == scanner.Ident {
switch p.lit {
@ -1023,9 +1069,10 @@ func (p *parser) parseDecl() {
// ----------------------------------------------------------------------------
// Export
// Export = "PackageClause { Decl } "$$" .
// PackageClause = "package" PackageName [ "safe" ] "\n" .
// parseExport parses an Export:
//
// Export = "PackageClause { Decl } "$$" .
// PackageClause = "package" PackageName [ "safe" ] "\n" .
func (p *parser) parseExport() *types.Package {
p.expectKeyword("package")
name := p.parsePackageName()

View File

@ -11,6 +11,7 @@ package gcimporter
import (
"bytes"
"encoding/binary"
"fmt"
"go/ast"
"go/constant"
"go/token"
@ -19,6 +20,8 @@ import (
"math/big"
"reflect"
"sort"
"strconv"
"strings"
"golang.org/x/tools/internal/typeparams"
)
@ -33,15 +36,15 @@ const bundleVersion = 0
// The package path of the top-level package will not be recorded,
// so that calls to IImportData can override with a provided package path.
func IExportData(out io.Writer, fset *token.FileSet, pkg *types.Package) error {
return iexportCommon(out, fset, false, []*types.Package{pkg})
return iexportCommon(out, fset, false, iexportVersion, []*types.Package{pkg})
}
// IExportBundle writes an indexed export bundle for pkgs to out.
func IExportBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {
return iexportCommon(out, fset, true, pkgs)
return iexportCommon(out, fset, true, iexportVersion, pkgs)
}
func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, pkgs []*types.Package) (err error) {
func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int, pkgs []*types.Package) (err error) {
if !debug {
defer func() {
if e := recover(); e != nil {
@ -57,9 +60,11 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, pkgs []*type
p := iexporter{
fset: fset,
version: version,
allPkgs: map[*types.Package]bool{},
stringIndex: map[string]uint64{},
declIndex: map[types.Object]uint64{},
tparamNames: map[types.Object]string{},
typIndex: map[types.Type]uint64{},
}
if !bundle {
@ -119,7 +124,7 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, pkgs []*type
if bundle {
hdr.uint64(bundleVersion)
}
hdr.uint64(iexportVersion)
hdr.uint64(uint64(p.version))
hdr.uint64(uint64(p.strings.Len()))
hdr.uint64(dataLen)
@ -136,8 +141,12 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, pkgs []*type
// non-compiler tools and includes a complete package description
// (i.e., name and height).
func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
type pkgObj struct {
obj types.Object
name string // qualified name; differs from obj.Name for type params
}
// Build a map from packages to objects from that package.
pkgObjs := map[*types.Package][]types.Object{}
pkgObjs := map[*types.Package][]pkgObj{}
// For the main index, make sure to include every package that
// we reference, even if we're not exporting (or reexporting)
@ -150,7 +159,8 @@ func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
}
for obj := range index {
pkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], obj)
name := w.p.exportName(obj)
pkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], pkgObj{obj, name})
}
var pkgs []*types.Package
@ -158,7 +168,7 @@ func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
pkgs = append(pkgs, pkg)
sort.Slice(objs, func(i, j int) bool {
return indexName(objs[i]) < indexName(objs[j])
return objs[i].name < objs[j].name
})
}
@ -175,29 +185,25 @@ func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
objs := pkgObjs[pkg]
w.uint64(uint64(len(objs)))
for _, obj := range objs {
w.string(indexName(obj))
w.uint64(index[obj])
w.string(obj.name)
w.uint64(index[obj.obj])
}
}
}
// indexName returns the 'indexed' name of an object. It differs from
// obj.Name() only for type parameter names, where we include the subscripted
// type parameter ID.
//
// TODO(rfindley): remove this once we no longer need subscripts.
func indexName(obj types.Object) (res string) {
if _, ok := obj.(*types.TypeName); ok {
if tparam, ok := obj.Type().(*typeparams.TypeParam); ok {
return types.TypeString(tparam, func(*types.Package) string { return "" })
}
// exportName returns the 'exported' name of an object. It differs from
// obj.Name() only for type parameters (see tparamExportName for details).
func (p *iexporter) exportName(obj types.Object) (res string) {
if name := p.tparamNames[obj]; name != "" {
return name
}
return obj.Name()
}
type iexporter struct {
fset *token.FileSet
out *bytes.Buffer
fset *token.FileSet
out *bytes.Buffer
version int
localpkg *types.Package
@ -211,9 +217,21 @@ type iexporter struct {
strings intWriter
stringIndex map[string]uint64
data0 intWriter
declIndex map[types.Object]uint64
typIndex map[types.Type]uint64
data0 intWriter
declIndex map[types.Object]uint64
tparamNames map[types.Object]string // typeparam->exported name
typIndex map[types.Type]uint64
indent int // for tracing support
}
func (p *iexporter) trace(format string, args ...interface{}) {
if !trace {
// Call sites should also be guarded, but having this check here allows
// easily enabling/disabling debug trace statements.
return
}
fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
}
// stringOff returns the offset of s within the string section.
@ -233,13 +251,16 @@ func (p *iexporter) stringOff(s string) uint64 {
// 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.
assert(obj.Pkg() != types.Unsafe)
// Caller should not ask us to do export it.
if obj.Pkg() == types.Unsafe {
panic("cannot export package unsafe")
}
if _, ok := p.declIndex[obj]; ok {
return
}
p.declIndex[obj] = ^uint64(0) // mark n present in work queue
p.declIndex[obj] = ^uint64(0) // mark obj present in work queue
p.declTodo.pushTail(obj)
}
@ -262,6 +283,14 @@ func (w *exportWriter) exportPath(pkg *types.Package) string {
}
func (p *iexporter) doDecl(obj types.Object) {
if trace {
p.trace("exporting decl %v (%T)", obj, obj)
p.indent++
defer func() {
p.indent--
p.trace("=> %s", obj)
}()
}
w := p.newWriter()
w.setPkg(obj.Pkg(), false)
@ -284,14 +313,15 @@ func (p *iexporter) doDecl(obj types.Object) {
w.tag('G')
}
w.pos(obj.Pos())
// The tparam list of the function type is the
// declaration of the type params. So, write out the type
// params right now. Then those type params will be
// referenced via their type offset (via typOff) in all
// other places in the signature and function that they
// are used.
// The tparam list of the function type is the declaration of the type
// params. So, write out the type params right now. Then those type params
// will be referenced via their type offset (via typOff) in all other
// places in the signature and function where they are used.
//
// 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 {
w.tparamList(tparams, obj.Pkg())
w.tparamList(obj.Name(), tparams, obj.Pkg())
}
w.signature(sig)
@ -306,7 +336,15 @@ func (p *iexporter) doDecl(obj types.Object) {
if tparam, ok := t.(*typeparams.TypeParam); ok {
w.tag('P')
w.pos(obj.Pos())
w.typ(tparam.Constraint(), obj.Pkg())
constraint := tparam.Constraint()
if p.version >= iexportVersionGo1_18 {
implicit := false
if iface, _ := constraint.(*types.Interface); iface != nil {
implicit = typeparams.IsImplicit(iface)
}
w.bool(implicit)
}
w.typ(constraint, obj.Pkg())
break
}
@ -331,7 +369,9 @@ func (p *iexporter) doDecl(obj types.Object) {
w.pos(obj.Pos())
if typeparams.ForNamed(named).Len() > 0 {
w.tparamList(typeparams.ForNamed(named), obj.Pkg())
// 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())
}
underlying := obj.Type().Underlying()
@ -348,6 +388,17 @@ func (p *iexporter) doDecl(obj types.Object) {
w.pos(m.Pos())
w.string(m.Name())
sig, _ := m.Type().(*types.Signature)
// 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 {
prefix := obj.Name() + "." + m.Name()
for i := 0; i < rparams.Len(); i++ {
rparam := rparams.At(i)
name := tparamExportName(prefix, rparam)
w.p.tparamNames[rparam.Obj()] = name
}
}
w.param(sig.Recv())
w.signature(sig)
}
@ -364,7 +415,7 @@ func (w *exportWriter) tag(tag byte) {
}
func (w *exportWriter) pos(pos token.Pos) {
if iexportVersion >= iexportVersionPosCol {
if w.p.version >= iexportVersionPosCol {
w.posV1(pos)
} else {
w.posV0(pos)
@ -447,9 +498,11 @@ func (w *exportWriter) pkg(pkg *types.Package) {
}
func (w *exportWriter) qualifiedIdent(obj types.Object) {
name := w.p.exportName(obj)
// Ensure any referenced declarations are written out too.
w.p.pushDecl(obj)
w.string(indexName(obj))
w.string(name)
w.pkg(obj.Pkg())
}
@ -483,6 +536,14 @@ func (w *exportWriter) startType(k itag) {
}
func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
if trace {
w.p.trace("exporting type %s (%T)", t, t)
w.p.indent++
defer func() {
w.p.indent--
w.p.trace("=> %s", t)
}()
}
switch t := t.(type) {
case *types.Named:
if targs := typeparams.NamedTypeArgs(t); targs.Len() > 0 {
@ -619,14 +680,49 @@ func (w *exportWriter) typeList(ts *typeparams.TypeList, pkg *types.Package) {
}
}
func (w *exportWriter) tparamList(list *typeparams.TypeParamList, pkg *types.Package) {
func (w *exportWriter) tparamList(prefix string, list *typeparams.TypeParamList, pkg *types.Package) {
ll := uint64(list.Len())
w.uint64(ll)
for i := 0; i < list.Len(); i++ {
tparam := list.At(i)
// Set the type parameter exportName before exporting its type.
exportName := tparamExportName(prefix, tparam)
w.p.tparamNames[tparam.Obj()] = exportName
w.typ(list.At(i), pkg)
}
}
const blankMarker = "$"
// tparamExportName returns the 'exported' name of a type parameter, which
// 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 {
assert(prefix != "")
name := tparam.Obj().Name()
if name == "_" {
name = blankMarker + strconv.Itoa(tparam.Index())
}
return prefix + "." + name
}
// tparamName returns the real name of a type parameter, after stripping its
// qualifying prefix and reverting blank-name encoding. See tparamExportName
// for details.
func tparamName(exportName string) string {
// Remove the "path" from the type param name that makes it unique.
ix := strings.LastIndex(exportName, ".")
if ix < 0 {
errorf("malformed type parameter export name %s: missing prefix", exportName)
}
name := exportName[ix+1:]
if strings.HasPrefix(name, blankMarker) {
return "_"
}
return name
}
func (w *exportWriter) paramList(tup *types.Tuple) {
n := tup.Len()
w.uint64(uint64(n))
@ -643,6 +739,9 @@ func (w *exportWriter) param(obj types.Object) {
func (w *exportWriter) value(typ types.Type, v constant.Value) {
w.typ(typ, nil)
if w.p.version >= iexportVersionGo1_18 {
w.int64(int64(v.Kind()))
}
switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
case types.IsBoolean:
@ -832,7 +931,7 @@ func (w *exportWriter) localIdent(obj types.Object) {
return
}
name := indexName(obj)
name := obj.Name()
if name == "_" {
w.string("_")
return

View File

@ -17,7 +17,9 @@ import (
"go/token"
"go/types"
"io"
"math/big"
"sort"
"strings"
"golang.org/x/tools/internal/typeparams"
)
@ -45,16 +47,14 @@ func (r *intReader) uint64() uint64 {
// Keep this in sync with constants in iexport.go.
const (
iexportVersionGo1_11 = 0
iexportVersionPosCol = 1
// TODO: before release, change this back to 2.
iexportVersionGenerics = iexportVersionPosCol
iexportVersionCurrent = iexportVersionGenerics
iexportVersionGo1_11 = 0
iexportVersionPosCol = 1
iexportVersionGo1_18 = 2
iexportVersionGenerics = 2
)
type ident struct {
pkg string
pkg *types.Package
name string
}
@ -101,7 +101,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
if !debug {
defer func() {
if e := recover(); e != nil {
if version > currentVersion {
if bundle {
err = fmt.Errorf("%v", e)
} 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)
@ -123,9 +125,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
version = int64(r.uint64())
switch version {
case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
default:
if version > iexportVersionGenerics {
if version > iexportVersionGo1_18 {
errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
} else {
errorf("unknown iexport format version %d", version)
@ -141,9 +143,8 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
r.Seek(sLen+dLen, io.SeekCurrent)
p := iimporter{
exportVersion: version,
ipath: path,
version: int(version),
version: int(version),
ipath: path,
stringData: stringData,
stringCache: make(map[uint64]string),
@ -153,14 +154,15 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
pkgIndex: make(map[*types.Package]map[string]uint64),
typCache: make(map[uint64]types.Type),
// Separate map for typeparams, keyed by their package and unique
// name (name with subscript).
// name.
tparamIndex: make(map[ident]types.Type),
fake: fakeFileSet{
fset: fset,
files: make(map[string]*token.File),
files: make(map[string]*fileInfo),
},
}
defer p.fake.setLines() // set lines for files in fset
for i, pt := range predeclared() {
p.typCache[uint64(i)] = pt
@ -238,6 +240,15 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
pkg.MarkComplete()
}
// 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(),
// 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)
}
for _, typ := range p.interfaceList {
typ.Complete()
}
@ -245,10 +256,14 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
return pkgs, nil
}
type setConstraintArgs struct {
t *typeparams.TypeParam
constraint types.Type
}
type iimporter struct {
exportVersion int64
ipath string
version int
version int
ipath string
stringData []byte
stringCache map[uint64]string
@ -261,9 +276,31 @@ type iimporter struct {
fake fakeFileSet
interfaceList []*types.Interface
// Arguments for calls to SetConstraint that are deferred due to recursive types
later []setConstraintArgs
indent int // for tracing support
}
func (p *iimporter) trace(format string, args ...interface{}) {
if !trace {
// Call sites should also be guarded, but having this check here allows
// easily enabling/disabling debug trace statements.
return
}
fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...)
}
func (p *iimporter) doDecl(pkg *types.Package, name string) {
if debug {
p.trace("import decl %s", name)
p.indent++
defer func() {
p.indent--
p.trace("=> %s", name)
}()
}
// See if we've already imported this declaration.
if obj := pkg.Scope().Lookup(name); obj != nil {
return
@ -305,7 +342,7 @@ func (p *iimporter) pkgAt(off uint64) *types.Package {
}
func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
if t, ok := p.typCache[off]; ok && canReuse(base, t) {
return t
}
@ -317,12 +354,30 @@ func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
r.declReader.Reset(p.declData[off-predeclReserved:])
t := r.doType(base)
if base == nil || !isInterface(t) {
if canReuse(base, t) {
p.typCache[off] = t
}
return t
}
// canReuse reports whether the type rhs on the RHS of the declaration for def
// may be re-used.
//
// Specifically, if def is non-nil and rhs is an interface type with methods, it
// may not be re-used because we have a convention of setting the receiver type
// for interface methods to def.
func canReuse(def *types.Named, rhs types.Type) bool {
if def == nil {
return true
}
iface, _ := rhs.(*types.Interface)
if iface == nil {
return true
}
// Don't use iface.Empty() here as iface may not be complete.
return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
}
type importReader struct {
p *iimporter
declReader bytes.Reader
@ -352,8 +407,7 @@ func (r *importReader) obj(name string) {
if tag == 'G' {
tparams = r.tparamList()
}
sig := r.signature(nil)
typeparams.SetForSignature(sig, tparams)
sig := r.signature(nil, nil, tparams)
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
case 'T', 'U':
@ -377,23 +431,21 @@ func (r *importReader) obj(name string) {
mpos := r.pos()
mname := r.ident()
recv := r.param()
msig := r.signature(recv)
// 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).
targs := typeparams.NamedTypeArgs(baseType(msig.Recv().Type()))
base := baseType(recv.Type())
assert(base != nil)
targs := typeparams.NamedTypeArgs(base)
var rparams []*typeparams.TypeParam
if targs.Len() > 0 {
rparams := make([]*typeparams.TypeParam, targs.Len())
rparams = make([]*typeparams.TypeParam, targs.Len())
for i := range rparams {
// TODO(rfindley): this is less tolerant than the standard library
// go/internal/gcimporter, which calls under(...) and is tolerant
// of nil rparams. Bring them in sync by making the standard
// library importer stricter.
rparams[i] = targs.At(i).(*typeparams.TypeParam)
}
typeparams.SetRecvTypeParams(msig, rparams)
}
msig := r.signature(recv, rparams, nil)
named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
}
@ -403,25 +455,34 @@ func (r *importReader) obj(name string) {
// 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.
if r.p.exportVersion < iexportVersionGenerics {
if r.p.version < iexportVersionGenerics {
errorf("unexpected type param type")
}
name0, sub := parseSubscript(name)
name0 := tparamName(name)
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
t := typeparams.NewTypeParam(tn, nil)
if sub == 0 {
errorf("name %q missing subscript", name)
}
// TODO(rfindley): can we use a different, stable ID?
// t.SetId(sub)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
id := ident{r.currPkg.Name(), name}
id := ident{r.currPkg, name}
r.p.tparamIndex[id] = t
typeparams.SetTypeParamConstraint(t, r.typ())
var implicit bool
if r.p.version >= iexportVersionGo1_18 {
implicit = r.bool()
}
constraint := r.typ()
if implicit {
iface, _ := constraint.(*types.Interface)
if iface == nil {
errorf("non-interface constraint marked implicit")
}
typeparams.MarkImplicit(iface)
}
// The constraint type may not be complete, if we
// are in the middle of a type recursion involving type
// constraints. So, we defer SetConstraint until we have
// completely set up all types in ImportData.
r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
case 'V':
typ := r.typ()
@ -439,6 +500,10 @@ func (r *importReader) declare(obj types.Object) {
func (r *importReader) value() (typ types.Type, val constant.Value) {
typ = r.typ()
if r.p.version >= iexportVersionGo1_18 {
// TODO: add support for using the kind.
_ = constant.Kind(r.int64())
}
switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
case types.IsBoolean:
@ -448,7 +513,9 @@ func (r *importReader) value() (typ types.Type, val constant.Value) {
val = constant.MakeString(r.string())
case types.IsInteger:
val = r.mpint(b)
var x big.Int
r.mpint(&x, b)
val = constant.Make(&x)
case types.IsFloat:
val = r.mpfloat(b)
@ -497,8 +564,8 @@ func intSize(b *types.Basic) (signed bool, maxBytes uint) {
return
}
func (r *importReader) mpint(b *types.Basic) constant.Value {
signed, maxBytes := intSize(b)
func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
signed, maxBytes := intSize(typ)
maxSmall := 256 - maxBytes
if signed {
@ -517,7 +584,8 @@ func (r *importReader) mpint(b *types.Basic) constant.Value {
v = ^v
}
}
return constant.MakeInt64(v)
x.SetInt64(v)
return
}
v := -n
@ -527,47 +595,23 @@ func (r *importReader) mpint(b *types.Basic) constant.Value {
if v < 1 || uint(v) > maxBytes {
errorf("weird decoding: %v, %v => %v", n, signed, v)
}
buf := make([]byte, v)
io.ReadFull(&r.declReader, buf)
// 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(buf)-1; i < j; i, j = i+1, j-1 {
buf[i], buf[j] = buf[j], buf[i]
}
x := constant.MakeFromBytes(buf)
b := make([]byte, v)
io.ReadFull(&r.declReader, b)
x.SetBytes(b)
if signed && n&1 != 0 {
x = constant.UnaryOp(token.SUB, x, 0)
x.Neg(x)
}
return x
}
func (r *importReader) mpfloat(b *types.Basic) constant.Value {
x := r.mpint(b)
if constant.Sign(x) == 0 {
return x
func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
var mant big.Int
r.mpint(&mant, typ)
var f big.Float
f.SetInt(&mant)
if f.Sign() != 0 {
f.SetMantExp(&f, int(r.int64()))
}
exp := r.int64()
switch {
case exp > 0:
x = constant.Shift(x, token.SHL, uint(exp))
// Ensure that the imported Kind is Float, else this constant may run into
// bitsize limits on overlarge integers. Eventually we can instead adopt
// the approach of CL 288632, but that CL relies on go/constant APIs that
// were introduced in go1.13.
//
// TODO(rFindley): sync the logic here with tip Go once we no longer
// support go1.12.
x = constant.ToFloat(x)
case exp < 0:
d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
x = constant.BinaryOp(x, token.QUO, d)
}
return x
return constant.Make(&f)
}
func (r *importReader) ident() string {
@ -581,7 +625,7 @@ func (r *importReader) qualifiedIdent() (*types.Package, string) {
}
func (r *importReader) pos() token.Pos {
if r.p.exportVersion >= iexportVersionPosCol {
if r.p.version >= iexportVersionPosCol {
r.posv1()
} else {
r.posv0()
@ -629,8 +673,17 @@ func isInterface(t types.Type) bool {
func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
func (r *importReader) doType(base *types.Named) types.Type {
switch k := r.kind(); k {
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.indent++
defer func() {
r.p.indent--
r.p.trace("=> %s", res)
}()
}
switch k {
default:
errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
return nil
@ -653,7 +706,7 @@ func (r *importReader) doType(base *types.Named) types.Type {
return types.NewMap(r.typ(), r.typ())
case signatureType:
r.currPkg = r.pkg()
return r.signature(nil)
return r.signature(nil, nil, nil)
case structType:
r.currPkg = r.pkg()
@ -693,7 +746,7 @@ func (r *importReader) doType(base *types.Named) types.Type {
recv = types.NewVar(token.NoPos, r.currPkg, "", base)
}
msig := r.signature(recv)
msig := r.signature(recv, nil, nil)
methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
}
@ -702,11 +755,11 @@ func (r *importReader) doType(base *types.Named) types.Type {
return typ
case typeParamType:
if r.p.exportVersion < iexportVersionGenerics {
if r.p.version < iexportVersionGenerics {
errorf("unexpected type param type")
}
pkg, name := r.qualifiedIdent()
id := ident{pkg.Name(), name}
id := ident{pkg, name}
if t, ok := r.p.tparamIndex[id]; ok {
// We're already in the process of importing this typeparam.
return t
@ -716,7 +769,7 @@ func (r *importReader) doType(base *types.Named) types.Type {
return r.p.tparamIndex[id]
case instanceType:
if r.p.exportVersion < iexportVersionGenerics {
if r.p.version < iexportVersionGenerics {
errorf("unexpected instantiation type")
}
// pos does not matter for instances: they are positioned on the original
@ -735,7 +788,7 @@ func (r *importReader) doType(base *types.Named) types.Type {
return t
case unionType:
if r.p.exportVersion < iexportVersionGenerics {
if r.p.version < iexportVersionGenerics {
errorf("unexpected instantiation type")
}
terms := make([]*typeparams.Term, r.uint64())
@ -750,11 +803,11 @@ func (r *importReader) kind() itag {
return itag(r.uint64())
}
func (r *importReader) signature(recv *types.Var) *types.Signature {
func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature {
params := r.paramList()
results := r.paramList()
variadic := params.Len() > 0 && r.bool()
return types.NewSignature(recv, params, results, variadic)
return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic)
}
func (r *importReader) tparamList() []*typeparams.TypeParam {
@ -823,23 +876,3 @@ func baseType(typ types.Type) *types.Named {
n, _ := typ.(*types.Named)
return n
}
func parseSubscript(name string) (string, uint64) {
// Extract the subscript value from the type param name. We export
// and import the subscript value, so that all type params have
// unique names.
sub := uint64(0)
startsub := -1
for i, r := range name {
if '₀' <= r && r < '₀'+10 {
if startsub == -1 {
startsub = i
}
sub = sub*10 + uint64(r-'₀')
}
}
if startsub >= 0 {
name = name[:startsub]
}
return name, sub
}

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !typeparams || !go1.18
// +build !typeparams !go1.18
//go:build !go1.18
// +build !go1.18
package gcimporter

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build typeparams && go1.18
// +build typeparams,go1.18
//go:build go1.18
// +build go1.18
package gcimporter
@ -16,5 +16,8 @@ func additionalPredeclared() []types.Type {
return []types.Type{
// comparable
types.Universe.Lookup("comparable").Type(),
// any
types.Universe.Lookup("any").Type(),
}
}

View File

@ -0,0 +1,10 @@
// 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

View File

@ -0,0 +1,10 @@
// 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

View File

@ -0,0 +1,19 @@
// 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
}

View File

@ -0,0 +1,612 @@
// 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.
// Derived from go/internal/gcimporter/ureader.go
//go:build go1.18
// +build go1.18
package gcimporter
import (
"go/token"
"go/types"
"strings"
"golang.org/x/tools/go/internal/pkgbits"
)
// A pkgReader holds the shared state for reading a unified IR package
// description.
type pkgReader struct {
pkgbits.PkgDecoder
fake fakeFileSet
ctxt *types.Context
imports map[string]*types.Package // previously imported packages, indexed by path
// lazily initialized arrays corresponding to the unified IR
// PosBase, Pkg, and Type sections, respectively.
posBases []string // position bases (i.e., file names)
pkgs []*types.Package
typs []types.Type
// laterFns holds functions that need to be invoked at the end of
// import reading.
laterFns []func()
}
// later adds a function to be invoked at the end of import reading.
func (pr *pkgReader) later(fn func()) {
pr.laterFns = append(pr.laterFns, fn)
}
// See cmd/compile/internal/noder.derivedInfo.
type derivedInfo struct {
idx pkgbits.Index
needed bool
}
// See cmd/compile/internal/noder.typeInfo.
type typeInfo struct {
idx pkgbits.Index
derived bool
}
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
s := string(data)
s = s[:strings.LastIndex(s, "\n$$\n")]
input := pkgbits.NewPkgDecoder(path, s)
pkg = readUnifiedPackage(fset, nil, imports, input)
return
}
// readUnifiedPackage reads a package description from the given
// unified IR export data decoder.
func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {
pr := pkgReader{
PkgDecoder: input,
fake: fakeFileSet{
fset: fset,
files: make(map[string]*fileInfo),
},
ctxt: ctxt,
imports: imports,
posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),
pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
typs: make([]types.Type, input.NumElems(pkgbits.RelocType)),
}
defer pr.fake.setLines()
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
pkg := r.pkg()
r.Bool() // has init
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())
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
assert(r.Len() == 0)
}
r.Sync(pkgbits.SyncEOF)
for _, fn := range pr.laterFns {
fn()
}
pkg.MarkComplete()
return pkg
}
// A reader holds the state for reading a single unified IR element
// within a package.
type reader struct {
pkgbits.Decoder
p *pkgReader
dict *readerDict
}
// A readerDict holds the state for type parameters that parameterize
// the current unified IR element.
type readerDict struct {
// bounds is a slice of typeInfos corresponding to the underlying
// bounds of the element's type parameters.
bounds []typeInfo
// 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
// instantiated while reading the current element.
derived []derivedInfo
derivedTypes []types.Type // lazily instantiated from derived
}
func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
return &reader{
Decoder: pr.NewDecoder(k, idx, marker),
p: pr,
}
}
// @@@ Positions
func (r *reader) pos() token.Pos {
r.Sync(pkgbits.SyncPos)
if !r.Bool() {
return token.NoPos
}
// TODO(mdempsky): Delta encoding.
posBase := r.posBase()
line := r.Uint()
col := r.Uint()
return r.p.fake.pos(posBase, int(line), int(col))
}
func (r *reader) posBase() string {
return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))
}
func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {
if b := pr.posBases[idx]; b != "" {
return b
}
r := pr.newReader(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.
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()
// Was: "b = token.NewLineBase(pos, filename, true, line, col)"
_, _, _ = pos, line, col
}
b := filename
pr.posBases[idx] = b
return b
}
// @@@ Packages
func (r *reader) pkg() *types.Package {
r.Sync(pkgbits.SyncPkg)
return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))
}
func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package {
// TODO(mdempsky): Consider using some non-nil pointer to indicate
// the universe scope, so we don't need to keep re-reading it.
if pkg := pr.pkgs[idx]; pkg != nil {
return pkg
}
pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg()
pr.pkgs[idx] = pkg
return pkg
}
func (r *reader) doPkg() *types.Package {
path := r.String()
switch path {
case "":
path = r.p.PkgPath()
case "builtin":
return nil // universe
case "unsafe":
return types.Unsafe
}
if pkg := r.p.imports[path]; pkg != nil {
return pkg
}
name := r.String()
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(imports)
return pkg
}
// @@@ Types
func (r *reader) typ() types.Type {
return r.p.typIdx(r.typInfo(), r.dict)
}
func (r *reader) typInfo() typeInfo {
r.Sync(pkgbits.SyncType)
if r.Bool() {
return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
}
return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}
}
func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {
idx := info.idx
var where *types.Type
if info.derived {
where = &dict.derivedTypes[idx]
idx = dict.derived[idx].idx
} else {
where = &pr.typs[idx]
}
if typ := *where; typ != nil {
return typ
}
r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
r.dict = dict
typ := r.doTyp()
assert(typ != nil)
// See comment in pkgReader.typIdx explaining how this happens.
if prev := *where; prev != nil {
return prev
}
*where = typ
return typ
}
func (r *reader) doTyp() (res types.Type) {
switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
default:
errorf("unhandled type tag: %v", tag)
panic("unreachable")
case pkgbits.TypeBasic:
return types.Typ[r.Len()]
case pkgbits.TypeNamed:
obj, targs := r.obj()
name := obj.(*types.TypeName)
if len(targs) != 0 {
t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false)
return t
}
return name.Type()
case pkgbits.TypeTypeParam:
return r.dict.tparams[r.Len()]
case pkgbits.TypeArray:
len := int64(r.Uint64())
return types.NewArray(r.typ(), len)
case pkgbits.TypeChan:
dir := types.ChanDir(r.Len())
return types.NewChan(dir, r.typ())
case pkgbits.TypeMap:
return types.NewMap(r.typ(), r.typ())
case pkgbits.TypePointer:
return types.NewPointer(r.typ())
case pkgbits.TypeSignature:
return r.signature(nil, nil, nil)
case pkgbits.TypeSlice:
return types.NewSlice(r.typ())
case pkgbits.TypeStruct:
return r.structType()
case pkgbits.TypeInterface:
return r.interfaceType()
case pkgbits.TypeUnion:
return r.unionType()
}
}
func (r *reader) structType() *types.Struct {
fields := make([]*types.Var, r.Len())
var tags []string
for i := range fields {
pos := r.pos()
pkg, name := r.selector()
ftyp := r.typ()
tag := r.String()
embedded := r.Bool()
fields[i] = types.NewField(pos, pkg, name, ftyp, embedded)
if tag != "" {
for len(tags) < i {
tags = append(tags, "")
}
tags = append(tags, tag)
}
}
return types.NewStruct(fields, tags)
}
func (r *reader) unionType() *types.Union {
terms := make([]*types.Term, r.Len())
for i := range terms {
terms[i] = types.NewTerm(r.Bool(), r.typ())
}
return types.NewUnion(terms)
}
func (r *reader) interfaceType() *types.Interface {
methods := make([]*types.Func, r.Len())
embeddeds := make([]types.Type, r.Len())
implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()
for i := range methods {
pos := r.pos()
pkg, name := r.selector()
mtyp := r.signature(nil, nil, nil)
methods[i] = types.NewFunc(pos, pkg, name, mtyp)
}
for i := range embeddeds {
embeddeds[i] = r.typ()
}
iface := types.NewInterfaceType(methods, embeddeds)
if implicit {
iface.MarkImplicit()
}
return iface
}
func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature {
r.Sync(pkgbits.SyncSignature)
params := r.params()
results := r.params()
variadic := r.Bool()
return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
}
func (r *reader) params() *types.Tuple {
r.Sync(pkgbits.SyncParams)
params := make([]*types.Var, r.Len())
for i := range params {
params[i] = r.param()
}
return types.NewTuple(params...)
}
func (r *reader) param() *types.Var {
r.Sync(pkgbits.SyncParam)
pos := r.pos()
pkg, name := r.localIdent()
typ := r.typ()
return types.NewParam(pos, pkg, name, typ)
}
// @@@ Objects
func (r *reader) obj() (types.Object, []types.Type) {
r.Sync(pkgbits.SyncObject)
assert(!r.Bool())
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
obj := pkgScope(pkg).Lookup(name)
targs := make([]types.Type, r.Len())
for i := range targs {
targs[i] = r.typ()
}
return obj, targs
}
func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
objPkg, objName := rname.qualifiedIdent()
assert(objName != "")
tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
if tag == pkgbits.ObjStub {
assert(objPkg == nil || objPkg == types.Unsafe)
return objPkg, objName
}
if objPkg.Scope().Lookup(objName) == nil {
dict := pr.objDictIdx(idx)
r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
r.dict = dict
declare := func(obj types.Object) {
objPkg.Scope().Insert(obj)
}
switch tag {
default:
panic("weird")
case pkgbits.ObjAlias:
pos := r.pos()
typ := r.typ()
declare(types.NewTypeName(pos, objPkg, objName, typ))
case pkgbits.ObjConst:
pos := r.pos()
typ := r.typ()
val := r.Value()
declare(types.NewConst(pos, objPkg, objName, typ, val))
case pkgbits.ObjFunc:
pos := r.pos()
tparams := r.typeParamNames()
sig := r.signature(nil, nil, tparams)
declare(types.NewFunc(pos, objPkg, objName, sig))
case pkgbits.ObjType:
pos := r.pos()
obj := types.NewTypeName(pos, objPkg, objName, nil)
named := types.NewNamed(obj, nil, nil)
declare(obj)
named.SetTypeParams(r.typeParamNames())
// TODO(mdempsky): Rewrite receiver types to underlying is an
// Interface? The go/types importer does this (I think because
// unit tests expected that), but cmd/compile doesn't care
// about it, so maybe we can avoid worrying about that here.
rhs := r.typ()
r.p.later(func() {
underlying := rhs.Underlying()
named.SetUnderlying(underlying)
})
for i, n := 0, r.Len(); i < n; i++ {
named.AddMethod(r.method())
}
case pkgbits.ObjVar:
pos := r.pos()
typ := r.typ()
declare(types.NewVar(pos, objPkg, objName, typ))
}
}
return objPkg, objName
}
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)
}
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()}
}
// function references follow, but reader doesn't need those
return &dict
}
func (r *reader) typeParamNames() []*types.TypeParam {
r.Sync(pkgbits.SyncTypeParamNames)
// Note: This code assumes it only processes objects without
// implement type parameters. This is currently fine, because
// reader is only used to read in exported declarations, which are
// always package scoped.
if len(r.dict.bounds) == 0 {
return nil
}
// Careful: Type parameter lists may have cycles. To allow for this,
// we construct the type parameter list in two passes: first we
// create all the TypeNames and TypeParams, then we construct and
// set the bound type.
r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds))
for i := range r.dict.bounds {
pos := r.pos()
pkg, name := r.localIdent()
tname := types.NewTypeName(pos, pkg, name, nil)
r.dict.tparams[i] = types.NewTypeParam(tname, nil)
}
typs := make([]types.Type, len(r.dict.bounds))
for i, bound := range r.dict.bounds {
typs[i] = r.p.typIdx(bound, r.dict)
}
// TODO(mdempsky): This is subtle, elaborate further.
//
// We have to save tparams outside of the closure, because
// typeParamNames() can be called multiple times with the same
// dictionary instance.
//
// Also, this needs to happen later to make sure SetUnderlying has
// been called.
//
// TODO(mdempsky): Is it safe to have a single "later" slice or do
// we need to have multiple passes? See comments on CL 386002 and
// go.dev/issue/52104.
tparams := r.dict.tparams
r.p.later(func() {
for i, typ := range typs {
tparams[i].SetConstraint(typ)
}
})
return r.dict.tparams
}
func (r *reader) method() *types.Func {
r.Sync(pkgbits.SyncMethod)
pos := r.pos()
pkg, name := r.selector()
rparams := r.typeParamNames()
sig := r.signature(r.param(), rparams, nil)
_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.
return types.NewFunc(pos, pkg, name, sig)
}
func (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) }
func (r *reader) localIdent() (*types.Package, string) { return r.ident(pkgbits.SyncLocalIdent) }
func (r *reader) selector() (*types.Package, string) { return r.ident(pkgbits.SyncSelector) }
func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) {
r.Sync(marker)
return r.pkg(), r.String()
}
// pkgScope returns pkg.Scope().
// If pkg is nil, it returns types.Universe instead.
//
// TODO(mdempsky): Remove after x/tools can depend on Go 1.19.
func pkgScope(pkg *types.Package) *types.Scope {
if pkg != nil {
return pkg.Scope()
}
return types.Universe
}

77
vendor/golang.org/x/tools/go/internal/pkgbits/codes.go generated vendored Normal file
View File

@ -0,0 +1,77 @@
// 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.
package pkgbits
// A Code is an enum value that can be encoded into bitstreams.
//
// Code types are preferable for enum types, because they allow
// Decoder to detect desyncs.
type Code interface {
// Marker returns the SyncMarker for the Code's dynamic type.
Marker() SyncMarker
// Value returns the Code's ordinal value.
Value() int
}
// A CodeVal distinguishes among go/constant.Value encodings.
type CodeVal int
func (c CodeVal) Marker() SyncMarker { return SyncVal }
func (c CodeVal) Value() int { return int(c) }
// Note: These values are public and cannot be changed without
// updating the go/types importers.
const (
ValBool CodeVal = iota
ValString
ValInt64
ValBigInt
ValBigRat
ValBigFloat
)
// A CodeType distinguishes among go/types.Type encodings.
type CodeType int
func (c CodeType) Marker() SyncMarker { return SyncType }
func (c CodeType) Value() int { return int(c) }
// Note: These values are public and cannot be changed without
// updating the go/types importers.
const (
TypeBasic CodeType = iota
TypeNamed
TypePointer
TypeSlice
TypeArray
TypeChan
TypeMap
TypeSignature
TypeStruct
TypeInterface
TypeUnion
TypeTypeParam
)
// A CodeObj distinguishes among go/types.Object encodings.
type CodeObj int
func (c CodeObj) Marker() SyncMarker { return SyncCodeObj }
func (c CodeObj) Value() int { return int(c) }
// Note: These values are public and cannot be changed without
// updating the go/types importers.
const (
ObjAlias CodeObj = iota
ObjConst
ObjType
ObjFunc
ObjVar
ObjStub
)

View File

@ -0,0 +1,433 @@
// 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.
package pkgbits
import (
"encoding/binary"
"fmt"
"go/constant"
"go/token"
"math/big"
"os"
"runtime"
"strings"
)
// A PkgDecoder provides methods for decoding a package's Unified IR
// export data.
type PkgDecoder struct {
// version is the file format version.
version uint32
// sync indicates whether the file uses sync markers.
sync bool
// pkgPath is the package path for the package to be decoded.
//
// TODO(mdempsky): Remove; unneeded since CL 391014.
pkgPath string
// elemData is the full data payload of the encoded package.
// Elements are densely and contiguously packed together.
//
// The last 8 bytes of elemData are the package fingerprint.
elemData string
// elemEnds stores the byte-offset end positions of element
// bitstreams within elemData.
//
// For example, element I's bitstream data starts at elemEnds[I-1]
// (or 0, if I==0) and ends at elemEnds[I].
//
// Note: elemEnds is indexed by absolute indices, not
// section-relative indices.
elemEnds []uint32
// elemEndsEnds stores the index-offset end positions of relocation
// sections within elemEnds.
//
// 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
}
// PkgPath returns the package path for the package
//
// TODO(mdempsky): Remove; unneeded since CL 391014.
func (pr *PkgDecoder) PkgPath() string { return pr.pkgPath }
// SyncMarkers reports whether pr uses sync markers.
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,
}
// TODO(mdempsky): Implement direct indexing of input string to
// avoid copying the position information.
r := strings.NewReader(input)
assert(binary.Read(r, binary.LittleEndian, &pr.version) == nil)
switch pr.version {
default:
panic(fmt.Errorf("unsupported version: %v", pr.version))
case 0:
// no flags
case 1:
var flags uint32
assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
pr.sync = flags&flagSyncMarkers != 0
}
assert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil)
pr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1])
assert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil)
pos, err := r.Seek(0, os.SEEK_CUR)
assert(err == nil)
pr.elemData = input[pos:]
assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1]))
return pr
}
// NumElems returns the number of elements in section k.
func (pr *PkgDecoder) NumElems(k RelocKind) int {
count := int(pr.elemEndsEnds[k])
if k > 0 {
count -= int(pr.elemEndsEnds[k-1])
}
return count
}
// TotalElems returns the total number of elements across all sections.
func (pr *PkgDecoder) TotalElems() int {
return len(pr.elemEnds)
}
// Fingerprint returns the package fingerprint.
func (pr *PkgDecoder) Fingerprint() [8]byte {
var fp [8]byte
copy(fp[:], pr.elemData[len(pr.elemData)-8:])
return fp
}
// AbsIdx returns the absolute index for the given (section, index)
// pair.
func (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int {
absIdx := int(idx)
if k > 0 {
absIdx += int(pr.elemEndsEnds[k-1])
}
if absIdx >= int(pr.elemEndsEnds[k]) {
errorf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
}
return absIdx
}
// DataIdx returns the raw element bitstream for the given (section,
// index) pair.
func (pr *PkgDecoder) DataIdx(k RelocKind, idx Index) string {
absIdx := pr.AbsIdx(k, idx)
var start uint32
if absIdx > 0 {
start = pr.elemEnds[absIdx-1]
}
end := pr.elemEnds[absIdx]
return pr.elemData[start:end]
}
// StringIdx returns the string value for the given string index.
func (pr *PkgDecoder) StringIdx(idx Index) string {
return pr.DataIdx(RelocString, idx)
}
// NewDecoder returns a Decoder for the given (section, index) pair,
// and decodes the given SyncMarker from the element bitstream.
func (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {
r := pr.NewDecoderRaw(k, idx)
r.Sync(marker)
return r
}
// NewDecoderRaw returns a Decoder for the given (section, index) pair.
//
// Most callers should use NewDecoder instead.
func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
r := Decoder{
common: pr,
k: k,
Idx: idx,
}
// TODO(mdempsky) r.data.Reset(...) after #44505 is resolved.
r.Data = *strings.NewReader(pr.DataIdx(k, idx))
r.Sync(SyncRelocs)
r.Relocs = make([]RelocEnt, r.Len())
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 {
common *PkgDecoder
Relocs []RelocEnt
Data strings.Reader
k RelocKind
Idx Index
}
func (r *Decoder) checkErr(err error) {
if err != nil {
errorf("unexpected decoding error: %w", err)
}
}
func (r *Decoder) rawUvarint() uint64 {
x, err := binary.ReadUvarint(&r.Data)
r.checkErr(err)
return x
}
func (r *Decoder) rawVarint() int64 {
ux := r.rawUvarint()
// Zig-zag decode.
x := int64(ux >> 1)
if ux&1 != 0 {
x = ^x
}
return x
}
func (r *Decoder) rawReloc(k RelocKind, idx int) Index {
e := r.Relocs[idx]
assert(e.Kind == k)
return e.Idx
}
// Sync decodes a sync marker from the element bitstream and asserts
// that it matches the expected marker.
//
// If r.common.sync is false, then Sync is a no-op.
func (r *Decoder) Sync(mWant SyncMarker) {
if !r.common.sync {
return
}
pos, _ := r.Data.Seek(0, os.SEEK_CUR) // TODO(mdempsky): io.SeekCurrent after #44505 is resolved
mHave := SyncMarker(r.rawUvarint())
writerPCs := make([]int, r.rawUvarint())
for i := range writerPCs {
writerPCs[i] = int(r.rawUvarint())
}
if mHave == mWant {
return
}
// There's some tension here between printing:
//
// (1) full file paths that tools can recognize (e.g., so emacs
// hyperlinks the "file:line" text for easy navigation), or
//
// (2) short file paths that are easier for humans to read (e.g., by
// omitting redundant or irrelevant details, so it's easier to
// focus on the useful bits that remain).
//
// The current formatting favors the former, as it seems more
// helpful in practice. But perhaps the formatting could be improved
// to better address both concerns. For example, use relative file
// paths if they would be shorter, or rewrite file paths to contain
// "$GOROOT" (like objabi.AbsFile does) if tools can be taught how
// to reliably expand that again.
fmt.Printf("export data desync: package %q, section %v, index %v, offset %v\n", r.common.pkgPath, r.k, r.Idx, pos)
fmt.Printf("\nfound %v, written at:\n", mHave)
if len(writerPCs) == 0 {
fmt.Printf("\t[stack trace unavailable; recompile package %q with -d=syncframes]\n", r.common.pkgPath)
}
for _, pc := range writerPCs {
fmt.Printf("\t%s\n", r.common.StringIdx(r.rawReloc(RelocString, pc)))
}
fmt.Printf("\nexpected %v, reading at:\n", mWant)
var readerPCs [32]uintptr // TODO(mdempsky): Dynamically size?
n := runtime.Callers(2, readerPCs[:])
for _, pc := range fmtFrames(readerPCs[:n]...) {
fmt.Printf("\t%s\n", pc)
}
// We already printed a stack trace for the reader, so now we can
// simply exit. Printing a second one with panic or base.Fatalf
// would just be noise.
os.Exit(1)
}
// Bool decodes and returns a bool value from the element bitstream.
func (r *Decoder) Bool() bool {
r.Sync(SyncBool)
x, err := r.Data.ReadByte()
r.checkErr(err)
assert(x < 2)
return x != 0
}
// Int64 decodes and returns an int64 value from the element bitstream.
func (r *Decoder) Int64() int64 {
r.Sync(SyncInt64)
return r.rawVarint()
}
// Int64 decodes and returns a uint64 value from the element bitstream.
func (r *Decoder) Uint64() uint64 {
r.Sync(SyncUint64)
return r.rawUvarint()
}
// Len decodes and returns a non-negative int value from the element bitstream.
func (r *Decoder) Len() int { x := r.Uint64(); v := int(x); assert(uint64(v) == x); return v }
// Int decodes and returns an int value from the element bitstream.
func (r *Decoder) Int() int { x := r.Int64(); v := int(x); assert(int64(v) == x); return v }
// Uint decodes and returns a uint value from the element bitstream.
func (r *Decoder) Uint() uint { x := r.Uint64(); v := uint(x); assert(uint64(v) == x); return v }
// Code decodes a Code value from the element bitstream and returns
// its ordinal value. It's the caller's responsibility to convert the
// result to an appropriate Code type.
//
// TODO(mdempsky): Ideally this method would have signature "Code[T
// Code] T" instead, but we don't allow generic methods and the
// compiler can't depend on generics yet anyway.
func (r *Decoder) Code(mark SyncMarker) int {
r.Sync(mark)
return r.Len()
}
// Reloc decodes a relocation of expected section k from the element
// bitstream and returns an index to the referenced element.
func (r *Decoder) Reloc(k RelocKind) Index {
r.Sync(SyncUseReloc)
return r.rawReloc(k, r.Len())
}
// String decodes and returns a string value from the element
// bitstream.
func (r *Decoder) String() string {
r.Sync(SyncString)
return r.common.StringIdx(r.Reloc(RelocString))
}
// Strings decodes and returns a variable-length slice of strings from
// the element bitstream.
func (r *Decoder) Strings() []string {
res := make([]string, r.Len())
for i := range res {
res[i] = r.String()
}
return res
}
// Value decodes and returns a constant.Value from the element
// bitstream.
func (r *Decoder) Value() constant.Value {
r.Sync(SyncValue)
isComplex := r.Bool()
val := r.scalar()
if isComplex {
val = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar()))
}
return val
}
func (r *Decoder) scalar() constant.Value {
switch tag := CodeVal(r.Code(SyncVal)); tag {
default:
panic(fmt.Errorf("unexpected scalar tag: %v", tag))
case ValBool:
return constant.MakeBool(r.Bool())
case ValString:
return constant.MakeString(r.String())
case ValInt64:
return constant.MakeInt64(r.Int64())
case ValBigInt:
return constant.Make(r.bigInt())
case ValBigRat:
num := r.bigInt()
denom := r.bigInt()
return constant.Make(new(big.Rat).SetFrac(num, denom))
case ValBigFloat:
return constant.Make(r.bigFloat())
}
}
func (r *Decoder) bigInt() *big.Int {
v := new(big.Int).SetBytes([]byte(r.String()))
if r.Bool() {
v.Neg(v)
}
return v
}
func (r *Decoder) bigFloat() *big.Float {
v := new(big.Float).SetPrec(512)
assert(v.UnmarshalText([]byte(r.String())) == nil)
return v
}
// @@@ Helpers
// TODO(mdempsky): These should probably be removed. I think they're a
// smell that the export data format is not yet quite right.
// 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()
if path == "" {
path = pr.pkgPath
}
return path
}
// 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()
assert(name != "")
tag := CodeObj(r.Code(SyncCodeObj))
return path, name, tag
}

32
vendor/golang.org/x/tools/go/internal/pkgbits/doc.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
// 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 pkgbits implements low-level coding abstractions for
// Unified IR's export data format.
//
// At a low-level, a package is a collection of bitstream elements.
// Each element has a "kind" and a dense, non-negative index.
// Elements can be randomly accessed given their kind and index.
//
// Individual elements are sequences of variable-length values (e.g.,
// integers, booleans, strings, go/constant values, cross-references
// to other elements). Package pkgbits provides APIs for encoding and
// decoding these low-level values, but the details of mapping
// higher-level Go constructs into elements is left to higher-level
// abstractions.
//
// Elements may cross-reference each other with "relocations." For
// example, an element representing a pointer type has a relocation
// referring to the element type.
//
// Go constructs may be composed as a constellation of multiple
// elements. For example, a declared function may have one element to
// describe the object (e.g., its name, type, position), and a
// separate element to describe its function body. This allows readers
// some flexibility in efficiently seeking or re-reading data (e.g.,
// inlining requires re-reading the function body for each inlined
// call, without needing to re-read the object-level details).
//
// This is a copy of internal/pkgbits in the Go implementation.
package pkgbits

View File

@ -0,0 +1,379 @@
// 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.
package pkgbits
import (
"bytes"
"crypto/md5"
"encoding/binary"
"go/constant"
"io"
"math/big"
"runtime"
)
// 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 {
// elems holds the bitstream for previously encoded elements.
elems [numRelocs][]string
// stringsIdx maps previously encoded strings to their index within
// the RelocString section, to allow deduplication. That is,
// elems[RelocString][stringsIdx[s]] == s (if present).
stringsIdx map[string]Index
// syncFrames is the number of frames to write at each sync
// marker. A negative value means sync markers are omitted.
syncFrames int
}
// SyncMarkers reports whether pw uses sync markers.
func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
// NewPkgEncoder returns an initialized PkgEncoder.
//
// syncFrames is the number of caller frames that should be serialized
// at Sync points. Serializing additional frames results in larger
// 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 {
return PkgEncoder{
stringsIdx: make(map[string]Index),
syncFrames: syncFrames,
}
}
// DumpTo writes the package's encoded data to out0 and returns the
// package fingerprint.
func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {
h := md5.New()
out := io.MultiWriter(out0, h)
writeUint32 := func(x uint32) {
assert(binary.Write(out, binary.LittleEndian, x) == nil)
}
writeUint32(currentVersion)
var flags uint32
if pw.SyncMarkers() {
flags |= flagSyncMarkers
}
writeUint32(flags)
// Write elemEndsEnds.
var sum uint32
for _, elems := range &pw.elems {
sum += uint32(len(elems))
writeUint32(sum)
}
// Write elemEnds.
sum = 0
for _, elems := range &pw.elems {
for _, elem := range elems {
sum += uint32(len(elem))
writeUint32(sum)
}
}
// Write elemData.
for _, elems := range &pw.elems {
for _, elem := range elems {
_, err := io.WriteString(out, elem)
assert(err == nil)
}
}
// Write fingerprint.
copy(fingerprint[:], h.Sum(nil))
_, err := out0.Write(fingerprint[:])
assert(err == nil)
return
}
// StringIdx adds a string value to the strings section, if not
// already present, and returns its index.
func (pw *PkgEncoder) StringIdx(s string) Index {
if idx, ok := pw.stringsIdx[s]; ok {
assert(pw.elems[RelocString][idx] == s)
return idx
}
idx := Index(len(pw.elems[RelocString]))
pw.elems[RelocString] = append(pw.elems[RelocString], s)
pw.stringsIdx[s] = idx
return idx
}
// NewEncoder returns an Encoder for a new element within the given
// section, and encodes the given SyncMarker as the start of the
// element bitstream.
func (pw *PkgEncoder) NewEncoder(k RelocKind, marker SyncMarker) Encoder {
e := pw.NewEncoderRaw(k)
e.Sync(marker)
return e
}
// NewEncoderRaw returns an Encoder for a new element within the given
// section.
//
// Most callers should use NewEncoder instead.
func (pw *PkgEncoder) NewEncoderRaw(k RelocKind) Encoder {
idx := Index(len(pw.elems[k]))
pw.elems[k] = append(pw.elems[k], "") // placeholder
return Encoder{
p: pw,
k: k,
Idx: idx,
}
}
// An Encoder provides methods for encoding an individual element's
// bitstream data.
type Encoder struct {
p *PkgEncoder
Relocs []RelocEnt
Data bytes.Buffer // accumulated element bitstream data
encodingRelocHeader bool
k RelocKind
Idx Index // index within relocation section
}
// 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
// Backup the data so we write the relocations at the front.
var tmp bytes.Buffer
io.Copy(&tmp, &w.Data)
// TODO(mdempsky): Consider writing these out separately so they're
// easier to strip, along with function bodies, so that we can prune
// down to just the data that's relevant to go/types.
if w.encodingRelocHeader {
panic("encodingRelocHeader already true; recursive flush?")
}
w.encodingRelocHeader = true
w.Sync(SyncRelocs)
w.Len(len(w.Relocs))
for _, rEnt := range w.Relocs {
w.Sync(SyncReloc)
w.Len(int(rEnt.Kind))
w.Len(int(rEnt.Idx))
}
io.Copy(&sb, &w.Data)
io.Copy(&sb, &tmp)
w.p.elems[w.k][w.Idx] = sb.String()
return w.Idx
}
func (w *Encoder) checkErr(err error) {
if err != nil {
errorf("unexpected encoding error: %v", err)
}
}
func (w *Encoder) rawUvarint(x uint64) {
var buf [binary.MaxVarintLen64]byte
n := binary.PutUvarint(buf[:], x)
_, err := w.Data.Write(buf[:n])
w.checkErr(err)
}
func (w *Encoder) rawVarint(x int64) {
// Zig-zag encode.
ux := uint64(x) << 1
if x < 0 {
ux = ^ux
}
w.rawUvarint(ux)
}
func (w *Encoder) rawReloc(r RelocKind, idx Index) int {
// TODO(mdempsky): Use map for lookup; this takes quadratic time.
for i, rEnt := range w.Relocs {
if rEnt.Kind == r && rEnt.Idx == idx {
return i
}
}
i := len(w.Relocs)
w.Relocs = append(w.Relocs, RelocEnt{r, idx})
return i
}
func (w *Encoder) Sync(m SyncMarker) {
if !w.p.SyncMarkers() {
return
}
// Writing out stack frame string references requires working
// relocations, but writing out the relocations themselves involves
// sync markers. To prevent infinite recursion, we simply trim the
// stack frame for sync markers within the relocation header.
var frames []string
if !w.encodingRelocHeader && w.p.syncFrames > 0 {
pcs := make([]uintptr, w.p.syncFrames)
n := runtime.Callers(2, pcs)
frames = fmtFrames(pcs[:n]...)
}
// TODO(mdempsky): Save space by writing out stack frames as a
// linked list so we can share common stack frames.
w.rawUvarint(uint64(m))
w.rawUvarint(uint64(len(frames)))
for _, frame := range frames {
w.rawUvarint(uint64(w.rawReloc(RelocString, w.p.StringIdx(frame))))
}
}
// Bool encodes and writes a bool value into the element bitstream,
// and then returns the bool value.
//
// For simple, 2-alternative encodings, the idiomatic way to call Bool
// is something like:
//
// if w.Bool(x != 0) {
// // alternative #1
// } else {
// // alternative #2
// }
//
// For multi-alternative encodings, use Code instead.
func (w *Encoder) Bool(b bool) bool {
w.Sync(SyncBool)
var x byte
if b {
x = 1
}
err := w.Data.WriteByte(x)
w.checkErr(err)
return b
}
// Int64 encodes and writes an int64 value into the element bitstream.
func (w *Encoder) Int64(x int64) {
w.Sync(SyncInt64)
w.rawVarint(x)
}
// Uint64 encodes and writes a uint64 value into the element bitstream.
func (w *Encoder) Uint64(x uint64) {
w.Sync(SyncUint64)
w.rawUvarint(x)
}
// Len encodes and writes a non-negative int value into the element bitstream.
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.
func (w *Encoder) Uint(x uint) { w.Uint64(uint64(x)) }
// Reloc encodes and writes a relocation for the given (section,
// index) pair into the element bitstream.
//
// Note: Only the index is formally written into the element
// bitstream, so bitstream decoders must know from context which
// section an encoded relocation refers to.
func (w *Encoder) Reloc(r RelocKind, idx Index) {
w.Sync(SyncUseReloc)
w.Len(w.rawReloc(r, idx))
}
// Code encodes and writes a Code value into the element bitstream.
func (w *Encoder) Code(c Code) {
w.Sync(c.Marker())
w.Len(c.Value())
}
// String encodes and writes a string value into the element
// bitstream.
//
// Internally, strings are deduplicated by adding them to the strings
// section (if not already present), and then writing a relocation
// into the element bitstream.
func (w *Encoder) String(s string) {
w.Sync(SyncString)
w.Reloc(RelocString, w.p.StringIdx(s))
}
// Strings encodes and writes a variable-length slice of strings into
// the element bitstream.
func (w *Encoder) Strings(ss []string) {
w.Len(len(ss))
for _, s := range ss {
w.String(s)
}
}
// Value encodes and writes a constant.Value into the element
// bitstream.
func (w *Encoder) Value(val constant.Value) {
w.Sync(SyncValue)
if w.Bool(val.Kind() == constant.Complex) {
w.scalar(constant.Real(val))
w.scalar(constant.Imag(val))
} else {
w.scalar(val)
}
}
func (w *Encoder) scalar(val constant.Value) {
switch v := constant.Val(val).(type) {
default:
errorf("unhandled %v (%v)", val, val.Kind())
case bool:
w.Code(ValBool)
w.Bool(v)
case string:
w.Code(ValString)
w.String(v)
case int64:
w.Code(ValInt64)
w.Int64(v)
case *big.Int:
w.Code(ValBigInt)
w.bigInt(v)
case *big.Rat:
w.Code(ValBigRat)
w.bigInt(v.Num())
w.bigInt(v.Denom())
case *big.Float:
w.Code(ValBigFloat)
w.bigFloat(v)
}
}
func (w *Encoder) bigInt(v *big.Int) {
b := v.Bytes()
w.String(string(b)) // TODO: More efficient encoding.
w.Bool(v.Sign() < 0)
}
func (w *Encoder) bigFloat(v *big.Float) {
b := v.Append(nil, 'p', -1)
w.String(string(b)) // TODO: More efficient encoding.
}

View File

@ -0,0 +1,9 @@
// 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 pkgbits
const (
flagSyncMarkers = 1 << iota // file format contains sync markers
)

View File

@ -0,0 +1,21 @@
// 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())
}
}

View File

@ -0,0 +1,28 @@
// 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
}
}
}

42
vendor/golang.org/x/tools/go/internal/pkgbits/reloc.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// 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.
package pkgbits
// A RelocKind indicates a particular section within a unified IR export.
type RelocKind int
// An Index represents a bitstream element index within a particular
// section.
type Index int
// A relocEnt (relocation entry) is an entry in an element's local
// reference table.
//
// TODO(mdempsky): Rename this too.
type RelocEnt struct {
Kind RelocKind
Idx Index
}
// Reserved indices within the meta relocation section.
const (
PublicRootIdx Index = 0
PrivateRootIdx Index = 1
)
const (
RelocString RelocKind = iota
RelocMeta
RelocPosBase
RelocPkg
RelocName
RelocType
RelocObj
RelocObjExt
RelocObjDict
RelocBody
numRelocs = iota
)

View File

@ -0,0 +1,17 @@
// 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 pkgbits
import "fmt"
func assert(b bool) {
if !b {
panic("assertion failed")
}
}
func errorf(format string, args ...interface{}) {
panic(fmt.Errorf(format, args...))
}

113
vendor/golang.org/x/tools/go/internal/pkgbits/sync.go generated vendored Normal file
View File

@ -0,0 +1,113 @@
// 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.
package pkgbits
import (
"fmt"
"strings"
)
// fmtFrames formats a backtrace for reporting reader/writer desyncs.
func fmtFrames(pcs ...uintptr) []string {
res := make([]string, 0, len(pcs))
walkFrames(pcs, func(file string, line int, name string, offset uintptr) {
// Trim package from function name. It's just redundant noise.
name = strings.TrimPrefix(name, "cmd/compile/internal/noder.")
res = append(res, fmt.Sprintf("%s:%v: %s +0x%v", file, line, name, offset))
})
return res
}
type frameVisitor func(file string, line int, name string, offset uintptr)
// SyncMarker is an enum type that represents markers that may be
// written to export data to ensure the reader and writer stay
// synchronized.
type SyncMarker int
//go:generate stringer -type=SyncMarker -trimprefix=Sync
const (
_ SyncMarker = iota
// Public markers (known to go/types importers).
// Low-level coding markers.
SyncEOF
SyncBool
SyncInt64
SyncUint64
SyncString
SyncValue
SyncVal
SyncRelocs
SyncReloc
SyncUseReloc
// Higher-level object and type markers.
SyncPublic
SyncPos
SyncPosBase
SyncObject
SyncObject1
SyncPkg
SyncPkgDef
SyncMethod
SyncType
SyncTypeIdx
SyncTypeParamNames
SyncSignature
SyncParams
SyncParam
SyncCodeObj
SyncSym
SyncLocalIdent
SyncSelector
// Private markers (only known to cmd/compile).
SyncPrivate
SyncFuncExt
SyncVarExt
SyncTypeExt
SyncPragma
SyncExprList
SyncExprs
SyncExpr
SyncExprType
SyncAssign
SyncOp
SyncFuncLit
SyncCompLit
SyncDecl
SyncFuncBody
SyncOpenScope
SyncCloseScope
SyncCloseAnotherScope
SyncDeclNames
SyncDeclName
SyncStmts
SyncBlockStmt
SyncIfStmt
SyncForStmt
SyncSwitchStmt
SyncRangeStmt
SyncCaseClause
SyncCommClause
SyncSelectStmt
SyncDecls
SyncLabeledStmt
SyncUseObjLocal
SyncAddLocal
SyncLinkname
SyncStmt1
SyncStmtsEnd
SyncLabel
SyncOptLabel
)

View File

@ -0,0 +1,89 @@
// Code generated by "stringer -type=SyncMarker -trimprefix=Sync"; DO NOT EDIT.
package pkgbits
import "strconv"
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[SyncEOF-1]
_ = x[SyncBool-2]
_ = x[SyncInt64-3]
_ = x[SyncUint64-4]
_ = x[SyncString-5]
_ = x[SyncValue-6]
_ = x[SyncVal-7]
_ = x[SyncRelocs-8]
_ = x[SyncReloc-9]
_ = x[SyncUseReloc-10]
_ = x[SyncPublic-11]
_ = x[SyncPos-12]
_ = x[SyncPosBase-13]
_ = x[SyncObject-14]
_ = x[SyncObject1-15]
_ = x[SyncPkg-16]
_ = x[SyncPkgDef-17]
_ = x[SyncMethod-18]
_ = x[SyncType-19]
_ = x[SyncTypeIdx-20]
_ = x[SyncTypeParamNames-21]
_ = x[SyncSignature-22]
_ = x[SyncParams-23]
_ = x[SyncParam-24]
_ = x[SyncCodeObj-25]
_ = x[SyncSym-26]
_ = x[SyncLocalIdent-27]
_ = x[SyncSelector-28]
_ = x[SyncPrivate-29]
_ = x[SyncFuncExt-30]
_ = x[SyncVarExt-31]
_ = x[SyncTypeExt-32]
_ = x[SyncPragma-33]
_ = x[SyncExprList-34]
_ = x[SyncExprs-35]
_ = x[SyncExpr-36]
_ = x[SyncExprType-37]
_ = x[SyncAssign-38]
_ = x[SyncOp-39]
_ = x[SyncFuncLit-40]
_ = x[SyncCompLit-41]
_ = x[SyncDecl-42]
_ = x[SyncFuncBody-43]
_ = x[SyncOpenScope-44]
_ = x[SyncCloseScope-45]
_ = x[SyncCloseAnotherScope-46]
_ = x[SyncDeclNames-47]
_ = x[SyncDeclName-48]
_ = x[SyncStmts-49]
_ = x[SyncBlockStmt-50]
_ = x[SyncIfStmt-51]
_ = x[SyncForStmt-52]
_ = x[SyncSwitchStmt-53]
_ = x[SyncRangeStmt-54]
_ = x[SyncCaseClause-55]
_ = x[SyncCommClause-56]
_ = x[SyncSelectStmt-57]
_ = x[SyncDecls-58]
_ = x[SyncLabeledStmt-59]
_ = x[SyncUseObjLocal-60]
_ = x[SyncAddLocal-61]
_ = x[SyncLinkname-62]
_ = x[SyncStmt1-63]
_ = x[SyncStmtsEnd-64]
_ = x[SyncLabel-65]
_ = x[SyncOptLabel-66]
}
const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabel"
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}
func (i SyncMarker) String() string {
i -= 1
if i < 0 || i >= SyncMarker(len(_SyncMarker_index)-1) {
return "SyncMarker(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _SyncMarker_name[_SyncMarker_index[i]:_SyncMarker_index[i+1]]
}

View File

@ -67,7 +67,6 @@ Most tools should pass their command-line arguments (after any flags)
uninterpreted to the loader, so that the loader can interpret them
according to the conventions of the underlying build system.
See the Example function for typical usage.
*/
package packages // import "golang.org/x/tools/go/packages"

View File

@ -26,7 +26,6 @@ import (
"golang.org/x/tools/go/internal/packagesdriver"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/packagesinternal"
"golang.org/x/xerrors"
)
// debug controls verbose logging.
@ -303,11 +302,12 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries
}
dirResponse, err := state.createDriverResponse(pattern)
// If there was an error loading the package, or the package is returned
// with errors, try to load the file as an ad-hoc package.
// If there was an error loading the package, or no packages are returned,
// or the package is returned with errors, try to load the file as an
// ad-hoc package.
// Usually the error will appear in a returned package, but may not if we're
// in module mode and the ad-hoc is located outside a module.
if err != nil || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 &&
if err != nil || len(dirResponse.Packages) == 0 || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 &&
len(dirResponse.Packages[0].Errors) == 1 {
var queryErr error
if dirResponse, queryErr = state.adhocPackage(pattern, query); queryErr != nil {
@ -393,6 +393,8 @@ type jsonPackage struct {
CompiledGoFiles []string
IgnoredGoFiles []string
IgnoredOtherFiles []string
EmbedPatterns []string
EmbedFiles []string
CFiles []string
CgoFiles []string
CXXFiles []string
@ -444,7 +446,11 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
// Run "go list" for complete
// information on the specified packages.
buf, err := state.invokeGo("list", golistargs(state.cfg, words)...)
goVersion, err := state.getGoVersion()
if err != nil {
return nil, err
}
buf, err := state.invokeGo("list", golistargs(state.cfg, words, goVersion)...)
if err != nil {
return nil, err
}
@ -565,6 +571,8 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles),
CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles),
OtherFiles: absJoin(p.Dir, otherFiles(p)...),
EmbedFiles: absJoin(p.Dir, p.EmbedFiles),
EmbedPatterns: absJoin(p.Dir, p.EmbedPatterns),
IgnoredFiles: absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles),
forTest: p.ForTest,
depsErrors: p.DepsErrors,
@ -805,17 +813,83 @@ func absJoin(dir string, fileses ...[]string) (res []string) {
return res
}
func golistargs(cfg *Config, words []string) []string {
func jsonFlag(cfg *Config, goVersion int) string {
if goVersion < 19 {
return "-json"
}
var fields []string
added := make(map[string]bool)
addFields := func(fs ...string) {
for _, f := range fs {
if !added[f] {
added[f] = true
fields = append(fields, f)
}
}
}
addFields("Name", "ImportPath", "Error") // These fields are always needed
if cfg.Mode&NeedFiles != 0 || cfg.Mode&NeedTypes != 0 {
addFields("Dir", "GoFiles", "IgnoredGoFiles", "IgnoredOtherFiles", "CFiles",
"CgoFiles", "CXXFiles", "MFiles", "HFiles", "FFiles", "SFiles",
"SwigFiles", "SwigCXXFiles", "SysoFiles")
if cfg.Tests {
addFields("TestGoFiles", "XTestGoFiles")
}
}
if cfg.Mode&NeedTypes != 0 {
// CompiledGoFiles seems to be required for the test case TestCgoNoSyntax,
// even when -compiled isn't passed in.
// TODO(#52435): Should we make the test ask for -compiled, or automatically
// request CompiledGoFiles in certain circumstances?
addFields("Dir", "CompiledGoFiles")
}
if cfg.Mode&NeedCompiledGoFiles != 0 {
addFields("Dir", "CompiledGoFiles", "Export")
}
if cfg.Mode&NeedImports != 0 {
// When imports are requested, DepOnly is used to distinguish between packages
// explicitly requested and transitive imports of those packages.
addFields("DepOnly", "Imports", "ImportMap")
if cfg.Tests {
addFields("TestImports", "XTestImports")
}
}
if cfg.Mode&NeedDeps != 0 {
addFields("DepOnly")
}
if usesExportData(cfg) {
// Request Dir in the unlikely case Export is not absolute.
addFields("Dir", "Export")
}
if cfg.Mode&needInternalForTest != 0 {
addFields("ForTest")
}
if cfg.Mode&needInternalDepsErrors != 0 {
addFields("DepsErrors")
}
if cfg.Mode&NeedModule != 0 {
addFields("Module")
}
if cfg.Mode&NeedEmbedFiles != 0 {
addFields("EmbedFiles")
}
if cfg.Mode&NeedEmbedPatterns != 0 {
addFields("EmbedPatterns")
}
return "-json=" + strings.Join(fields, ",")
}
func golistargs(cfg *Config, words []string, goVersion int) []string {
const findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo
fullargs := []string{
"-e", "-json",
"-e", jsonFlag(cfg, goVersion),
fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypes|NeedTypesInfo|NeedTypesSizes) != 0),
fmt.Sprintf("-test=%t", cfg.Tests),
fmt.Sprintf("-export=%t", usesExportData(cfg)),
fmt.Sprintf("-deps=%t", cfg.Mode&NeedImports != 0),
// go list doesn't let you pass -test and -find together,
// probably because you'd just get the TestMain.
fmt.Sprintf("-find=%t", !cfg.Tests && cfg.Mode&findFlags == 0),
fmt.Sprintf("-find=%t", !cfg.Tests && cfg.Mode&findFlags == 0 && !usesExportData(cfg)),
}
fullargs = append(fullargs, cfg.BuildFlags...)
fullargs = append(fullargs, "--")
@ -879,7 +953,7 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
if !ok {
// Catastrophic error:
// - context cancellation
return nil, xerrors.Errorf("couldn't run 'go': %w", err)
return nil, fmt.Errorf("couldn't run 'go': %w", err)
}
// Old go version?

View File

@ -15,7 +15,7 @@ var allModes = []LoadMode{
NeedCompiledGoFiles,
NeedImports,
NeedDeps,
NeedExportsFile,
NeedExportFile,
NeedTypes,
NeedSyntax,
NeedTypesInfo,
@ -28,7 +28,7 @@ var modeStrings = []string{
"NeedCompiledGoFiles",
"NeedImports",
"NeedDeps",
"NeedExportsFile",
"NeedExportFile",
"NeedTypes",
"NeedSyntax",
"NeedTypesInfo",

View File

@ -26,6 +26,7 @@ import (
"golang.org/x/tools/go/gcexportdata"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/packagesinternal"
"golang.org/x/tools/internal/typeparams"
"golang.org/x/tools/internal/typesinternal"
)
@ -38,9 +39,6 @@ import (
// Load may return more information than requested.
type LoadMode int
// TODO(matloob): When a V2 of go/packages is released, rename NeedExportsFile to
// NeedExportFile to make it consistent with the Package field it's adding.
const (
// NeedName adds Name and PkgPath.
NeedName LoadMode = 1 << iota
@ -58,8 +56,8 @@ const (
// NeedDeps adds the fields requested by the LoadMode in the packages in Imports.
NeedDeps
// NeedExportsFile adds ExportFile.
NeedExportsFile
// NeedExportFile adds ExportFile.
NeedExportFile
// NeedTypes adds Types, Fset, and IllTyped.
NeedTypes
@ -73,12 +71,25 @@ const (
// NeedTypesSizes adds TypesSizes.
NeedTypesSizes
// needInternalDepsErrors adds the internal deps errors field for use by gopls.
needInternalDepsErrors
// needInternalForTest adds the internal forTest field.
// Tests must also be set on the context for this field to be populated.
needInternalForTest
// typecheckCgo enables full support for type checking cgo. Requires Go 1.15+.
// Modifies CompiledGoFiles and Types, and has no effect on its own.
typecheckCgo
// NeedModule adds Module.
NeedModule
// NeedEmbedFiles adds EmbedFiles.
NeedEmbedFiles
// NeedEmbedPatterns adds EmbedPatterns.
NeedEmbedPatterns
)
const (
@ -101,6 +112,9 @@ const (
// Deprecated: LoadAllSyntax exists for historical compatibility
// and should not be used. Please directly specify the needed fields using the Need values.
LoadAllSyntax = LoadSyntax | NeedDeps
// Deprecated: NeedExportsFile is a historical misspelling of NeedExportFile.
NeedExportsFile = NeedExportFile
)
// A Config specifies details about how packages should be loaded.
@ -295,6 +309,14 @@ type Package struct {
// including assembly, C, C++, Fortran, Objective-C, SWIG, and so on.
OtherFiles []string
// EmbedFiles lists the absolute file paths of the package's files
// embedded with go:embed.
EmbedFiles []string
// EmbedPatterns lists the absolute file patterns of the package's
// files embedded with go:embed.
EmbedPatterns []string
// IgnoredFiles lists source files that are not part of the package
// using the current build configuration but that might be part of
// the package using other build configurations.
@ -327,6 +349,9 @@ type Package struct {
// The NeedSyntax LoadMode bit populates this field for packages matching the patterns.
// If NeedDeps and NeedImports are also set, this field will also be populated
// for dependencies.
//
// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are
// removed. If parsing returned nil, Syntax may be shorter than CompiledGoFiles.
Syntax []*ast.File
// TypesInfo provides type information about the package's syntax trees.
@ -385,6 +410,8 @@ func init() {
config.(*Config).modFlag = value
}
packagesinternal.TypecheckCgo = int(typecheckCgo)
packagesinternal.DepsErrors = int(needInternalDepsErrors)
packagesinternal.ForTest = int(needInternalForTest)
}
// An Error describes a problem with a package's metadata, syntax, or types.
@ -427,6 +454,8 @@ type flatPackage struct {
GoFiles []string `json:",omitempty"`
CompiledGoFiles []string `json:",omitempty"`
OtherFiles []string `json:",omitempty"`
EmbedFiles []string `json:",omitempty"`
EmbedPatterns []string `json:",omitempty"`
IgnoredFiles []string `json:",omitempty"`
ExportFile string `json:",omitempty"`
Imports map[string]string `json:",omitempty"`
@ -450,6 +479,8 @@ func (p *Package) MarshalJSON() ([]byte, error) {
GoFiles: p.GoFiles,
CompiledGoFiles: p.CompiledGoFiles,
OtherFiles: p.OtherFiles,
EmbedFiles: p.EmbedFiles,
EmbedPatterns: p.EmbedPatterns,
IgnoredFiles: p.IgnoredFiles,
ExportFile: p.ExportFile,
}
@ -477,6 +508,8 @@ func (p *Package) UnmarshalJSON(b []byte) error {
GoFiles: flat.GoFiles,
CompiledGoFiles: flat.CompiledGoFiles,
OtherFiles: flat.OtherFiles,
EmbedFiles: flat.EmbedFiles,
EmbedPatterns: flat.EmbedPatterns,
ExportFile: flat.ExportFile,
}
if len(flat.Imports) > 0 {
@ -610,7 +643,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||
// ... or if we need types and the exportData is invalid. We fall back to (incompletely)
// typechecking packages from source if they fail to compile.
(ld.Mode&NeedTypes|NeedTypesInfo != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
(ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
lpkg := &loaderPackage{
Package: pkg,
needtypes: needtypes,
@ -748,13 +781,19 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
ld.pkgs[i].OtherFiles = nil
ld.pkgs[i].IgnoredFiles = nil
}
if ld.requestedMode&NeedEmbedFiles == 0 {
ld.pkgs[i].EmbedFiles = nil
}
if ld.requestedMode&NeedEmbedPatterns == 0 {
ld.pkgs[i].EmbedPatterns = nil
}
if ld.requestedMode&NeedCompiledGoFiles == 0 {
ld.pkgs[i].CompiledGoFiles = nil
}
if ld.requestedMode&NeedImports == 0 {
ld.pkgs[i].Imports = nil
}
if ld.requestedMode&NeedExportsFile == 0 {
if ld.requestedMode&NeedExportFile == 0 {
ld.pkgs[i].ExportFile = ""
}
if ld.requestedMode&NeedTypes == 0 {
@ -910,6 +949,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
Scopes: make(map[ast.Node]*types.Scope),
Selections: make(map[*ast.SelectorExpr]*types.Selection),
}
typeparams.InitInstanceInfo(lpkg.TypesInfo)
lpkg.TypesSizes = ld.sizes
importer := importerFunc(func(path string) (*types.Package, error) {
@ -1048,7 +1088,6 @@ func (ld *loader) parseFile(filename string) (*ast.File, error) {
//
// Because files are scanned in parallel, the token.Pos
// positions of the resulting ast.Files are not ordered.
//
func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
var wg sync.WaitGroup
n := len(filenames)
@ -1092,7 +1131,6 @@ func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
// sameFile returns true if x and y have the same basename and denote
// the same file.
//
func sameFile(x, y string) bool {
if x == y {
// It could be the case that y doesn't exist.
@ -1205,8 +1243,13 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
if err != nil {
return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
}
if _, ok := view["go.shape"]; ok {
// Account for the pseudopackage "go.shape" that gets
// created by generic code.
viewLen++
}
if viewLen != len(view) {
log.Fatalf("Unexpected package creation during export data loading")
log.Panicf("golang.org/x/tools/go/packages: unexpected new packages during load of %s", lpkg.PkgPath)
}
lpkg.Types = tpkg
@ -1217,17 +1260,8 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
// impliedLoadMode returns loadMode with its dependencies.
func impliedLoadMode(loadMode LoadMode) LoadMode {
if loadMode&NeedTypesInfo != 0 && loadMode&NeedImports == 0 {
// If NeedTypesInfo, go/packages needs to do typechecking itself so it can
// associate type info with the AST. To do so, we need the export data
// for dependencies, which means we need to ask for the direct dependencies.
// NeedImports is used to ask for the direct dependencies.
loadMode |= NeedImports
}
if loadMode&NeedDeps != 0 && loadMode&NeedImports == 0 {
// With NeedDeps we need to load at least direct dependencies.
// NeedImports is used to ask for the direct dependencies.
if loadMode&(NeedDeps|NeedTypes|NeedTypesInfo) != 0 {
// All these things require knowing the import graph.
loadMode |= NeedImports
}
@ -1235,5 +1269,5 @@ func impliedLoadMode(loadMode LoadMode) LoadMode {
}
func usesExportData(cfg *Config) bool {
return cfg.Mode&NeedExportsFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0
return cfg.Mode&NeedExportFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0
}

View File

@ -9,7 +9,6 @@ import (
"bytes"
"context"
"fmt"
exec "golang.org/x/sys/execabs"
"io"
"os"
"regexp"
@ -18,6 +17,8 @@ import (
"sync"
"time"
exec "golang.org/x/sys/execabs"
"golang.org/x/tools/internal/event"
)
@ -131,9 +132,16 @@ type Invocation struct {
Verb string
Args []string
BuildFlags []string
ModFlag string
ModFile string
Overlay string
// If ModFlag is set, the go command is invoked with -mod=ModFlag.
ModFlag string
// If ModFile is set, the go command is invoked with -modfile=ModFile.
ModFile string
// If Overlay is set, the go command is invoked with -overlay=Overlay.
Overlay string
// If CleanEnv is set, the invocation will run only with the environment
// in Env, not starting with os.Environ.
CleanEnv bool
@ -256,8 +264,10 @@ func cmdDebugStr(cmd *exec.Cmd) string {
env := make(map[string]string)
for _, kv := range cmd.Env {
split := strings.SplitN(kv, "=", 2)
k, v := split[0], split[1]
env[k] = v
if len(split) == 2 {
k, v := split[0], split[1]
env[k] = v
}
}
var args []string

View File

@ -38,10 +38,10 @@ var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`)
// 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 VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {
func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, *ModuleJSON, error) {
mainMod, go114, err := getMainModuleAnd114(ctx, inv, r)
if err != nil {
return nil, false, err
return false, nil, err
}
// We check the GOFLAGS to see if there is anything overridden or not.
@ -49,7 +49,7 @@ func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON,
inv.Args = []string{"GOFLAGS"}
stdout, err := r.Run(ctx, inv)
if err != nil {
return nil, false, err
return false, nil, err
}
goflags := string(bytes.TrimSpace(stdout.Bytes()))
matches := modFlagRegexp.FindStringSubmatch(goflags)
@ -57,25 +57,27 @@ func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON,
if len(matches) != 0 {
modFlag = matches[1]
}
if modFlag != "" {
// Don't override an explicit '-mod=' argument.
return mainMod, modFlag == "vendor", nil
// Don't override an explicit '-mod=' argument.
if modFlag == "vendor" {
return true, mainMod, nil
} else if modFlag != "" {
return false, nil, nil
}
if mainMod == nil || !go114 {
return mainMod, false, nil
return false, nil, nil
}
// Check 1.14's automatic vendor mode.
if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() {
if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 {
// The Go version is at least 1.14, and a vendor directory exists.
// Set -mod=vendor by default.
return mainMod, true, nil
return true, mainMod, nil
}
}
return mainMod, false, nil
return false, nil, nil
}
// getMainModuleAnd114 gets the main module's information and whether the
// getMainModuleAnd114 gets one of the main modules' information and whether the
// go command in use is 1.14+. This is the information needed to figure out
// if vendoring should be enabled.
func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {

View File

@ -23,6 +23,8 @@ 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) {}

View File

@ -2,24 +2,178 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package typeparams provides functions to work indirectly with type parameter
// data stored in go/ast and go/types objects, while these API are guarded by a
// build constraint.
// Package typeparams contains common utilities for writing tools that interact
// with generic Go code, as introduced with Go 1.18.
//
// This package exists to make it easier for tools to work with generic code,
// while also compiling against older Go versions.
// 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
// restrictions on a type parameter.
//
// An external version of these APIs is available in the
// golang.org/x/exp/typeparams module.
package typeparams
import (
"go/ast"
"go/token"
"go/types"
)
// A IndexExprData holds data from both ast.IndexExpr and the new
// ast.MultiIndexExpr, which was introduced in Go 1.18.
type IndexExprData struct {
X ast.Expr // expression
Lbrack token.Pos // position of "["
Indices []ast.Expr // index expressions
Rbrack token.Pos // position of "]"
// UnpackIndexExpr extracts data from AST nodes that represent index
// expressions.
//
// For an ast.IndexExpr, the resulting indices slice will contain exactly one
// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable
// number of index expressions.
//
// For nodes that don't represent index expressions, the first return value of
// UnpackIndexExpr will be nil.
func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) {
switch e := n.(type) {
case *ast.IndexExpr:
return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
case *IndexListExpr:
return e.X, e.Lbrack, e.Indices, e.Rbrack
}
return nil, token.NoPos, nil, token.NoPos
}
// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
// will panic.
func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
switch len(indices) {
case 0:
panic("empty indices")
case 1:
return &ast.IndexExpr{
X: x,
Lbrack: lbrack,
Index: indices[0],
Rbrack: rbrack,
}
default:
return &IndexListExpr{
X: x,
Lbrack: lbrack,
Indices: indices,
Rbrack: rbrack,
}
}
}
// IsTypeParam reports whether t is a type parameter.
func IsTypeParam(t types.Type) bool {
_, ok := t.(*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)
}

View File

@ -0,0 +1,122 @@
// 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 typeparams
import (
"go/types"
)
// CoreType returns the core type of T or nil if T does not have a core type.
//
// See https://go.dev/ref/spec#Core_types for the definition of a core type.
func CoreType(T types.Type) types.Type {
U := T.Underlying()
if _, ok := U.(*types.Interface); !ok {
return U // for non-interface types,
}
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.
return nil // no core type.
}
U = terms[0].Type().Underlying()
var identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying())
for identical = 1; identical < len(terms); identical++ {
if !types.Identical(U, terms[identical].Type().Underlying()) {
break
}
}
if identical == len(terms) {
// https://go.dev/ref/spec#Core_types
// "There is a single type U which is the underlying type of all types in the type set of T"
return U
}
ch, ok := U.(*types.Chan)
if !ok {
return nil // no core type as identical < len(terms) and U is not a channel.
}
// https://go.dev/ref/spec#Core_types
// "the type chan E if T contains only bidirectional channels, or the type chan<- E or
// <-chan E depending on the direction of the directional channels present."
for chans := identical; chans < len(terms); chans++ {
curr, ok := terms[chans].Type().Underlying().(*types.Chan)
if !ok {
return nil
}
if !types.Identical(ch.Elem(), curr.Elem()) {
return nil // channel elements are not identical.
}
if ch.Dir() == types.SendRecv {
// ch is bidirectional. We can safely always use curr's direction.
ch = curr
} else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() {
// ch and curr are not bidirectional and not the same direction.
return nil
}
}
return ch
}
// _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
// *types.Union, this is just a single term with Tilde() == false and
// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see
// below.
//
// Structural type restrictions of a type parameter are created via
// non-interface types embedded in its constraint interface (directly, or via a
// chain of interface embeddings). For example, in the declaration type
// T[P interface{~int; m()}] int the structural restriction of the type
// parameter P is ~int.
//
// With interface embedding and unions, the specification of structural type
// restrictions may be arbitrarily complex. For example, consider the
// following:
//
// type A interface{ ~string|~[]byte }
//
// type B interface{ int|string }
//
// type C interface { ~string|~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
// "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
// 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.
//
// _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:
return StructuralTerms(typ)
case *Union:
return UnionTermSet(typ)
case *types.Interface:
return InterfaceTermSet(typ)
default:
return []*Term{NewTerm(false, typ)}, nil
}
}

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !typeparams || !go1.18
// +build !typeparams !go1.18
//go:build !go1.18
// +build !go1.18
package typeparams

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build typeparams && go1.18
// +build typeparams,go1.18
//go:build go1.18
// +build go1.18
package typeparams

View File

@ -0,0 +1,218 @@
// 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.
package typeparams
import (
"errors"
"fmt"
"go/types"
"os"
"strings"
)
//go:generate go run copytermlist.go
const debug = false
var ErrEmptyTypeSet = errors.New("empty type set")
// StructuralTerms returns a slice of terms representing the normalized
// structural type restrictions of a type parameter, if any.
//
// Structural type restrictions of a type parameter are created via
// non-interface types embedded in its constraint interface (directly, or via a
// chain of interface embeddings). For example, in the declaration
//
// type T[P interface{~int; m()}] int
//
// the structural restriction of the type parameter P is ~int.
//
// With interface embedding and unions, the specification of structural type
// restrictions may be arbitrarily complex. For example, consider the
// following:
//
// type A interface{ ~string|~[]byte }
//
// type B interface{ int|string }
//
// type C interface { ~string|~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.
//
// StructuralTerms 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, StructuralTerms
// returns a slice of tilde terms corresponding to the terms of the union in
// the normalized structural restriction. An error is returned if the
// constraint interface is invalid, exceeds complexity bounds, or has an empty
// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet.
//
// StructuralTerms makes no guarantees about the order of terms, except that it
// is deterministic.
func StructuralTerms(tparam *TypeParam) ([]*Term, error) {
constraint := tparam.Constraint()
if constraint == nil {
return nil, fmt.Errorf("%s has nil constraint", tparam)
}
iface, _ := constraint.Underlying().(*types.Interface)
if iface == nil {
return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying())
}
return InterfaceTermSet(iface)
}
// InterfaceTermSet computes the normalized terms for a constraint interface,
// returning an error if the term set cannot be computed or is empty. In the
// latter case, the error will be ErrEmptyTypeSet.
//
// See the documentation of StructuralTerms for more information on
// normalization.
func InterfaceTermSet(iface *types.Interface) ([]*Term, error) {
return computeTermSet(iface)
}
// UnionTermSet computes the normalized terms for a union, returning an error
// if the term set cannot be computed or is empty. In the latter case, the
// error will be ErrEmptyTypeSet.
//
// See the documentation of StructuralTerms for more information on
// normalization.
func UnionTermSet(union *Union) ([]*Term, error) {
return computeTermSet(union)
}
func computeTermSet(typ types.Type) ([]*Term, error) {
tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)
if err != nil {
return nil, err
}
if tset.terms.isEmpty() {
return nil, ErrEmptyTypeSet
}
if tset.terms.isAll() {
return nil, nil
}
var terms []*Term
for _, term := range tset.terms {
terms = append(terms, NewTerm(term.tilde, term.typ))
}
return terms, nil
}
// A termSet holds the normalized set of terms for a given type.
//
// The name termSet is intentionally distinct from 'type set': a type set is
// all types that implement a type (and includes method restrictions), whereas
// a term set just represents the structural restrictions on a type.
type termSet struct {
complete bool
terms termlist
}
func indentf(depth int, format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...)
}
func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) {
if t == nil {
panic("nil type")
}
if debug {
indentf(depth, "%s", t.String())
defer func() {
if err != nil {
indentf(depth, "=> %s", err)
} else {
indentf(depth, "=> %s", res.terms.String())
}
}()
}
const maxTermCount = 100
if tset, ok := seen[t]; ok {
if !tset.complete {
return nil, fmt.Errorf("cycle detected in the declaration of %s", t)
}
return tset, nil
}
// Mark the current type as seen to avoid infinite recursion.
tset := new(termSet)
defer func() {
tset.complete = true
}()
seen[t] = tset
switch u := t.Underlying().(type) {
case *types.Interface:
// The term set of an interface is the intersection of the term sets of its
// embedded types.
tset.terms = allTermlist
for i := 0; i < u.NumEmbeddeds(); i++ {
embedded := u.EmbeddedType(i)
if _, ok := embedded.Underlying().(*TypeParam); ok {
return nil, fmt.Errorf("invalid embedded type %T", embedded)
}
tset2, err := computeTermSetInternal(embedded, seen, depth+1)
if err != nil {
return nil, err
}
tset.terms = tset.terms.intersect(tset2.terms)
}
case *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++ {
t := u.Term(i)
var terms termlist
switch t.Type().Underlying().(type) {
case *types.Interface:
tset2, err := computeTermSetInternal(t.Type(), seen, depth+1)
if err != nil {
return nil, err
}
terms = tset2.terms
case *TypeParam, *Union:
// A stand-alone type parameter or union is not permitted as union
// term.
return nil, fmt.Errorf("invalid union term %T", t)
default:
if t.Type() == types.Typ[types.Invalid] {
continue
}
terms = termlist{{t.Tilde(), t.Type()}}
}
tset.terms = tset.terms.union(terms)
if len(tset.terms) > maxTermCount {
return nil, fmt.Errorf("exceeded max term count %d", maxTermCount)
}
}
case *TypeParam:
panic("unreachable")
default:
// For all other types, the term set is just a single non-tilde term
// holding the type itself.
if u != types.Typ[types.Invalid] {
tset.terms = termlist{{false, t}}
}
}
return tset, nil
}
// under is a facade for the go/types internal function of the same name. It is
// used by typeterm.go.
func under(t types.Type) types.Type {
return t.Underlying()
}

View File

@ -0,0 +1,163 @@
// 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.
// Code generated by copytermlist.go DO NOT EDIT.
package typeparams
import (
"bytes"
"go/types"
)
// A termlist represents the type set represented by the union
// t1 y2 ... tn of the type sets of the terms t1 to tn.
// A termlist is in normal form if all terms are disjoint.
// termlist operations don't require the operands to be in
// normal form.
type termlist []*term
// allTermlist represents the set of all types.
// It is in normal form.
var allTermlist = termlist{new(term)}
// String prints the termlist exactly (without normalization).
func (xl termlist) String() string {
if len(xl) == 0 {
return "∅"
}
var buf bytes.Buffer
for i, x := range xl {
if i > 0 {
buf.WriteString(" ")
}
buf.WriteString(x.String())
}
return buf.String()
}
// isEmpty reports whether the termlist xl represents the empty set of types.
func (xl termlist) isEmpty() bool {
// If there's a non-nil term, the entire list is not empty.
// If the termlist is in normal form, this requires at most
// one iteration.
for _, x := range xl {
if x != nil {
return false
}
}
return true
}
// isAll reports whether the termlist xl represents the set of all types.
func (xl termlist) isAll() bool {
// If there's a 𝓤 term, the entire list is 𝓤.
// If the termlist is in normal form, this requires at most
// one iteration.
for _, x := range xl {
if x != nil && x.typ == nil {
return true
}
}
return false
}
// norm returns the normal form of xl.
func (xl termlist) norm() termlist {
// Quadratic algorithm, but good enough for now.
// TODO(gri) fix asymptotic performance
used := make([]bool, len(xl))
var rl termlist
for i, xi := range xl {
if xi == nil || used[i] {
continue
}
for j := i + 1; j < len(xl); j++ {
xj := xl[j]
if xj == nil || used[j] {
continue
}
if u1, u2 := xi.union(xj); u2 == nil {
// If we encounter a 𝓤 term, the entire list is 𝓤.
// Exit early.
// (Note that this is not just an optimization;
// if we continue, we may end up with a 𝓤 term
// and other terms and the result would not be
// in normal form.)
if u1.typ == nil {
return allTermlist
}
xi = u1
used[j] = true // xj is now unioned into xi - ignore it in future iterations
}
}
rl = append(rl, xi)
}
return rl
}
// union returns the union xl yl.
func (xl termlist) union(yl termlist) termlist {
return append(xl, yl...).norm()
}
// intersect returns the intersection xl ∩ yl.
func (xl termlist) intersect(yl termlist) termlist {
if xl.isEmpty() || yl.isEmpty() {
return nil
}
// Quadratic algorithm, but good enough for now.
// TODO(gri) fix asymptotic performance
var rl termlist
for _, x := range xl {
for _, y := range yl {
if r := x.intersect(y); r != nil {
rl = append(rl, r)
}
}
}
return rl.norm()
}
// equal reports whether xl and yl represent the same type set.
func (xl termlist) equal(yl termlist) bool {
// TODO(gri) this should be more efficient
return xl.subsetOf(yl) && yl.subsetOf(xl)
}
// includes reports whether t ∈ xl.
func (xl termlist) includes(t types.Type) bool {
for _, x := range xl {
if x.includes(t) {
return true
}
}
return false
}
// supersetOf reports whether y ⊆ xl.
func (xl termlist) supersetOf(y *term) bool {
for _, x := range xl {
if y.subsetOf(x) {
return true
}
}
return false
}
// subsetOf reports whether xl ⊆ yl.
func (xl termlist) subsetOf(yl termlist) bool {
if yl.isEmpty() {
return xl.isEmpty()
}
// each term x of xl must be a subset of yl
for _, x := range xl {
if !yl.supersetOf(x) {
return false // x is not a subset yl
}
}
return true
}

View File

@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !typeparams || !go1.18
// +build !typeparams !go1.18
//go:build !go1.18
// +build !go1.18
package typeparams
import (
"go/ast"
"go/token"
"go/types"
)
@ -16,18 +17,14 @@ func unsupported() {
panic("type parameters are unsupported at this go version")
}
// GetIndexExprData extracts data from *ast.IndexExpr nodes.
// For other nodes, GetIndexExprData returns nil.
func GetIndexExprData(n ast.Node) *IndexExprData {
if e, _ := n.(*ast.IndexExpr); e != nil {
return &IndexExprData{
X: e.X,
Lbrack: e.Lbrack,
Indices: []ast.Expr{e.Index},
Rbrack: e.Rbrack,
}
}
return nil
// 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
@ -46,6 +43,7 @@ func ForFuncType(*ast.FuncType) *ast.FieldList {
// 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 }
@ -72,42 +70,46 @@ 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
}
// SetForSignature panics if tparams is non-empty.
func SetForSignature(_ *types.Signature, tparams []*TypeParam) {
if len(tparams) > 0 {
unsupported()
}
}
// RecvTypeParams returns a nil slice.
func RecvTypeParams(sig *types.Signature) *TypeParamList {
return nil
}
// SetRecvTypeParams panics if rparams is non-empty.
func SetRecvTypeParams(sig *types.Signature, rparams []*TypeParam) {
if len(rparams) > 0 {
unsupported()
}
}
// IsComparable returns false, as no interfaces are type-restricted at this Go
// version.
func IsComparable(*types.Interface) bool {
return false
}
// IsConstraint returns false, as no interfaces are type-restricted at this Go
// IsMethodSet returns true, as no interfaces are type-restricted at this Go
// version.
func IsConstraint(*types.Interface) bool {
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 {
@ -131,19 +133,25 @@ func NamedTypeOrigin(named *types.Named) types.Type {
return named
}
// Term is a placeholder type, as type parameters are not supported at this Go
// version. Its methods panic on use.
type Term struct{}
// Term holds information about a structural type restriction.
type Term struct {
tilde bool
typ types.Type
}
func (*Term) Tilde() bool { unsupported(); return false }
func (*Term) Type() types.Type { unsupported(); return nil }
func (*Term) String() string { unsupported(); return "" }
func (*Term) Underlying() types.Type { unsupported(); return nil }
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 {
unsupported()
return nil
return &Term{tilde, typ}
}
// Union is a placeholder type, as type parameters are not supported at this Go
@ -162,16 +170,28 @@ func NewUnion(terms []*Term) *Union {
// InitInstanceInfo is a noop at this Go version.
func InitInstanceInfo(*types.Info) {}
// GetInstance returns nothing, as type parameters are not supported at this Go
// version.
func GetInstance(*types.Info, *ast.Ident) (*TypeList, types.Type) { return nil, nil }
// Instance is a placeholder type, as type parameters are not supported at this
// Go version.
type Instance struct {
TypeArgs *TypeList
Type types.Type
}
// Environment is a placeholder type, as type parameters are not supported at
// 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 Environment struct{}
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(env *Environment, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
unsupported()
return nil, nil
}

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build typeparams && go1.18
// +build typeparams,go1.18
//go:build go1.18
// +build go1.18
package typeparams
@ -12,29 +12,8 @@ import (
"go/types"
)
// GetIndexExprData extracts data from AST nodes that represent index
// expressions.
//
// For an ast.IndexExpr, the resulting IndexExprData will have exactly one
// index expression. For an ast.IndexListExpr (go1.18+), it may have a
// variable number of index expressions.
//
// For nodes that don't represent index expressions, GetIndexExprData returns
// nil.
func GetIndexExprData(n ast.Node) *IndexExprData {
switch e := n.(type) {
case *ast.IndexExpr:
return &IndexExprData{
X: e.X,
Lbrack: e.Lbrack,
Indices: []ast.Expr{e.Index},
Rbrack: e.Rbrack,
}
case *ast.IndexListExpr:
return (*IndexExprData)(e)
}
return nil
}
// IndexListExpr is an alias for ast.IndexListExpr.
type IndexListExpr = ast.IndexListExpr
// ForTypeSpec returns n.TypeParams.
func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList {
@ -71,34 +50,39 @@ 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()
}
// SetForSignature calls sig.SetTypeParams(tparams)
func SetForSignature(sig *types.Signature, tparams []*TypeParam) {
sig.SetTypeParams(tparams)
}
// RecvTypeParams returns sig.RecvTypeParams().
func RecvTypeParams(sig *types.Signature) *TypeParamList {
return sig.RecvTypeParams()
}
// SetRecvTypeParams calls sig.SetRecvTypeParams(rparams).
func SetRecvTypeParams(sig *types.Signature, rparams []*TypeParam) {
sig.SetRecvTypeParams(rparams)
}
// IsComparable calls iface.IsComparable().
func IsComparable(iface *types.Interface) bool {
return iface.IsComparable()
}
// IsConstraint calls iface.IsConstraint().
func IsConstraint(iface *types.Interface) bool {
return iface.IsConstraint()
// 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
@ -145,21 +129,23 @@ func InitInstanceInfo(info *types.Info) {
info.Instances = make(map[*ast.Ident]types.Instance)
}
// GetInstance extracts information about the instantiation occurring at the
// identifier id. id should be the identifier denoting a parameterized type or
// function in an instantiation expression or function call.
func GetInstance(info *types.Info, id *ast.Ident) (*TypeList, types.Type) {
if info.Instances != nil {
inf := info.Instances[id]
return inf.TypeArgs, inf.Type
}
return nil, nil
// 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
}
// Environment is an alias for types.Environment.
type Environment = types.Environment
// 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(env *Environment, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
return types.Instantiate(env, typ, targs, validate)
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
return types.Instantiate(ctxt, typ, targs, validate)
}

View File

@ -0,0 +1,170 @@
// 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.
// Code generated by copytermlist.go DO NOT EDIT.
package typeparams
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
//
type term struct {
tilde bool // valid if typ != nil
typ types.Type
}
func (x *term) String() string {
switch {
case x == nil:
return "∅"
case x.typ == nil:
return "𝓤"
case x.tilde:
return "~" + x.typ.String()
default:
return x.typ.String()
}
}
// equal reports whether x and y represent the same type set.
func (x *term) equal(y *term) bool {
// easy cases
switch {
case x == nil || y == nil:
return x == y
case x.typ == nil || y.typ == nil:
return x.typ == y.typ
}
// ∅ ⊂ x, y ⊂ 𝓤
return x.tilde == y.tilde && types.Identical(x.typ, y.typ)
}
// union returns the union x y: zero, one, or two non-nil terms.
func (x *term) union(y *term) (_, _ *term) {
// easy cases
switch {
case x == nil && y == nil:
return nil, nil // ∅ ∅ == ∅
case x == nil:
return y, nil // ∅ y == y
case y == nil:
return x, nil // x ∅ == x
case x.typ == nil:
return x, nil // 𝓤 y == 𝓤
case y.typ == nil:
return y, nil // x 𝓤 == 𝓤
}
// ∅ ⊂ x, y ⊂ 𝓤
if x.disjoint(y) {
return x, y // x y == (x, y) if x ∩ y == ∅
}
// x.typ == y.typ
// ~t ~t == ~t
// ~t T == ~t
// T ~t == ~t
// T T == T
if x.tilde || !y.tilde {
return x, nil
}
return y, nil
}
// intersect returns the intersection x ∩ y.
func (x *term) intersect(y *term) *term {
// easy cases
switch {
case x == nil || y == nil:
return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅
case x.typ == nil:
return y // 𝓤 ∩ y == y
case y.typ == nil:
return x // x ∩ 𝓤 == x
}
// ∅ ⊂ x, y ⊂ 𝓤
if x.disjoint(y) {
return nil // x ∩ y == ∅ if x ∩ y == ∅
}
// x.typ == y.typ
// ~t ∩ ~t == ~t
// ~t ∩ T == T
// T ∩ ~t == T
// T ∩ T == T
if !x.tilde || y.tilde {
return x
}
return y
}
// includes reports whether t ∈ x.
func (x *term) includes(t types.Type) bool {
// easy cases
switch {
case x == nil:
return false // t ∈ ∅ == false
case x.typ == nil:
return true // t ∈ 𝓤 == true
}
// ∅ ⊂ x ⊂ 𝓤
u := t
if x.tilde {
u = under(u)
}
return types.Identical(x.typ, u)
}
// subsetOf reports whether x ⊆ y.
func (x *term) subsetOf(y *term) bool {
// easy cases
switch {
case x == nil:
return true // ∅ ⊆ y == true
case y == nil:
return false // x ⊆ ∅ == false since x != ∅
case y.typ == nil:
return true // x ⊆ 𝓤 == true
case x.typ == nil:
return false // 𝓤 ⊆ y == false since y != 𝓤
}
// ∅ ⊂ x, y ⊂ 𝓤
if x.disjoint(y) {
return false // x ⊆ y == false if x ∩ y == ∅
}
// x.typ == y.typ
// ~t ⊆ ~t == true
// ~t ⊆ T == false
// T ⊆ ~t == true
// T ⊆ T == true
return !x.tilde || y.tilde
}
// disjoint reports whether x ∩ y == ∅.
// x.typ and y.typ must not be nil.
func (x *term) disjoint(y *term) bool {
if debug && (x.typ == nil || y.typ == nil) {
panic("invalid argument(s)")
}
ux := x.typ
if y.tilde {
ux = under(ux)
}
uy := y.typ
if x.tilde {
uy = under(uy)
}
return !types.Identical(ux, uy)
}

View File

@ -1365,4 +1365,162 @@ const (
// return i
// }
InvalidGo
// All codes below were added in Go 1.17.
/* decl */
// BadDecl occurs when a declaration has invalid syntax.
BadDecl
// RepeatedDecl occurs when an identifier occurs more than once on the left
// hand side of a short variable declaration.
//
// Example:
// func _() {
// x, y, y := 1, 2, 3
// }
RepeatedDecl
/* unsafe */
// InvalidUnsafeAdd occurs when unsafe.Add is called with a
// length argument that is not of integer type.
//
// Example:
// import "unsafe"
//
// var p unsafe.Pointer
// var _ = unsafe.Add(p, float64(1))
InvalidUnsafeAdd
// InvalidUnsafeSlice occurs when unsafe.Slice is called with a
// pointer argument that is not of pointer type or a length argument
// that is not of integer type, negative, or out of bounds.
//
// Example:
// import "unsafe"
//
// var x int
// var _ = unsafe.Slice(x, 1)
//
// Example:
// import "unsafe"
//
// var x int
// var _ = unsafe.Slice(&x, float64(1))
//
// Example:
// import "unsafe"
//
// var x int
// var _ = unsafe.Slice(&x, -1)
//
// Example:
// import "unsafe"
//
// var x int
// var _ = unsafe.Slice(&x, uint64(1) << 63)
InvalidUnsafeSlice
// All codes below were added in Go 1.18.
/* features */
// UnsupportedFeature occurs when a language feature is used that is not
// supported at this Go version.
UnsupportedFeature
/* type params */
// NotAGenericType occurs when a non-generic type is used where a generic
// type is expected: in type or function instantiation.
//
// Example:
// type T int
//
// var _ T[int]
NotAGenericType
// WrongTypeArgCount occurs when a type or function is instantiated with an
// incorrent 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.
//
// Example:
// type T[p any] int
//
// var _ T[int, string]
//
// Example:
// func f[T any]() {}
//
// var x = f
WrongTypeArgCount
// CannotInferTypeArgs occurs when type or function type argument inference
// fails to infer all type arguments.
//
// Example:
// func f[T any]() {}
//
// func _() {
// f()
// }
//
// Example:
// type N[P, Q any] struct{}
//
// var _ N[int]
CannotInferTypeArgs
// InvalidTypeArg occurs when a type argument does not satisfy its
// corresponding type parameter constraints.
//
// Example:
// type T[P ~int] struct{}
//
// var _ T[string]
InvalidTypeArg // arguments? InferenceFailed
// InvalidInstanceCycle occurs when an invalid cycle is detected
// within the instantiation graph.
//
// Example:
// func f[T any]() { f[*T]() }
InvalidInstanceCycle
// InvalidUnion occurs when an embedded union or approximation element is
// not valid.
//
// Example:
// type _ interface {
// ~int | interface{ m() }
// }
InvalidUnion
// MisplacedConstraintIface occurs when a constraint-type interface is used
// outside of constraint position.
//
// Example:
// type I interface { ~int }
//
// var _ I
MisplacedConstraintIface
// InvalidMethodTypeParams occurs when methods have type parameters.
//
// It cannot be encountered with an AST parsed using go/parser.
InvalidMethodTypeParams
// MisplacedTypeParam occurs when a type parameter is used in a place where
// it is not permitted.
//
// Example:
// type T[P any] P
//
// Example:
// type T[P any] struct{ *P }
MisplacedTypeParam
)

View File

@ -138,11 +138,25 @@ func _() {
_ = x[UnusedResults-128]
_ = x[InvalidDefer-129]
_ = x[InvalidGo-130]
_ = x[BadDecl-131]
_ = x[RepeatedDecl-132]
_ = x[InvalidUnsafeAdd-133]
_ = x[InvalidUnsafeSlice-134]
_ = x[UnsupportedFeature-135]
_ = x[NotAGenericType-136]
_ = x[WrongTypeArgCount-137]
_ = x[CannotInferTypeArgs-138]
_ = x[InvalidTypeArg-139]
_ = x[InvalidInstanceCycle-140]
_ = x[InvalidUnion-141]
_ = x[MisplacedConstraintIface-142]
_ = x[InvalidMethodTypeParams-143]
_ = x[MisplacedTypeParam-144]
}
const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGo"
const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParam"
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}
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}
func (i ErrorCode) String() string {
i -= 1

View File

@ -48,3 +48,5 @@ 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 }

View File

@ -0,0 +1,19 @@
// 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
}
}