mirror of https://github.com/docker/buildx.git
				
				
				
			vendor: golang.org/x/tools v0.14.0, golang.org/x/mod v0.13.0, golang.org/x/sync v0.4.0
full diff: - https://github.com/golang/tools/compare/v0.10.0...v0.14.0 - https://github.com/golang/mod/compare/v0.11.0...v0.13.0 - https://github.com/golang/sync/compare/v0.3.0...v0.4.0 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
		
							parent
							
								
									7206e2d179
								
							
						
					
					
						commit
						da95d9f0ca
					
				
							
								
								
									
										6
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										6
									
								
								go.mod
								
								
								
								
							|  | @ -44,8 +44,8 @@ require ( | |||
| 	go.opentelemetry.io/otel/metric v1.19.0 | ||||
| 	go.opentelemetry.io/otel/sdk/metric v1.19.0 | ||||
| 	go.opentelemetry.io/otel/trace v1.19.0 | ||||
| 	golang.org/x/mod v0.11.0 | ||||
| 	golang.org/x/sync v0.3.0 | ||||
| 	golang.org/x/mod v0.13.0 | ||||
| 	golang.org/x/sync v0.4.0 | ||||
| 	golang.org/x/sys v0.16.0 | ||||
| 	golang.org/x/term v0.15.0 | ||||
| 	google.golang.org/grpc v1.58.3 | ||||
|  | @ -155,7 +155,7 @@ require ( | |||
| 	golang.org/x/oauth2 v0.10.0 // indirect | ||||
| 	golang.org/x/text v0.14.0 // indirect | ||||
| 	golang.org/x/time v0.3.0 // indirect | ||||
| 	golang.org/x/tools v0.10.0 // indirect | ||||
| 	golang.org/x/tools v0.14.0 // indirect | ||||
| 	google.golang.org/appengine v1.6.7 // indirect | ||||
| 	google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect | ||||
| 	google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect | ||||
|  |  | |||
							
								
								
									
										12
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										12
									
								
								go.sum
								
								
								
								
							|  | @ -527,8 +527,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx | |||
| golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= | ||||
| golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||||
| golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= | ||||
| golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= | ||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
|  | @ -553,8 +553,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||
| golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= | ||||
| golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= | ||||
| golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= | ||||
| golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
|  | @ -592,8 +592,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn | |||
| golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
| golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||||
| golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||||
| golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= | ||||
| golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= | ||||
| golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= | ||||
| golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= | ||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ import ( | |||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| // Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be
 | ||||
| // Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be
 | ||||
| // compiled the first time it is needed.
 | ||||
| type Regexp struct { | ||||
| 	str  string | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 
 | ||||
| // Package module defines the module.Version type along with support code.
 | ||||
| //
 | ||||
| // The module.Version type is a simple Path, Version pair:
 | ||||
| // The [module.Version] type is a simple Path, Version pair:
 | ||||
| //
 | ||||
| //	type Version struct {
 | ||||
| //		Path string
 | ||||
|  | @ -12,7 +12,7 @@ | |||
| //	}
 | ||||
| //
 | ||||
| // There are no restrictions imposed directly by use of this structure,
 | ||||
| // but additional checking functions, most notably Check, verify that
 | ||||
| // but additional checking functions, most notably [Check], verify that
 | ||||
| // a particular path, version pair is valid.
 | ||||
| //
 | ||||
| // # Escaped Paths
 | ||||
|  | @ -140,7 +140,7 @@ type ModuleError struct { | |||
| 	Err     error | ||||
| } | ||||
| 
 | ||||
| // VersionError returns a ModuleError derived from a Version and error,
 | ||||
| // VersionError returns a [ModuleError] derived from a [Version] and error,
 | ||||
| // or err itself if it is already such an error.
 | ||||
| func VersionError(v Version, err error) error { | ||||
| 	var mErr *ModuleError | ||||
|  | @ -169,7 +169,7 @@ func (e *ModuleError) Unwrap() error { return e.Err } | |||
| // An InvalidVersionError indicates an error specific to a version, with the
 | ||||
| // module path unknown or specified externally.
 | ||||
| //
 | ||||
| // A ModuleError may wrap an InvalidVersionError, but an InvalidVersionError
 | ||||
| // A [ModuleError] may wrap an InvalidVersionError, but an InvalidVersionError
 | ||||
| // must not wrap a ModuleError.
 | ||||
| type InvalidVersionError struct { | ||||
| 	Version string | ||||
|  | @ -193,8 +193,8 @@ func (e *InvalidVersionError) Error() string { | |||
| func (e *InvalidVersionError) Unwrap() error { return e.Err } | ||||
| 
 | ||||
| // An InvalidPathError indicates a module, import, or file path doesn't
 | ||||
| // satisfy all naming constraints. See CheckPath, CheckImportPath,
 | ||||
| // and CheckFilePath for specific restrictions.
 | ||||
| // satisfy all naming constraints. See [CheckPath], [CheckImportPath],
 | ||||
| // and [CheckFilePath] for specific restrictions.
 | ||||
| type InvalidPathError struct { | ||||
| 	Kind string // "module", "import", or "file"
 | ||||
| 	Path string | ||||
|  | @ -294,7 +294,7 @@ func fileNameOK(r rune) bool { | |||
| } | ||||
| 
 | ||||
| // CheckPath checks that a module path is valid.
 | ||||
| // A valid module path is a valid import path, as checked by CheckImportPath,
 | ||||
| // A valid module path is a valid import path, as checked by [CheckImportPath],
 | ||||
| // with three additional constraints.
 | ||||
| // First, the leading path element (up to the first slash, if any),
 | ||||
| // by convention a domain name, must contain only lower-case ASCII letters,
 | ||||
|  | @ -380,7 +380,7 @@ const ( | |||
| // checkPath returns an error describing why the path is not valid.
 | ||||
| // Because these checks apply to module, import, and file paths,
 | ||||
| // and because other checks may be applied, the caller is expected to wrap
 | ||||
| // this error with InvalidPathError.
 | ||||
| // this error with [InvalidPathError].
 | ||||
| func checkPath(path string, kind pathKind) error { | ||||
| 	if !utf8.ValidString(path) { | ||||
| 		return fmt.Errorf("invalid UTF-8") | ||||
|  | @ -532,7 +532,7 @@ var badWindowsNames = []string{ | |||
| // they require ".vN" instead of "/vN", and for all N, not just N >= 2.
 | ||||
| // SplitPathVersion returns with ok = false when presented with
 | ||||
| // a path whose last path element does not satisfy the constraints
 | ||||
| // applied by CheckPath, such as "example.com/pkg/v1" or "example.com/pkg/v1.2".
 | ||||
| // applied by [CheckPath], such as "example.com/pkg/v1" or "example.com/pkg/v1.2".
 | ||||
| func SplitPathVersion(path string) (prefix, pathMajor string, ok bool) { | ||||
| 	if strings.HasPrefix(path, "gopkg.in/") { | ||||
| 		return splitGopkgIn(path) | ||||
|  | @ -582,7 +582,7 @@ func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) { | |||
| // MatchPathMajor reports whether the semantic version v
 | ||||
| // matches the path major version pathMajor.
 | ||||
| //
 | ||||
| // MatchPathMajor returns true if and only if CheckPathMajor returns nil.
 | ||||
| // MatchPathMajor returns true if and only if [CheckPathMajor] returns nil.
 | ||||
| func MatchPathMajor(v, pathMajor string) bool { | ||||
| 	return CheckPathMajor(v, pathMajor) == nil | ||||
| } | ||||
|  | @ -622,7 +622,7 @@ func CheckPathMajor(v, pathMajor string) error { | |||
| // PathMajorPrefix returns the major-version tag prefix implied by pathMajor.
 | ||||
| // An empty PathMajorPrefix allows either v0 or v1.
 | ||||
| //
 | ||||
| // Note that MatchPathMajor may accept some versions that do not actually begin
 | ||||
| // Note that [MatchPathMajor] may accept some versions that do not actually begin
 | ||||
| // with this prefix: namely, it accepts a 'v0.0.0-' prefix for a '.v1'
 | ||||
| // pathMajor, even though that pathMajor implies 'v1' tagging.
 | ||||
| func PathMajorPrefix(pathMajor string) string { | ||||
|  | @ -643,7 +643,7 @@ func PathMajorPrefix(pathMajor string) string { | |||
| } | ||||
| 
 | ||||
| // CanonicalVersion returns the canonical form of the version string v.
 | ||||
| // It is the same as semver.Canonical(v) except that it preserves the special build suffix "+incompatible".
 | ||||
| // It is the same as [semver.Canonical] except that it preserves the special build suffix "+incompatible".
 | ||||
| func CanonicalVersion(v string) string { | ||||
| 	cv := semver.Canonical(v) | ||||
| 	if semver.Build(v) == "+incompatible" { | ||||
|  | @ -652,8 +652,8 @@ func CanonicalVersion(v string) string { | |||
| 	return cv | ||||
| } | ||||
| 
 | ||||
| // Sort sorts the list by Path, breaking ties by comparing Version fields.
 | ||||
| // The Version fields are interpreted as semantic versions (using semver.Compare)
 | ||||
| // Sort sorts the list by Path, breaking ties by comparing [Version] fields.
 | ||||
| // The Version fields are interpreted as semantic versions (using [semver.Compare])
 | ||||
| // optionally followed by a tie-breaking suffix introduced by a slash character,
 | ||||
| // like in "v0.0.1/go.mod".
 | ||||
| func Sort(list []Version) { | ||||
|  | @ -793,7 +793,7 @@ func unescapeString(escaped string) (string, bool) { | |||
| } | ||||
| 
 | ||||
| // MatchPrefixPatterns reports whether any path prefix of target matches one of
 | ||||
| // the glob patterns (as defined by path.Match) in the comma-separated globs
 | ||||
| // the glob patterns (as defined by [path.Match]) in the comma-separated globs
 | ||||
| // list. This implements the algorithm used when matching a module path to the
 | ||||
| // GOPRIVATE environment variable, as described by 'go help module-private'.
 | ||||
| //
 | ||||
|  |  | |||
|  | @ -125,7 +125,7 @@ func IsPseudoVersion(v string) bool { | |||
| } | ||||
| 
 | ||||
| // IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base,
 | ||||
| // timestamp, and revision, as returned by ZeroPseudoVersion.
 | ||||
| // timestamp, and revision, as returned by [ZeroPseudoVersion].
 | ||||
| func IsZeroPseudoVersion(v string) bool { | ||||
| 	return v == ZeroPseudoVersion(semver.Major(v)) | ||||
| } | ||||
|  |  | |||
|  | @ -140,7 +140,7 @@ func Compare(v, w string) int { | |||
| // Max canonicalizes its arguments and then returns the version string
 | ||||
| // that compares greater.
 | ||||
| //
 | ||||
| // Deprecated: use Compare instead. In most cases, returning a canonicalized
 | ||||
| // Deprecated: use [Compare] instead. In most cases, returning a canonicalized
 | ||||
| // version is not expected or desired.
 | ||||
| func Max(v, w string) string { | ||||
| 	v = Canonical(v) | ||||
|  | @ -151,7 +151,7 @@ func Max(v, w string) string { | |||
| 	return w | ||||
| } | ||||
| 
 | ||||
| // ByVersion implements sort.Interface for sorting semantic version strings.
 | ||||
| // ByVersion implements [sort.Interface] for sorting semantic version strings.
 | ||||
| type ByVersion []string | ||||
| 
 | ||||
| func (vs ByVersion) Len() int      { return len(vs) } | ||||
|  | @ -164,7 +164,7 @@ func (vs ByVersion) Less(i, j int) bool { | |||
| 	return vs[i] < vs[j] | ||||
| } | ||||
| 
 | ||||
| // Sort sorts a list of semantic version strings using ByVersion.
 | ||||
| // Sort sorts a list of semantic version strings using [ByVersion].
 | ||||
| func Sort(list []string) { | ||||
| 	sort.Sort(ByVersion(list)) | ||||
| } | ||||
|  |  | |||
|  | @ -188,6 +188,8 @@ type Generator struct { | |||
| 
 | ||||
| 	trimPrefix  string | ||||
| 	lineComment bool | ||||
| 
 | ||||
| 	logf func(format string, args ...interface{}) // test logging hook; nil when not testing
 | ||||
| } | ||||
| 
 | ||||
| func (g *Generator) Printf(format string, args ...interface{}) { | ||||
|  | @ -221,13 +223,14 @@ func (g *Generator) parsePackage(patterns []string, tags []string) { | |||
| 		// in a separate pass? For later.
 | ||||
| 		Tests:      false, | ||||
| 		BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))}, | ||||
| 		Logf:       g.logf, | ||||
| 	} | ||||
| 	pkgs, err := packages.Load(cfg, patterns...) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	if len(pkgs) != 1 { | ||||
| 		log.Fatalf("error: %d packages found", len(pkgs)) | ||||
| 		log.Fatalf("error: %d packages matching %v", len(pkgs), strings.Join(patterns, " ")) | ||||
| 	} | ||||
| 	g.addPackage(pkgs[0]) | ||||
| } | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ package packagesdriver | |||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"go/types" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"golang.org/x/tools/internal/gocommand" | ||||
|  | @ -16,7 +15,7 @@ import ( | |||
| 
 | ||||
| var debug = false | ||||
| 
 | ||||
| func GetSizesGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (types.Sizes, error) { | ||||
| func GetSizesForArgsGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) { | ||||
| 	inv.Verb = "list" | ||||
| 	inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"} | ||||
| 	stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv) | ||||
|  | @ -29,21 +28,21 @@ func GetSizesGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner * | |||
| 			inv.Args = []string{"GOARCH"} | ||||
| 			envout, enverr := gocmdRunner.Run(ctx, inv) | ||||
| 			if enverr != nil { | ||||
| 				return nil, enverr | ||||
| 				return "", "", enverr | ||||
| 			} | ||||
| 			goarch = strings.TrimSpace(envout.String()) | ||||
| 			compiler = "gc" | ||||
| 		} else { | ||||
| 			return nil, friendlyErr | ||||
| 			return "", "", friendlyErr | ||||
| 		} | ||||
| 	} else { | ||||
| 		fields := strings.Fields(stdout.String()) | ||||
| 		if len(fields) < 2 { | ||||
| 			return nil, fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>", | ||||
| 			return "", "", fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>", | ||||
| 				stdout.String(), stderr.String()) | ||||
| 		} | ||||
| 		goarch = fields[0] | ||||
| 		compiler = fields[1] | ||||
| 	} | ||||
| 	return types.SizesFor(compiler, goarch), nil | ||||
| 	return compiler, goarch, nil | ||||
| } | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ The Package struct provides basic information about the package, including | |||
|   - Imports, a map from source import strings to the Packages they name; | ||||
|   - Types, the type information for the package's exported symbols; | ||||
|   - Syntax, the parsed syntax trees for the package's source code; and | ||||
|   - TypeInfo, the result of a complete type-check of the package syntax trees. | ||||
|   - TypesInfo, the result of a complete type-check of the package syntax trees. | ||||
| 
 | ||||
| (See the documentation for type Package for the complete list of fields | ||||
| and more detailed descriptions.) | ||||
|  |  | |||
|  | @ -9,8 +9,6 @@ import ( | |||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"go/types" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path" | ||||
|  | @ -153,10 +151,10 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { | |||
| 	if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { | ||||
| 		sizeswg.Add(1) | ||||
| 		go func() { | ||||
| 			var sizes types.Sizes | ||||
| 			sizes, sizeserr = packagesdriver.GetSizesGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) | ||||
| 			// types.SizesFor always returns nil or a *types.StdSizes.
 | ||||
| 			response.dr.Sizes, _ = sizes.(*types.StdSizes) | ||||
| 			compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) | ||||
| 			sizeserr = err | ||||
| 			response.dr.Compiler = compiler | ||||
| 			response.dr.Arch = arch | ||||
| 			sizeswg.Done() | ||||
| 		}() | ||||
| 	} | ||||
|  | @ -671,6 +669,9 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse | |||
| 		// Temporary work-around for golang/go#39986. Parse filenames out of
 | ||||
| 		// error messages. This happens if there are unrecoverable syntax
 | ||||
| 		// errors in the source, so we can't match on a specific error message.
 | ||||
| 		//
 | ||||
| 		// TODO(rfindley): remove this heuristic, in favor of considering
 | ||||
| 		// InvalidGoFiles from the list driver.
 | ||||
| 		if err := p.Error; err != nil && state.shouldAddFilenameFromError(p) { | ||||
| 			addFilenameFromPos := func(pos string) bool { | ||||
| 				split := strings.Split(pos, ":") | ||||
|  | @ -1107,7 +1108,7 @@ func (state *golistState) writeOverlays() (filename string, cleanup func(), err | |||
| 	if len(state.cfg.Overlay) == 0 { | ||||
| 		return "", func() {}, nil | ||||
| 	} | ||||
| 	dir, err := ioutil.TempDir("", "gopackages-*") | ||||
| 	dir, err := os.MkdirTemp("", "gopackages-*") | ||||
| 	if err != nil { | ||||
| 		return "", nil, err | ||||
| 	} | ||||
|  | @ -1126,7 +1127,7 @@ func (state *golistState) writeOverlays() (filename string, cleanup func(), err | |||
| 		// Create a unique filename for the overlaid files, to avoid
 | ||||
| 		// creating nested directories.
 | ||||
| 		noSeparator := strings.Join(strings.Split(filepath.ToSlash(k), "/"), "") | ||||
| 		f, err := ioutil.TempFile(dir, fmt.Sprintf("*-%s", noSeparator)) | ||||
| 		f, err := os.CreateTemp(dir, fmt.Sprintf("*-%s", noSeparator)) | ||||
| 		if err != nil { | ||||
| 			return "", func() {}, err | ||||
| 		} | ||||
|  | @ -1144,7 +1145,7 @@ func (state *golistState) writeOverlays() (filename string, cleanup func(), err | |||
| 	} | ||||
| 	// Write out the overlay file that contains the filepath mappings.
 | ||||
| 	filename = filepath.Join(dir, "overlay.json") | ||||
| 	if err := ioutil.WriteFile(filename, b, 0665); err != nil { | ||||
| 	if err := os.WriteFile(filename, b, 0665); err != nil { | ||||
| 		return "", func() {}, err | ||||
| 	} | ||||
| 	return filename, cleanup, nil | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ import ( | |||
| 	"go/token" | ||||
| 	"go/types" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | @ -220,8 +219,10 @@ type driverResponse struct { | |||
| 	// lists of multiple drivers, go/packages will fall back to the next driver.
 | ||||
| 	NotHandled bool | ||||
| 
 | ||||
| 	// Sizes, if not nil, is the types.Sizes to use when type checking.
 | ||||
| 	Sizes *types.StdSizes | ||||
| 	// Compiler and Arch are the arguments pass of types.SizesFor
 | ||||
| 	// to get a types.Sizes to use when type checking.
 | ||||
| 	Compiler string | ||||
| 	Arch     string | ||||
| 
 | ||||
| 	// Roots is the set of package IDs that make up the root packages.
 | ||||
| 	// We have to encode this separately because when we encode a single package
 | ||||
|  | @ -262,7 +263,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) { | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	l.sizes = response.Sizes | ||||
| 	l.sizes = types.SizesFor(response.Compiler, response.Arch) | ||||
| 	return l.refine(response) | ||||
| } | ||||
| 
 | ||||
|  | @ -630,7 +631,7 @@ func newLoader(cfg *Config) *loader { | |||
| 	return ld | ||||
| } | ||||
| 
 | ||||
| // refine connects the supplied packages into a graph and then adds type and
 | ||||
| // refine connects the supplied packages into a graph and then adds type
 | ||||
| // and syntax information as requested by the LoadMode.
 | ||||
| func (ld *loader) refine(response *driverResponse) ([]*Package, error) { | ||||
| 	roots := response.Roots | ||||
|  | @ -1043,6 +1044,9 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { | |||
| 		Error: appendError, | ||||
| 		Sizes: ld.sizes, | ||||
| 	} | ||||
| 	if lpkg.Module != nil && lpkg.Module.GoVersion != "" { | ||||
| 		typesinternal.SetGoVersion(tc, "go"+lpkg.Module.GoVersion) | ||||
| 	} | ||||
| 	if (ld.Mode & typecheckCgo) != 0 { | ||||
| 		if !typesinternal.SetUsesCgo(tc) { | ||||
| 			appendError(Error{ | ||||
|  | @ -1122,7 +1126,7 @@ func (ld *loader) parseFile(filename string) (*ast.File, error) { | |||
| 		var err error | ||||
| 		if src == nil { | ||||
| 			ioLimit <- true // wait
 | ||||
| 			src, err = ioutil.ReadFile(filename) | ||||
| 			src, err = os.ReadFile(filename) | ||||
| 			<-ioLimit // signal
 | ||||
| 		} | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -0,0 +1,827 @@ | |||
| // Copyright 2018 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Package objectpath defines a naming scheme for types.Objects
 | ||||
| // (that is, named entities in Go programs) relative to their enclosing
 | ||||
| // package.
 | ||||
| //
 | ||||
| // Type-checker objects are canonical, so they are usually identified by
 | ||||
| // their address in memory (a pointer), but a pointer has meaning only
 | ||||
| // within one address space. By contrast, objectpath names allow the
 | ||||
| // identity of an object to be sent from one program to another,
 | ||||
| // establishing a correspondence between types.Object variables that are
 | ||||
| // distinct but logically equivalent.
 | ||||
| //
 | ||||
| // A single object may have multiple paths. In this example,
 | ||||
| //
 | ||||
| //	type A struct{ X int }
 | ||||
| //	type B A
 | ||||
| //
 | ||||
| // the field X has two paths due to its membership of both A and B.
 | ||||
| // The For(obj) function always returns one of these paths, arbitrarily
 | ||||
| // but consistently.
 | ||||
| package objectpath | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"go/types" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	_ "unsafe" | ||||
| 
 | ||||
| 	"golang.org/x/tools/internal/typeparams" | ||||
| 	"golang.org/x/tools/internal/typesinternal" | ||||
| ) | ||||
| 
 | ||||
| // A Path is an opaque name that identifies a types.Object
 | ||||
| // relative to its package. Conceptually, the name consists of a
 | ||||
| // sequence of destructuring operations applied to the package scope
 | ||||
| // to obtain the original object.
 | ||||
| // The name does not include the package itself.
 | ||||
| type Path string | ||||
| 
 | ||||
| // Encoding
 | ||||
| //
 | ||||
| // An object path is a textual and (with training) human-readable encoding
 | ||||
| // of a sequence of destructuring operators, starting from a types.Package.
 | ||||
| // The sequences represent a path through the package/object/type graph.
 | ||||
| // We classify these operators by their type:
 | ||||
| //
 | ||||
| //	PO package->object	Package.Scope.Lookup
 | ||||
| //	OT  object->type 	Object.Type
 | ||||
| //	TT    type->type 	Type.{Elem,Key,Params,Results,Underlying} [EKPRU]
 | ||||
| //	TO   type->object	Type.{At,Field,Method,Obj} [AFMO]
 | ||||
| //
 | ||||
| // All valid paths start with a package and end at an object
 | ||||
| // and thus may be defined by the regular language:
 | ||||
| //
 | ||||
| //	objectpath = PO (OT TT* TO)*
 | ||||
| //
 | ||||
| // The concrete encoding follows directly:
 | ||||
| //   - The only PO operator is Package.Scope.Lookup, which requires an identifier.
 | ||||
| //   - The only OT operator is Object.Type,
 | ||||
| //     which we encode as '.' because dot cannot appear in an identifier.
 | ||||
| //   - The TT operators are encoded as [EKPRUTC];
 | ||||
| //     one of these (TypeParam) requires an integer operand,
 | ||||
| //     which is encoded as a string of decimal digits.
 | ||||
| //   - The TO operators are encoded as [AFMO];
 | ||||
| //     three of these (At,Field,Method) require an integer operand,
 | ||||
| //     which is encoded as a string of decimal digits.
 | ||||
| //     These indices are stable across different representations
 | ||||
| //     of the same package, even source and export data.
 | ||||
| //     The indices used are implementation specific and may not correspond to
 | ||||
| //     the argument to the go/types function.
 | ||||
| //
 | ||||
| // In the example below,
 | ||||
| //
 | ||||
| //	package p
 | ||||
| //
 | ||||
| //	type T interface {
 | ||||
| //		f() (a string, b struct{ X int })
 | ||||
| //	}
 | ||||
| //
 | ||||
| // field X has the path "T.UM0.RA1.F0",
 | ||||
| // representing the following sequence of operations:
 | ||||
| //
 | ||||
| //	p.Lookup("T")					T
 | ||||
| //	.Type().Underlying().Method(0).			f
 | ||||
| //	.Type().Results().At(1)				b
 | ||||
| //	.Type().Field(0)					X
 | ||||
| //
 | ||||
| // The encoding is not maximally compact---every R or P is
 | ||||
| // followed by an A, for example---but this simplifies the
 | ||||
| // encoder and decoder.
 | ||||
| const ( | ||||
| 	// object->type operators
 | ||||
| 	opType = '.' // .Type()		  (Object)
 | ||||
| 
 | ||||
| 	// type->type operators
 | ||||
| 	opElem       = 'E' // .Elem()		        (Pointer, Slice, Array, Chan, Map)
 | ||||
| 	opKey        = 'K' // .Key()		        (Map)
 | ||||
| 	opParams     = 'P' // .Params()		      (Signature)
 | ||||
| 	opResults    = 'R' // .Results()	      (Signature)
 | ||||
| 	opUnderlying = 'U' // .Underlying()	    (Named)
 | ||||
| 	opTypeParam  = 'T' // .TypeParams.At(i) (Named, Signature)
 | ||||
| 	opConstraint = 'C' // .Constraint()     (TypeParam)
 | ||||
| 
 | ||||
| 	// type->object operators
 | ||||
| 	opAt     = 'A' // .At(i)		 (Tuple)
 | ||||
| 	opField  = 'F' // .Field(i)	 (Struct)
 | ||||
| 	opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored)
 | ||||
| 	opObj    = 'O' // .Obj()		 (Named, TypeParam)
 | ||||
| ) | ||||
| 
 | ||||
| // For is equivalent to new(Encoder).For(obj).
 | ||||
| //
 | ||||
| // It may be more efficient to reuse a single Encoder across several calls.
 | ||||
| func For(obj types.Object) (Path, error) { | ||||
| 	return new(Encoder).For(obj) | ||||
| } | ||||
| 
 | ||||
| // An Encoder amortizes the cost of encoding the paths of multiple objects.
 | ||||
| // The zero value of an Encoder is ready to use.
 | ||||
| type Encoder struct { | ||||
| 	scopeMemo         map[*types.Scope][]types.Object // memoization of scopeObjects
 | ||||
| 	namedMethodsMemo  map[*types.Named][]*types.Func  // memoization of namedMethods()
 | ||||
| 	skipMethodSorting bool | ||||
| } | ||||
| 
 | ||||
| // Expose back doors so that gopls can avoid method sorting, which can dominate
 | ||||
| // analysis on certain repositories.
 | ||||
| //
 | ||||
| // TODO(golang/go#61443): remove this.
 | ||||
| func init() { | ||||
| 	typesinternal.SkipEncoderMethodSorting = func(enc interface{}) { | ||||
| 		enc.(*Encoder).skipMethodSorting = true | ||||
| 	} | ||||
| 	typesinternal.ObjectpathObject = object | ||||
| } | ||||
| 
 | ||||
| // For returns the path to an object relative to its package,
 | ||||
| // or an error if the object is not accessible from the package's Scope.
 | ||||
| //
 | ||||
| // The For function guarantees to return a path only for the following objects:
 | ||||
| // - package-level types
 | ||||
| // - exported package-level non-types
 | ||||
| // - methods
 | ||||
| // - parameter and result variables
 | ||||
| // - struct fields
 | ||||
| // These objects are sufficient to define the API of their package.
 | ||||
| // The objects described by a package's export data are drawn from this set.
 | ||||
| //
 | ||||
| // The set of objects accessible from a package's Scope depends on
 | ||||
| // whether the package was produced by type-checking syntax, or
 | ||||
| // reading export data; the latter may have a smaller Scope since
 | ||||
| // export data trims objects that are not reachable from an exported
 | ||||
| // declaration. For example, the For function will return a path for
 | ||||
| // an exported method of an unexported type that is not reachable
 | ||||
| // from any public declaration; this path will cause the Object
 | ||||
| // function to fail if called on a package loaded from export data.
 | ||||
| // TODO(adonovan): is this a bug or feature? Should this package
 | ||||
| // compute accessibility in the same way?
 | ||||
| //
 | ||||
| // For does not return a path for predeclared names, imported package
 | ||||
| // names, local names, and unexported package-level names (except
 | ||||
| // types).
 | ||||
| //
 | ||||
| // Example: given this definition,
 | ||||
| //
 | ||||
| //	package p
 | ||||
| //
 | ||||
| //	type T interface {
 | ||||
| //		f() (a string, b struct{ X int })
 | ||||
| //	}
 | ||||
| //
 | ||||
| // For(X) would return a path that denotes the following sequence of operations:
 | ||||
| //
 | ||||
| //	p.Scope().Lookup("T")				(TypeName T)
 | ||||
| //	.Type().Underlying().Method(0).			(method Func f)
 | ||||
| //	.Type().Results().At(1)				(field Var b)
 | ||||
| //	.Type().Field(0)					(field Var X)
 | ||||
| //
 | ||||
| // where p is the package (*types.Package) to which X belongs.
 | ||||
| func (enc *Encoder) For(obj types.Object) (Path, error) { | ||||
| 	pkg := obj.Pkg() | ||||
| 
 | ||||
| 	// This table lists the cases of interest.
 | ||||
| 	//
 | ||||
| 	// Object				Action
 | ||||
| 	// ------                               ------
 | ||||
| 	// nil					reject
 | ||||
| 	// builtin				reject
 | ||||
| 	// pkgname				reject
 | ||||
| 	// label				reject
 | ||||
| 	// var
 | ||||
| 	//    package-level			accept
 | ||||
| 	//    func param/result			accept
 | ||||
| 	//    local				reject
 | ||||
| 	//    struct field			accept
 | ||||
| 	// const
 | ||||
| 	//    package-level			accept
 | ||||
| 	//    local				reject
 | ||||
| 	// func
 | ||||
| 	//    package-level			accept
 | ||||
| 	//    init functions			reject
 | ||||
| 	//    concrete method			accept
 | ||||
| 	//    interface method			accept
 | ||||
| 	// type
 | ||||
| 	//    package-level			accept
 | ||||
| 	//    local				reject
 | ||||
| 	//
 | ||||
| 	// The only accessible package-level objects are members of pkg itself.
 | ||||
| 	//
 | ||||
| 	// The cases are handled in four steps:
 | ||||
| 	//
 | ||||
| 	// 1. reject nil and builtin
 | ||||
| 	// 2. accept package-level objects
 | ||||
| 	// 3. reject obviously invalid objects
 | ||||
| 	// 4. search the API for the path to the param/result/field/method.
 | ||||
| 
 | ||||
| 	// 1. reference to nil or builtin?
 | ||||
| 	if pkg == nil { | ||||
| 		return "", fmt.Errorf("predeclared %s has no path", obj) | ||||
| 	} | ||||
| 	scope := pkg.Scope() | ||||
| 
 | ||||
| 	// 2. package-level object?
 | ||||
| 	if scope.Lookup(obj.Name()) == obj { | ||||
| 		// Only exported objects (and non-exported types) have a path.
 | ||||
| 		// Non-exported types may be referenced by other objects.
 | ||||
| 		if _, ok := obj.(*types.TypeName); !ok && !obj.Exported() { | ||||
| 			return "", fmt.Errorf("no path for non-exported %v", obj) | ||||
| 		} | ||||
| 		return Path(obj.Name()), nil | ||||
| 	} | ||||
| 
 | ||||
| 	// 3. Not a package-level object.
 | ||||
| 	//    Reject obviously non-viable cases.
 | ||||
| 	switch obj := obj.(type) { | ||||
| 	case *types.TypeName: | ||||
| 		if _, ok := obj.Type().(*typeparams.TypeParam); !ok { | ||||
| 			// With the exception of type parameters, only package-level type names
 | ||||
| 			// have a path.
 | ||||
| 			return "", fmt.Errorf("no path for %v", obj) | ||||
| 		} | ||||
| 	case *types.Const, // Only package-level constants have a path.
 | ||||
| 		*types.Label,   // Labels are function-local.
 | ||||
| 		*types.PkgName: // PkgNames are file-local.
 | ||||
| 		return "", fmt.Errorf("no path for %v", obj) | ||||
| 
 | ||||
| 	case *types.Var: | ||||
| 		// Could be:
 | ||||
| 		// - a field (obj.IsField())
 | ||||
| 		// - a func parameter or result
 | ||||
| 		// - a local var.
 | ||||
| 		// Sadly there is no way to distinguish
 | ||||
| 		// a param/result from a local
 | ||||
| 		// so we must proceed to the find.
 | ||||
| 
 | ||||
| 	case *types.Func: | ||||
| 		// A func, if not package-level, must be a method.
 | ||||
| 		if recv := obj.Type().(*types.Signature).Recv(); recv == nil { | ||||
| 			return "", fmt.Errorf("func is not a method: %v", obj) | ||||
| 		} | ||||
| 
 | ||||
| 		if path, ok := enc.concreteMethod(obj); ok { | ||||
| 			// Fast path for concrete methods that avoids looping over scope.
 | ||||
| 			return path, nil | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		panic(obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// 4. Search the API for the path to the var (field/param/result) or method.
 | ||||
| 
 | ||||
| 	// First inspect package-level named types.
 | ||||
| 	// In the presence of path aliases, these give
 | ||||
| 	// the best paths because non-types may
 | ||||
| 	// refer to types, but not the reverse.
 | ||||
| 	empty := make([]byte, 0, 48) // initial space
 | ||||
| 	objs := enc.scopeObjects(scope) | ||||
| 	for _, o := range objs { | ||||
| 		tname, ok := o.(*types.TypeName) | ||||
| 		if !ok { | ||||
| 			continue // handle non-types in second pass
 | ||||
| 		} | ||||
| 
 | ||||
| 		path := append(empty, o.Name()...) | ||||
| 		path = append(path, opType) | ||||
| 
 | ||||
| 		T := o.Type() | ||||
| 
 | ||||
| 		if tname.IsAlias() { | ||||
| 			// type alias
 | ||||
| 			if r := find(obj, T, path, nil); r != nil { | ||||
| 				return Path(r), nil | ||||
| 			} | ||||
| 		} else { | ||||
| 			if named, _ := T.(*types.Named); named != nil { | ||||
| 				if r := findTypeParam(obj, typeparams.ForNamed(named), path, nil); r != nil { | ||||
| 					// generic named type
 | ||||
| 					return Path(r), nil | ||||
| 				} | ||||
| 			} | ||||
| 			// defined (named) type
 | ||||
| 			if r := find(obj, T.Underlying(), append(path, opUnderlying), nil); r != nil { | ||||
| 				return Path(r), nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Then inspect everything else:
 | ||||
| 	// non-types, and declared methods of defined types.
 | ||||
| 	for _, o := range objs { | ||||
| 		path := append(empty, o.Name()...) | ||||
| 		if _, ok := o.(*types.TypeName); !ok { | ||||
| 			if o.Exported() { | ||||
| 				// exported non-type (const, var, func)
 | ||||
| 				if r := find(obj, o.Type(), append(path, opType), nil); r != nil { | ||||
| 					return Path(r), nil | ||||
| 				} | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		// Inspect declared methods of defined types.
 | ||||
| 		if T, ok := o.Type().(*types.Named); ok { | ||||
| 			path = append(path, opType) | ||||
| 			if !enc.skipMethodSorting { | ||||
| 				// Note that method index here is always with respect
 | ||||
| 				// to canonical ordering of methods, regardless of how
 | ||||
| 				// they appear in the underlying type.
 | ||||
| 				for i, m := range enc.namedMethods(T) { | ||||
| 					path2 := appendOpArg(path, opMethod, i) | ||||
| 					if m == obj { | ||||
| 						return Path(path2), nil // found declared method
 | ||||
| 					} | ||||
| 					if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { | ||||
| 						return Path(r), nil | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				// This branch must match the logic in the branch above, using go/types
 | ||||
| 				// APIs without sorting.
 | ||||
| 				for i := 0; i < T.NumMethods(); i++ { | ||||
| 					m := T.Method(i) | ||||
| 					path2 := appendOpArg(path, opMethod, i) | ||||
| 					if m == obj { | ||||
| 						return Path(path2), nil // found declared method
 | ||||
| 					} | ||||
| 					if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { | ||||
| 						return Path(r), nil | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return "", fmt.Errorf("can't find path for %v in %s", obj, pkg.Path()) | ||||
| } | ||||
| 
 | ||||
| func appendOpArg(path []byte, op byte, arg int) []byte { | ||||
| 	path = append(path, op) | ||||
| 	path = strconv.AppendInt(path, int64(arg), 10) | ||||
| 	return path | ||||
| } | ||||
| 
 | ||||
| // concreteMethod returns the path for meth, which must have a non-nil receiver.
 | ||||
| // The second return value indicates success and may be false if the method is
 | ||||
| // an interface method or if it is an instantiated method.
 | ||||
| //
 | ||||
| // This function is just an optimization that avoids the general scope walking
 | ||||
| // approach. You are expected to fall back to the general approach if this
 | ||||
| // function fails.
 | ||||
| func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { | ||||
| 	// Concrete methods can only be declared on package-scoped named types. For
 | ||||
| 	// that reason we can skip the expensive walk over the package scope: the
 | ||||
| 	// path will always be package -> named type -> method. We can trivially get
 | ||||
| 	// the type name from the receiver, and only have to look over the type's
 | ||||
| 	// methods to find the method index.
 | ||||
| 	//
 | ||||
| 	// Methods on generic types require special consideration, however. Consider
 | ||||
| 	// the following package:
 | ||||
| 	//
 | ||||
| 	// 	L1: type S[T any] struct{}
 | ||||
| 	// 	L2: func (recv S[A]) Foo() { recv.Bar() }
 | ||||
| 	// 	L3: func (recv S[B]) Bar() { }
 | ||||
| 	// 	L4: type Alias = S[int]
 | ||||
| 	// 	L5: func _[T any]() { var s S[int]; s.Foo() }
 | ||||
| 	//
 | ||||
| 	// The receivers of methods on generic types are instantiations. L2 and L3
 | ||||
| 	// instantiate S with the type-parameters A and B, which are scoped to the
 | ||||
| 	// respective methods. L4 and L5 each instantiate S with int. Each of these
 | ||||
| 	// instantiations has its own method set, full of methods (and thus objects)
 | ||||
| 	// with receivers whose types are the respective instantiations. In other
 | ||||
| 	// words, we have
 | ||||
| 	//
 | ||||
| 	// S[A].Foo, S[A].Bar
 | ||||
| 	// S[B].Foo, S[B].Bar
 | ||||
| 	// S[int].Foo, S[int].Bar
 | ||||
| 	//
 | ||||
| 	// We may thus be trying to produce object paths for any of these objects.
 | ||||
| 	//
 | ||||
| 	// S[A].Foo and S[B].Bar are the origin methods, and their paths are S.Foo
 | ||||
| 	// and S.Bar, which are the paths that this function naturally produces.
 | ||||
| 	//
 | ||||
| 	// S[A].Bar, S[B].Foo, and both methods on S[int] are instantiations that
 | ||||
| 	// don't correspond to the origin methods. For S[int], this is significant.
 | ||||
| 	// The most precise object path for S[int].Foo, for example, is Alias.Foo,
 | ||||
| 	// not S.Foo. Our function, however, would produce S.Foo, which would
 | ||||
| 	// resolve to a different object.
 | ||||
| 	//
 | ||||
| 	// For S[A].Bar and S[B].Foo it could be argued that S.Bar and S.Foo are
 | ||||
| 	// still the correct paths, since only the origin methods have meaningful
 | ||||
| 	// paths. But this is likely only true for trivial cases and has edge cases.
 | ||||
| 	// Since this function is only an optimization, we err on the side of giving
 | ||||
| 	// up, deferring to the slower but definitely correct algorithm. Most users
 | ||||
| 	// of objectpath will only be giving us origin methods, anyway, as referring
 | ||||
| 	// to instantiated methods is usually not useful.
 | ||||
| 
 | ||||
| 	if typeparams.OriginMethod(meth) != meth { | ||||
| 		return "", false | ||||
| 	} | ||||
| 
 | ||||
| 	recvT := meth.Type().(*types.Signature).Recv().Type() | ||||
| 	if ptr, ok := recvT.(*types.Pointer); ok { | ||||
| 		recvT = ptr.Elem() | ||||
| 	} | ||||
| 
 | ||||
| 	named, ok := recvT.(*types.Named) | ||||
| 	if !ok { | ||||
| 		return "", false | ||||
| 	} | ||||
| 
 | ||||
| 	if types.IsInterface(named) { | ||||
| 		// Named interfaces don't have to be package-scoped
 | ||||
| 		//
 | ||||
| 		// TODO(dominikh): opt: if scope.Lookup(name) == named, then we can apply this optimization to interface
 | ||||
| 		// methods, too, I think.
 | ||||
| 		return "", false | ||||
| 	} | ||||
| 
 | ||||
| 	// Preallocate space for the name, opType, opMethod, and some digits.
 | ||||
| 	name := named.Obj().Name() | ||||
| 	path := make([]byte, 0, len(name)+8) | ||||
| 	path = append(path, name...) | ||||
| 	path = append(path, opType) | ||||
| 
 | ||||
| 	if !enc.skipMethodSorting { | ||||
| 		for i, m := range enc.namedMethods(named) { | ||||
| 			if m == meth { | ||||
| 				path = appendOpArg(path, opMethod, i) | ||||
| 				return Path(path), true | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		// This branch must match the logic of the branch above, using go/types
 | ||||
| 		// APIs without sorting.
 | ||||
| 		for i := 0; i < named.NumMethods(); i++ { | ||||
| 			m := named.Method(i) | ||||
| 			if m == meth { | ||||
| 				path = appendOpArg(path, opMethod, i) | ||||
| 				return Path(path), true | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Due to golang/go#59944, go/types fails to associate the receiver with
 | ||||
| 	// certain methods on cgo types.
 | ||||
| 	//
 | ||||
| 	// TODO(rfindley): replace this panic once golang/go#59944 is fixed in all Go
 | ||||
| 	// versions gopls supports.
 | ||||
| 	return "", false | ||||
| 	// panic(fmt.Sprintf("couldn't find method %s on type %s; methods: %#v", meth, named, enc.namedMethods(named)))
 | ||||
| } | ||||
| 
 | ||||
| // find finds obj within type T, returning the path to it, or nil if not found.
 | ||||
| //
 | ||||
| // The seen map is used to short circuit cycles through type parameters. If
 | ||||
| // nil, it will be allocated as necessary.
 | ||||
| func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { | ||||
| 	switch T := T.(type) { | ||||
| 	case *types.Basic, *types.Named: | ||||
| 		// Named types belonging to pkg were handled already,
 | ||||
| 		// so T must belong to another package. No path.
 | ||||
| 		return nil | ||||
| 	case *types.Pointer: | ||||
| 		return find(obj, T.Elem(), append(path, opElem), seen) | ||||
| 	case *types.Slice: | ||||
| 		return find(obj, T.Elem(), append(path, opElem), seen) | ||||
| 	case *types.Array: | ||||
| 		return find(obj, T.Elem(), append(path, opElem), seen) | ||||
| 	case *types.Chan: | ||||
| 		return find(obj, T.Elem(), append(path, opElem), seen) | ||||
| 	case *types.Map: | ||||
| 		if r := find(obj, T.Key(), append(path, opKey), seen); r != nil { | ||||
| 			return r | ||||
| 		} | ||||
| 		return find(obj, T.Elem(), append(path, opElem), seen) | ||||
| 	case *types.Signature: | ||||
| 		if r := findTypeParam(obj, typeparams.ForSignature(T), path, seen); r != nil { | ||||
| 			return r | ||||
| 		} | ||||
| 		if r := find(obj, T.Params(), append(path, opParams), seen); r != nil { | ||||
| 			return r | ||||
| 		} | ||||
| 		return find(obj, T.Results(), append(path, opResults), seen) | ||||
| 	case *types.Struct: | ||||
| 		for i := 0; i < T.NumFields(); i++ { | ||||
| 			fld := T.Field(i) | ||||
| 			path2 := appendOpArg(path, opField, i) | ||||
| 			if fld == obj { | ||||
| 				return path2 // found field var
 | ||||
| 			} | ||||
| 			if r := find(obj, fld.Type(), append(path2, opType), seen); r != nil { | ||||
| 				return r | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	case *types.Tuple: | ||||
| 		for i := 0; i < T.Len(); i++ { | ||||
| 			v := T.At(i) | ||||
| 			path2 := appendOpArg(path, opAt, i) | ||||
| 			if v == obj { | ||||
| 				return path2 // found param/result var
 | ||||
| 			} | ||||
| 			if r := find(obj, v.Type(), append(path2, opType), seen); r != nil { | ||||
| 				return r | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	case *types.Interface: | ||||
| 		for i := 0; i < T.NumMethods(); i++ { | ||||
| 			m := T.Method(i) | ||||
| 			path2 := appendOpArg(path, opMethod, i) | ||||
| 			if m == obj { | ||||
| 				return path2 // found interface method
 | ||||
| 			} | ||||
| 			if r := find(obj, m.Type(), append(path2, opType), seen); r != nil { | ||||
| 				return r | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	case *typeparams.TypeParam: | ||||
| 		name := T.Obj() | ||||
| 		if name == obj { | ||||
| 			return append(path, opObj) | ||||
| 		} | ||||
| 		if seen[name] { | ||||
| 			return nil | ||||
| 		} | ||||
| 		if seen == nil { | ||||
| 			seen = make(map[*types.TypeName]bool) | ||||
| 		} | ||||
| 		seen[name] = true | ||||
| 		if r := find(obj, T.Constraint(), append(path, opConstraint), seen); r != nil { | ||||
| 			return r | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 	panic(T) | ||||
| } | ||||
| 
 | ||||
| func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte, seen map[*types.TypeName]bool) []byte { | ||||
| 	for i := 0; i < list.Len(); i++ { | ||||
| 		tparam := list.At(i) | ||||
| 		path2 := appendOpArg(path, opTypeParam, i) | ||||
| 		if r := find(obj, tparam, path2, seen); r != nil { | ||||
| 			return r | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Object returns the object denoted by path p within the package pkg.
 | ||||
| func Object(pkg *types.Package, p Path) (types.Object, error) { | ||||
| 	return object(pkg, string(p), false) | ||||
| } | ||||
| 
 | ||||
| // Note: the skipMethodSorting parameter must match the value of
 | ||||
| // Encoder.skipMethodSorting used during encoding.
 | ||||
| func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.Object, error) { | ||||
| 	if pathstr == "" { | ||||
| 		return nil, fmt.Errorf("empty path") | ||||
| 	} | ||||
| 
 | ||||
| 	var pkgobj, suffix string | ||||
| 	if dot := strings.IndexByte(pathstr, opType); dot < 0 { | ||||
| 		pkgobj = pathstr | ||||
| 	} else { | ||||
| 		pkgobj = pathstr[:dot] | ||||
| 		suffix = pathstr[dot:] // suffix starts with "."
 | ||||
| 	} | ||||
| 
 | ||||
| 	obj := pkg.Scope().Lookup(pkgobj) | ||||
| 	if obj == nil { | ||||
| 		return nil, fmt.Errorf("package %s does not contain %q", pkg.Path(), pkgobj) | ||||
| 	} | ||||
| 
 | ||||
| 	// abstraction of *types.{Pointer,Slice,Array,Chan,Map}
 | ||||
| 	type hasElem interface { | ||||
| 		Elem() types.Type | ||||
| 	} | ||||
| 	// abstraction of *types.{Named,Signature}
 | ||||
| 	type hasTypeParams interface { | ||||
| 		TypeParams() *typeparams.TypeParamList | ||||
| 	} | ||||
| 	// abstraction of *types.{Named,TypeParam}
 | ||||
| 	type hasObj interface { | ||||
| 		Obj() *types.TypeName | ||||
| 	} | ||||
| 
 | ||||
| 	// The loop state is the pair (t, obj),
 | ||||
| 	// exactly one of which is non-nil, initially obj.
 | ||||
| 	// All suffixes start with '.' (the only object->type operation),
 | ||||
| 	// followed by optional type->type operations,
 | ||||
| 	// then a type->object operation.
 | ||||
| 	// The cycle then repeats.
 | ||||
| 	var t types.Type | ||||
| 	for suffix != "" { | ||||
| 		code := suffix[0] | ||||
| 		suffix = suffix[1:] | ||||
| 
 | ||||
| 		// Codes [AFM] have an integer operand.
 | ||||
| 		var index int | ||||
| 		switch code { | ||||
| 		case opAt, opField, opMethod, opTypeParam: | ||||
| 			rest := strings.TrimLeft(suffix, "0123456789") | ||||
| 			numerals := suffix[:len(suffix)-len(rest)] | ||||
| 			suffix = rest | ||||
| 			i, err := strconv.Atoi(numerals) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("invalid path: bad numeric operand %q for code %q", numerals, code) | ||||
| 			} | ||||
| 			index = int(i) | ||||
| 		case opObj: | ||||
| 			// no operand
 | ||||
| 		default: | ||||
| 			// The suffix must end with a type->object operation.
 | ||||
| 			if suffix == "" { | ||||
| 				return nil, fmt.Errorf("invalid path: ends with %q, want [AFMO]", code) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if code == opType { | ||||
| 			if t != nil { | ||||
| 				return nil, fmt.Errorf("invalid path: unexpected %q in type context", opType) | ||||
| 			} | ||||
| 			t = obj.Type() | ||||
| 			obj = nil | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		if t == nil { | ||||
| 			return nil, fmt.Errorf("invalid path: code %q in object context", code) | ||||
| 		} | ||||
| 
 | ||||
| 		// Inv: t != nil, obj == nil
 | ||||
| 
 | ||||
| 		switch code { | ||||
| 		case opElem: | ||||
| 			hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map
 | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want pointer, slice, array, chan or map)", code, t, t) | ||||
| 			} | ||||
| 			t = hasElem.Elem() | ||||
| 
 | ||||
| 		case opKey: | ||||
| 			mapType, ok := t.(*types.Map) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want map)", code, t, t) | ||||
| 			} | ||||
| 			t = mapType.Key() | ||||
| 
 | ||||
| 		case opParams: | ||||
| 			sig, ok := t.(*types.Signature) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want signature)", code, t, t) | ||||
| 			} | ||||
| 			t = sig.Params() | ||||
| 
 | ||||
| 		case opResults: | ||||
| 			sig, ok := t.(*types.Signature) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want signature)", code, t, t) | ||||
| 			} | ||||
| 			t = sig.Results() | ||||
| 
 | ||||
| 		case opUnderlying: | ||||
| 			named, ok := t.(*types.Named) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want named)", code, t, t) | ||||
| 			} | ||||
| 			t = named.Underlying() | ||||
| 
 | ||||
| 		case opTypeParam: | ||||
| 			hasTypeParams, ok := t.(hasTypeParams) // Named, Signature
 | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want named or signature)", code, t, t) | ||||
| 			} | ||||
| 			tparams := hasTypeParams.TypeParams() | ||||
| 			if n := tparams.Len(); index >= n { | ||||
| 				return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n) | ||||
| 			} | ||||
| 			t = tparams.At(index) | ||||
| 
 | ||||
| 		case opConstraint: | ||||
| 			tparam, ok := t.(*typeparams.TypeParam) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want type parameter)", code, t, t) | ||||
| 			} | ||||
| 			t = tparam.Constraint() | ||||
| 
 | ||||
| 		case opAt: | ||||
| 			tuple, ok := t.(*types.Tuple) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want tuple)", code, t, t) | ||||
| 			} | ||||
| 			if n := tuple.Len(); index >= n { | ||||
| 				return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n) | ||||
| 			} | ||||
| 			obj = tuple.At(index) | ||||
| 			t = nil | ||||
| 
 | ||||
| 		case opField: | ||||
| 			structType, ok := t.(*types.Struct) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want struct)", code, t, t) | ||||
| 			} | ||||
| 			if n := structType.NumFields(); index >= n { | ||||
| 				return nil, fmt.Errorf("field index %d out of range [0-%d)", index, n) | ||||
| 			} | ||||
| 			obj = structType.Field(index) | ||||
| 			t = nil | ||||
| 
 | ||||
| 		case opMethod: | ||||
| 			switch t := t.(type) { | ||||
| 			case *types.Interface: | ||||
| 				if index >= t.NumMethods() { | ||||
| 					return nil, fmt.Errorf("method index %d out of range [0-%d)", index, t.NumMethods()) | ||||
| 				} | ||||
| 				obj = t.Method(index) // Id-ordered
 | ||||
| 
 | ||||
| 			case *types.Named: | ||||
| 				if index >= t.NumMethods() { | ||||
| 					return nil, fmt.Errorf("method index %d out of range [0-%d)", index, t.NumMethods()) | ||||
| 				} | ||||
| 				if skipMethodSorting { | ||||
| 					obj = t.Method(index) | ||||
| 				} else { | ||||
| 					methods := namedMethods(t) // (unmemoized)
 | ||||
| 					obj = methods[index]       // Id-ordered
 | ||||
| 				} | ||||
| 
 | ||||
| 			default: | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want interface or named)", code, t, t) | ||||
| 			} | ||||
| 			t = nil | ||||
| 
 | ||||
| 		case opObj: | ||||
| 			hasObj, ok := t.(hasObj) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("cannot apply %q to %s (got %T, want named or type param)", code, t, t) | ||||
| 			} | ||||
| 			obj = hasObj.Obj() | ||||
| 			t = nil | ||||
| 
 | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("invalid path: unknown code %q", code) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if obj.Pkg() != pkg { | ||||
| 		return nil, fmt.Errorf("path denotes %s, which belongs to a different package", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	return obj, nil // success
 | ||||
| } | ||||
| 
 | ||||
| // namedMethods returns the methods of a Named type in ascending Id order.
 | ||||
| func namedMethods(named *types.Named) []*types.Func { | ||||
| 	methods := make([]*types.Func, named.NumMethods()) | ||||
| 	for i := range methods { | ||||
| 		methods[i] = named.Method(i) | ||||
| 	} | ||||
| 	sort.Slice(methods, func(i, j int) bool { | ||||
| 		return methods[i].Id() < methods[j].Id() | ||||
| 	}) | ||||
| 	return methods | ||||
| } | ||||
| 
 | ||||
| // namedMethods is a memoization of the namedMethods function. Callers must not modify the result.
 | ||||
| func (enc *Encoder) namedMethods(named *types.Named) []*types.Func { | ||||
| 	m := enc.namedMethodsMemo | ||||
| 	if m == nil { | ||||
| 		m = make(map[*types.Named][]*types.Func) | ||||
| 		enc.namedMethodsMemo = m | ||||
| 	} | ||||
| 	methods, ok := m[named] | ||||
| 	if !ok { | ||||
| 		methods = namedMethods(named) // allocates and sorts
 | ||||
| 		m[named] = methods | ||||
| 	} | ||||
| 	return methods | ||||
| } | ||||
| 
 | ||||
| // scopeObjects is a memoization of scope objects.
 | ||||
| // Callers must not modify the result.
 | ||||
| func (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object { | ||||
| 	m := enc.scopeMemo | ||||
| 	if m == nil { | ||||
| 		m = make(map[*types.Scope][]types.Object) | ||||
| 		enc.scopeMemo = m | ||||
| 	} | ||||
| 	objs, ok := m[scope] | ||||
| 	if !ok { | ||||
| 		names := scope.Names() // allocates and sorts
 | ||||
| 		objs = make([]types.Object, len(names)) | ||||
| 		for i, name := range names { | ||||
| 			objs[i] = scope.Lookup(name) | ||||
| 		} | ||||
| 		m[scope] = objs | ||||
| 	} | ||||
| 	return objs | ||||
| } | ||||
|  | @ -19,7 +19,7 @@ var ( | |||
| 	File          = keys.NewString("file", "") | ||||
| 	Directory     = keys.New("directory", "") | ||||
| 	URI           = keys.New("URI", "") | ||||
| 	Package       = keys.NewString("package", "") // Package ID
 | ||||
| 	Package       = keys.NewString("package", "") // sorted comma-separated list of Package IDs
 | ||||
| 	PackagePath   = keys.NewString("package_path", "") | ||||
| 	Query         = keys.New("query", "") | ||||
| 	Snapshot      = keys.NewUInt64("snapshot", "") | ||||
|  |  | |||
|  | @ -29,7 +29,6 @@ import ( | |||
| 	"go/token" | ||||
| 	"go/types" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
|  | @ -221,7 +220,7 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func | |||
| 	switch hdr { | ||||
| 	case "$$B\n": | ||||
| 		var data []byte | ||||
| 		data, err = ioutil.ReadAll(buf) | ||||
| 		data, err = io.ReadAll(buf) | ||||
| 		if err != nil { | ||||
| 			break | ||||
| 		} | ||||
|  |  | |||
|  | @ -22,17 +22,23 @@ import ( | |||
| 	"strconv" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"golang.org/x/tools/go/types/objectpath" | ||||
| 	"golang.org/x/tools/internal/tokeninternal" | ||||
| 	"golang.org/x/tools/internal/typeparams" | ||||
| ) | ||||
| 
 | ||||
| // IExportShallow encodes "shallow" export data for the specified package.
 | ||||
| //
 | ||||
| // No promises are made about the encoding other than that it can be
 | ||||
| // decoded by the same version of IIExportShallow. If you plan to save
 | ||||
| // export data in the file system, be sure to include a cryptographic
 | ||||
| // digest of the executable in the key to avoid version skew.
 | ||||
| func IExportShallow(fset *token.FileSet, pkg *types.Package) ([]byte, error) { | ||||
| // No promises are made about the encoding other than that it can be decoded by
 | ||||
| // the same version of IIExportShallow. If you plan to save export data in the
 | ||||
| // file system, be sure to include a cryptographic digest of the executable in
 | ||||
| // the key to avoid version skew.
 | ||||
| //
 | ||||
| // If the provided reportf func is non-nil, it will be used for reporting bugs
 | ||||
| // encountered during export.
 | ||||
| // TODO(rfindley): remove reportf when we are confident enough in the new
 | ||||
| // objectpath encoding.
 | ||||
| func IExportShallow(fset *token.FileSet, pkg *types.Package, reportf ReportFunc) ([]byte, error) { | ||||
| 	// In principle this operation can only fail if out.Write fails,
 | ||||
| 	// but that's impossible for bytes.Buffer---and as a matter of
 | ||||
| 	// fact iexportCommon doesn't even check for I/O errors.
 | ||||
|  | @ -47,19 +53,27 @@ func IExportShallow(fset *token.FileSet, pkg *types.Package) ([]byte, error) { | |||
| // IImportShallow decodes "shallow" types.Package data encoded by
 | ||||
| // IExportShallow in the same executable. This function cannot import data from
 | ||||
| // cmd/compile or gcexportdata.Write.
 | ||||
| func IImportShallow(fset *token.FileSet, getPackage GetPackageFunc, data []byte, path string, insert InsertType) (*types.Package, error) { | ||||
| //
 | ||||
| // The importer calls getPackages to obtain package symbols for all
 | ||||
| // packages mentioned in the export data, including the one being
 | ||||
| // decoded.
 | ||||
| //
 | ||||
| // If the provided reportf func is non-nil, it will be used for reporting bugs
 | ||||
| // encountered during import.
 | ||||
| // TODO(rfindley): remove reportf when we are confident enough in the new
 | ||||
| // objectpath encoding.
 | ||||
| func IImportShallow(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, path string, reportf ReportFunc) (*types.Package, error) { | ||||
| 	const bundle = false | ||||
| 	pkgs, err := iimportCommon(fset, getPackage, data, bundle, path, insert) | ||||
| 	const shallow = true | ||||
| 	pkgs, err := iimportCommon(fset, getPackages, data, bundle, path, shallow, reportf) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return pkgs[0], nil | ||||
| } | ||||
| 
 | ||||
| // InsertType is the type of a function that creates a types.TypeName
 | ||||
| // object for a named type and inserts it into the scope of the
 | ||||
| // specified Package.
 | ||||
| type InsertType = func(pkg *types.Package, name string) | ||||
| // ReportFunc is the type of a function used to report formatted bugs.
 | ||||
| type ReportFunc = func(string, ...interface{}) | ||||
| 
 | ||||
| // Current bundled export format version. Increase with each format change.
 | ||||
| // 0: initial implementation
 | ||||
|  | @ -313,8 +327,9 @@ type iexporter struct { | |||
| 	out     *bytes.Buffer | ||||
| 	version int | ||||
| 
 | ||||
| 	shallow  bool           // don't put types from other packages in the index
 | ||||
| 	localpkg *types.Package // (nil in bundle mode)
 | ||||
| 	shallow    bool                // don't put types from other packages in the index
 | ||||
| 	objEncoder *objectpath.Encoder // encodes objects from other packages in shallow mode; lazily allocated
 | ||||
| 	localpkg   *types.Package      // (nil in bundle mode)
 | ||||
| 
 | ||||
| 	// allPkgs tracks all packages that have been referenced by
 | ||||
| 	// the export data, so we can ensure to include them in the
 | ||||
|  | @ -354,6 +369,17 @@ func (p *iexporter) trace(format string, args ...interface{}) { | |||
| 	fmt.Printf(strings.Repeat("..", p.indent)+format+"\n", args...) | ||||
| } | ||||
| 
 | ||||
| // objectpathEncoder returns the lazily allocated objectpath.Encoder to use
 | ||||
| // when encoding objects in other packages during shallow export.
 | ||||
| //
 | ||||
| // Using a shared Encoder amortizes some of cost of objectpath search.
 | ||||
| func (p *iexporter) objectpathEncoder() *objectpath.Encoder { | ||||
| 	if p.objEncoder == nil { | ||||
| 		p.objEncoder = new(objectpath.Encoder) | ||||
| 	} | ||||
| 	return p.objEncoder | ||||
| } | ||||
| 
 | ||||
| // stringOff returns the offset of s within the string section.
 | ||||
| // If not already present, it's added to the end.
 | ||||
| func (p *iexporter) stringOff(s string) uint64 { | ||||
|  | @ -413,7 +439,6 @@ type exportWriter struct { | |||
| 	p *iexporter | ||||
| 
 | ||||
| 	data       intWriter | ||||
| 	currPkg    *types.Package | ||||
| 	prevFile   string | ||||
| 	prevLine   int64 | ||||
| 	prevColumn int64 | ||||
|  | @ -436,7 +461,6 @@ func (p *iexporter) doDecl(obj types.Object) { | |||
| 		}() | ||||
| 	} | ||||
| 	w := p.newWriter() | ||||
| 	w.setPkg(obj.Pkg(), false) | ||||
| 
 | ||||
| 	switch obj := obj.(type) { | ||||
| 	case *types.Var: | ||||
|  | @ -673,6 +697,9 @@ func (w *exportWriter) qualifiedType(obj *types.TypeName) { | |||
| 	w.pkg(obj.Pkg()) | ||||
| } | ||||
| 
 | ||||
| // TODO(rfindley): what does 'pkg' even mean here? It would be better to pass
 | ||||
| // it in explicitly into signatures and structs that may use it for
 | ||||
| // constructing fields.
 | ||||
| func (w *exportWriter) typ(t types.Type, pkg *types.Package) { | ||||
| 	w.data.uint64(w.p.typOff(t, pkg)) | ||||
| } | ||||
|  | @ -764,30 +791,53 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { | |||
| 
 | ||||
| 	case *types.Signature: | ||||
| 		w.startType(signatureType) | ||||
| 		w.setPkg(pkg, true) | ||||
| 		w.pkg(pkg) | ||||
| 		w.signature(t) | ||||
| 
 | ||||
| 	case *types.Struct: | ||||
| 		w.startType(structType) | ||||
| 		n := t.NumFields() | ||||
| 		// Even for struct{} we must emit some qualifying package, because that's
 | ||||
| 		// what the compiler does, and thus that's what the importer expects.
 | ||||
| 		fieldPkg := pkg | ||||
| 		if n > 0 { | ||||
| 			w.setPkg(t.Field(0).Pkg(), true) // qualifying package for field objects
 | ||||
| 		} else { | ||||
| 			w.setPkg(pkg, true) | ||||
| 			fieldPkg = t.Field(0).Pkg() | ||||
| 		} | ||||
| 		if fieldPkg == nil { | ||||
| 			// TODO(rfindley): improve this very hacky logic.
 | ||||
| 			//
 | ||||
| 			// The importer expects a package to be set for all struct types, even
 | ||||
| 			// those with no fields. A better encoding might be to set NumFields
 | ||||
| 			// before pkg. setPkg panics with a nil package, which may be possible
 | ||||
| 			// to reach with invalid packages (and perhaps valid packages, too?), so
 | ||||
| 			// (arbitrarily) set the localpkg if available.
 | ||||
| 			//
 | ||||
| 			// Alternatively, we may be able to simply guarantee that pkg != nil, by
 | ||||
| 			// reconsidering the encoding of constant values.
 | ||||
| 			if w.p.shallow { | ||||
| 				fieldPkg = w.p.localpkg | ||||
| 			} else { | ||||
| 				panic(internalErrorf("no package to set for empty struct")) | ||||
| 			} | ||||
| 		} | ||||
| 		w.pkg(fieldPkg) | ||||
| 		w.uint64(uint64(n)) | ||||
| 
 | ||||
| 		for i := 0; i < n; i++ { | ||||
| 			f := t.Field(i) | ||||
| 			if w.p.shallow { | ||||
| 				w.objectPath(f) | ||||
| 			} | ||||
| 			w.pos(f.Pos()) | ||||
| 			w.string(f.Name()) // unexported fields implicitly qualified by prior setPkg
 | ||||
| 			w.typ(f.Type(), pkg) | ||||
| 			w.typ(f.Type(), fieldPkg) | ||||
| 			w.bool(f.Anonymous()) | ||||
| 			w.string(t.Tag(i)) // note (or tag)
 | ||||
| 		} | ||||
| 
 | ||||
| 	case *types.Interface: | ||||
| 		w.startType(interfaceType) | ||||
| 		w.setPkg(pkg, true) | ||||
| 		w.pkg(pkg) | ||||
| 
 | ||||
| 		n := t.NumEmbeddeds() | ||||
| 		w.uint64(uint64(n)) | ||||
|  | @ -802,10 +852,16 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { | |||
| 			w.typ(ft, tPkg) | ||||
| 		} | ||||
| 
 | ||||
| 		// See comment for struct fields. In shallow mode we change the encoding
 | ||||
| 		// for interface methods that are promoted from other packages.
 | ||||
| 
 | ||||
| 		n = t.NumExplicitMethods() | ||||
| 		w.uint64(uint64(n)) | ||||
| 		for i := 0; i < n; i++ { | ||||
| 			m := t.ExplicitMethod(i) | ||||
| 			if w.p.shallow { | ||||
| 				w.objectPath(m) | ||||
| 			} | ||||
| 			w.pos(m.Pos()) | ||||
| 			w.string(m.Name()) | ||||
| 			sig, _ := m.Type().(*types.Signature) | ||||
|  | @ -827,12 +883,61 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (w *exportWriter) setPkg(pkg *types.Package, write bool) { | ||||
| 	if write { | ||||
| 		w.pkg(pkg) | ||||
| // objectPath writes the package and objectPath to use to look up obj in a
 | ||||
| // different package, when encoding in "shallow" mode.
 | ||||
| //
 | ||||
| // When doing a shallow import, the importer creates only the local package,
 | ||||
| // and requests package symbols for dependencies from the client.
 | ||||
| // However, certain types defined in the local package may hold objects defined
 | ||||
| // (perhaps deeply) within another package.
 | ||||
| //
 | ||||
| // For example, consider the following:
 | ||||
| //
 | ||||
| //	package a
 | ||||
| //	func F() chan * map[string] struct { X int }
 | ||||
| //
 | ||||
| //	package b
 | ||||
| //	import "a"
 | ||||
| //	var B = a.F()
 | ||||
| //
 | ||||
| // In this example, the type of b.B holds fields defined in package a.
 | ||||
| // In order to have the correct canonical objects for the field defined in the
 | ||||
| // type of B, they are encoded as objectPaths and later looked up in the
 | ||||
| // importer. The same problem applies to interface methods.
 | ||||
| func (w *exportWriter) objectPath(obj types.Object) { | ||||
| 	if obj.Pkg() == nil || obj.Pkg() == w.p.localpkg { | ||||
| 		// obj.Pkg() may be nil for the builtin error.Error.
 | ||||
| 		// In this case, or if obj is declared in the local package, no need to
 | ||||
| 		// encode.
 | ||||
| 		w.string("") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	w.currPkg = pkg | ||||
| 	objectPath, err := w.p.objectpathEncoder().For(obj) | ||||
| 	if err != nil { | ||||
| 		// Fall back to the empty string, which will cause the importer to create a
 | ||||
| 		// new object, which matches earlier behavior. Creating a new object is
 | ||||
| 		// sufficient for many purposes (such as type checking), but causes certain
 | ||||
| 		// references algorithms to fail (golang/go#60819). However, we didn't
 | ||||
| 		// notice this problem during months of gopls@v0.12.0 testing.
 | ||||
| 		//
 | ||||
| 		// TODO(golang/go#61674): this workaround is insufficient, as in the case
 | ||||
| 		// where the field forwarded from an instantiated type that may not appear
 | ||||
| 		// in the export data of the original package:
 | ||||
| 		//
 | ||||
| 		//  // package a
 | ||||
| 		//  type A[P any] struct{ F P }
 | ||||
| 		//
 | ||||
| 		//  // package b
 | ||||
| 		//  type B a.A[int]
 | ||||
| 		//
 | ||||
| 		// We need to update references algorithms not to depend on this
 | ||||
| 		// de-duplication, at which point we may want to simply remove the
 | ||||
| 		// workaround here.
 | ||||
| 		w.string("") | ||||
| 		return | ||||
| 	} | ||||
| 	w.string(string(objectPath)) | ||||
| 	w.pkg(obj.Pkg()) | ||||
| } | ||||
| 
 | ||||
| func (w *exportWriter) signature(sig *types.Signature) { | ||||
|  | @ -1205,6 +1310,13 @@ type internalError string | |||
| 
 | ||||
| func (e internalError) Error() string { return "gcimporter: " + string(e) } | ||||
| 
 | ||||
| // TODO(adonovan): make this call panic, so that it's symmetric with errorf.
 | ||||
| // Otherwise it's easy to forget to do anything with the error.
 | ||||
| //
 | ||||
| // TODO(adonovan): also, consider switching the names "errorf" and
 | ||||
| // "internalErrorf" as the former is used for bugs, whose cause is
 | ||||
| // internal inconsistency, whereas the latter is used for ordinary
 | ||||
| // situations like bad input, whose cause is external.
 | ||||
| func internalErrorf(format string, args ...interface{}) error { | ||||
| 	return internalError(fmt.Sprintf(format, args...)) | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import ( | |||
| 	"sort" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"golang.org/x/tools/go/types/objectpath" | ||||
| 	"golang.org/x/tools/internal/typeparams" | ||||
| ) | ||||
| 
 | ||||
|  | @ -85,7 +86,7 @@ const ( | |||
| // If the export data version is not recognized or the format is otherwise
 | ||||
| // compromised, an error is returned.
 | ||||
| func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) { | ||||
| 	pkgs, err := iimportCommon(fset, GetPackageFromMap(imports), data, false, path, nil) | ||||
| 	pkgs, err := iimportCommon(fset, GetPackagesFromMap(imports), data, false, path, false, nil) | ||||
| 	if err != nil { | ||||
| 		return 0, nil, err | ||||
| 	} | ||||
|  | @ -94,33 +95,49 @@ func IImportData(fset *token.FileSet, imports map[string]*types.Package, data [] | |||
| 
 | ||||
| // IImportBundle imports a set of packages from the serialized package bundle.
 | ||||
| func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) { | ||||
| 	return iimportCommon(fset, GetPackageFromMap(imports), data, true, "", nil) | ||||
| 	return iimportCommon(fset, GetPackagesFromMap(imports), data, true, "", false, nil) | ||||
| } | ||||
| 
 | ||||
| // A GetPackageFunc is a function that gets the package with the given path
 | ||||
| // from the importer state, creating it (with the specified name) if necessary.
 | ||||
| // It is an abstraction of the map historically used to memoize package creation.
 | ||||
| // A GetPackagesFunc function obtains the non-nil symbols for a set of
 | ||||
| // packages, creating and recursively importing them as needed. An
 | ||||
| // implementation should store each package symbol is in the Pkg
 | ||||
| // field of the items array.
 | ||||
| //
 | ||||
| // Two calls with the same path must return the same package.
 | ||||
| //
 | ||||
| // If the given getPackage func returns nil, the import will fail.
 | ||||
| type GetPackageFunc = func(path, name string) *types.Package | ||||
| // Any error causes importing to fail. This can be used to quickly read
 | ||||
| // the import manifest of an export data file without fully decoding it.
 | ||||
| type GetPackagesFunc = func(items []GetPackagesItem) error | ||||
| 
 | ||||
| // GetPackageFromMap returns a GetPackageFunc that retrieves packages from the
 | ||||
| // given map of package path -> package.
 | ||||
| // A GetPackagesItem is a request from the importer for the package
 | ||||
| // symbol of the specified name and path.
 | ||||
| type GetPackagesItem struct { | ||||
| 	Name, Path string | ||||
| 	Pkg        *types.Package // to be filled in by GetPackagesFunc call
 | ||||
| 
 | ||||
| 	// private importer state
 | ||||
| 	pathOffset uint64 | ||||
| 	nameIndex  map[string]uint64 | ||||
| } | ||||
| 
 | ||||
| // GetPackagesFromMap returns a GetPackagesFunc that retrieves
 | ||||
| // packages from the given map of package path to package.
 | ||||
| //
 | ||||
| // The resulting func may mutate m: if a requested package is not found, a new
 | ||||
| // package will be inserted into m.
 | ||||
| func GetPackageFromMap(m map[string]*types.Package) GetPackageFunc { | ||||
| 	return func(path, name string) *types.Package { | ||||
| 		if _, ok := m[path]; !ok { | ||||
| 			m[path] = types.NewPackage(path, name) | ||||
| // The returned function may mutate m: each requested package that is not
 | ||||
| // found is created with types.NewPackage and inserted into m.
 | ||||
| func GetPackagesFromMap(m map[string]*types.Package) GetPackagesFunc { | ||||
| 	return func(items []GetPackagesItem) error { | ||||
| 		for i, item := range items { | ||||
| 			pkg, ok := m[item.Path] | ||||
| 			if !ok { | ||||
| 				pkg = types.NewPackage(item.Path, item.Name) | ||||
| 				m[item.Path] = pkg | ||||
| 			} | ||||
| 			items[i].Pkg = pkg | ||||
| 		} | ||||
| 		return m[path] | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) { | ||||
| func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte, bundle bool, path string, shallow bool, reportf ReportFunc) (pkgs []*types.Package, err error) { | ||||
| 	const currentVersion = iexportVersionCurrent | ||||
| 	version := int64(-1) | ||||
| 	if !debug { | ||||
|  | @ -159,7 +176,7 @@ func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, | |||
| 	sLen := int64(r.uint64()) | ||||
| 	var fLen int64 | ||||
| 	var fileOffset []uint64 | ||||
| 	if insert != nil { | ||||
| 	if shallow { | ||||
| 		// Shallow mode uses a different position encoding.
 | ||||
| 		fLen = int64(r.uint64()) | ||||
| 		fileOffset = make([]uint64, r.uint64()) | ||||
|  | @ -178,7 +195,8 @@ func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, | |||
| 	p := iimporter{ | ||||
| 		version: int(version), | ||||
| 		ipath:   path, | ||||
| 		insert:  insert, | ||||
| 		shallow: shallow, | ||||
| 		reportf: reportf, | ||||
| 
 | ||||
| 		stringData:  stringData, | ||||
| 		stringCache: make(map[uint64]string), | ||||
|  | @ -205,8 +223,9 @@ func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, | |||
| 		p.typCache[uint64(i)] = pt | ||||
| 	} | ||||
| 
 | ||||
| 	pkgList := make([]*types.Package, r.uint64()) | ||||
| 	for i := range pkgList { | ||||
| 	// Gather the relevant packages from the manifest.
 | ||||
| 	items := make([]GetPackagesItem, r.uint64()) | ||||
| 	for i := range items { | ||||
| 		pkgPathOff := r.uint64() | ||||
| 		pkgPath := p.stringAt(pkgPathOff) | ||||
| 		pkgName := p.stringAt(r.uint64()) | ||||
|  | @ -215,29 +234,42 @@ func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, | |||
| 		if pkgPath == "" { | ||||
| 			pkgPath = path | ||||
| 		} | ||||
| 		pkg := getPackage(pkgPath, pkgName) | ||||
| 		if pkg == nil { | ||||
| 			errorf("internal error: getPackage returned nil package for %s", pkgPath) | ||||
| 		} else if pkg.Name() != pkgName { | ||||
| 			errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) | ||||
| 		} | ||||
| 		if i == 0 && !bundle { | ||||
| 			p.localpkg = pkg | ||||
| 		} | ||||
| 
 | ||||
| 		p.pkgCache[pkgPathOff] = pkg | ||||
| 		items[i].Name = pkgName | ||||
| 		items[i].Path = pkgPath | ||||
| 		items[i].pathOffset = pkgPathOff | ||||
| 
 | ||||
| 		// Read index for package.
 | ||||
| 		nameIndex := make(map[string]uint64) | ||||
| 		nSyms := r.uint64() | ||||
| 		// In shallow mode we don't expect an index for other packages.
 | ||||
| 		assert(nSyms == 0 || p.localpkg == pkg || p.insert == nil) | ||||
| 		// In shallow mode, only the current package (i=0) has an index.
 | ||||
| 		assert(!(shallow && i > 0 && nSyms != 0)) | ||||
| 		for ; nSyms > 0; nSyms-- { | ||||
| 			name := p.stringAt(r.uint64()) | ||||
| 			nameIndex[name] = r.uint64() | ||||
| 		} | ||||
| 
 | ||||
| 		p.pkgIndex[pkg] = nameIndex | ||||
| 		items[i].nameIndex = nameIndex | ||||
| 	} | ||||
| 
 | ||||
| 	// Request packages all at once from the client,
 | ||||
| 	// enabling a parallel implementation.
 | ||||
| 	if err := getPackages(items); err != nil { | ||||
| 		return nil, err // don't wrap this error
 | ||||
| 	} | ||||
| 
 | ||||
| 	// Check the results and complete the index.
 | ||||
| 	pkgList := make([]*types.Package, len(items)) | ||||
| 	for i, item := range items { | ||||
| 		pkg := item.Pkg | ||||
| 		if pkg == nil { | ||||
| 			errorf("internal error: getPackages returned nil package for %q", item.Path) | ||||
| 		} else if pkg.Path() != item.Path { | ||||
| 			errorf("internal error: getPackages returned wrong path %q, want %q", pkg.Path(), item.Path) | ||||
| 		} else if pkg.Name() != item.Name { | ||||
| 			errorf("internal error: getPackages returned wrong name %s for package %q, want %s", pkg.Name(), item.Path, item.Name) | ||||
| 		} | ||||
| 		p.pkgCache[item.pathOffset] = pkg | ||||
| 		p.pkgIndex[pkg] = item.nameIndex | ||||
| 		pkgList[i] = pkg | ||||
| 	} | ||||
| 
 | ||||
|  | @ -296,6 +328,13 @@ func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, | |||
| 		typ.Complete() | ||||
| 	} | ||||
| 
 | ||||
| 	// Workaround for golang/go#61561. See the doc for instanceList for details.
 | ||||
| 	for _, typ := range p.instanceList { | ||||
| 		if iface, _ := typ.Underlying().(*types.Interface); iface != nil { | ||||
| 			iface.Complete() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return pkgs, nil | ||||
| } | ||||
| 
 | ||||
|  | @ -308,8 +347,8 @@ type iimporter struct { | |||
| 	version int | ||||
| 	ipath   string | ||||
| 
 | ||||
| 	localpkg *types.Package | ||||
| 	insert   func(pkg *types.Package, name string) // "shallow" mode only
 | ||||
| 	shallow bool | ||||
| 	reportf ReportFunc // if non-nil, used to report bugs
 | ||||
| 
 | ||||
| 	stringData  []byte | ||||
| 	stringCache map[uint64]string | ||||
|  | @ -326,6 +365,12 @@ type iimporter struct { | |||
| 	fake          fakeFileSet | ||||
| 	interfaceList []*types.Interface | ||||
| 
 | ||||
| 	// Workaround for the go/types bug golang/go#61561: instances produced during
 | ||||
| 	// instantiation may contain incomplete interfaces. Here we only complete the
 | ||||
| 	// underlying type of the instance, which is the most common case but doesn't
 | ||||
| 	// handle parameterized interface literals defined deeper in the type.
 | ||||
| 	instanceList []types.Type // instances for later completion (see golang/go#61561)
 | ||||
| 
 | ||||
| 	// Arguments for calls to SetConstraint that are deferred due to recursive types
 | ||||
| 	later []setConstraintArgs | ||||
| 
 | ||||
|  | @ -357,13 +402,9 @@ func (p *iimporter) doDecl(pkg *types.Package, name string) { | |||
| 
 | ||||
| 	off, ok := p.pkgIndex[pkg][name] | ||||
| 	if !ok { | ||||
| 		// In "shallow" mode, call back to the application to
 | ||||
| 		// find the object and insert it into the package scope.
 | ||||
| 		if p.insert != nil { | ||||
| 			assert(pkg != p.localpkg) | ||||
| 			p.insert(pkg, name) // "can't fail"
 | ||||
| 			return | ||||
| 		} | ||||
| 		// In deep mode, the index should be complete. In shallow
 | ||||
| 		// mode, we should have already recursively loaded necessary
 | ||||
| 		// dependencies so the above Lookup succeeds.
 | ||||
| 		errorf("%v.%v not in index", pkg, name) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -730,7 +771,8 @@ func (r *importReader) qualifiedIdent() (*types.Package, string) { | |||
| } | ||||
| 
 | ||||
| func (r *importReader) pos() token.Pos { | ||||
| 	if r.p.insert != nil { // shallow mode
 | ||||
| 	if r.p.shallow { | ||||
| 		// precise offsets are encoded only in shallow mode
 | ||||
| 		return r.posv2() | ||||
| 	} | ||||
| 	if r.p.version >= iexportVersionPosCol { | ||||
|  | @ -831,13 +873,28 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { | |||
| 		fields := make([]*types.Var, r.uint64()) | ||||
| 		tags := make([]string, len(fields)) | ||||
| 		for i := range fields { | ||||
| 			var field *types.Var | ||||
| 			if r.p.shallow { | ||||
| 				field, _ = r.objectPathObject().(*types.Var) | ||||
| 			} | ||||
| 
 | ||||
| 			fpos := r.pos() | ||||
| 			fname := r.ident() | ||||
| 			ftyp := r.typ() | ||||
| 			emb := r.bool() | ||||
| 			tag := r.string() | ||||
| 
 | ||||
| 			fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb) | ||||
| 			// Either this is not a shallow import, the field is local, or the
 | ||||
| 			// encoded objectPath failed to produce an object (a bug).
 | ||||
| 			//
 | ||||
| 			// Even in this last, buggy case, fall back on creating a new field. As
 | ||||
| 			// discussed in iexport.go, this is not correct, but mostly works and is
 | ||||
| 			// preferable to failing (for now at least).
 | ||||
| 			if field == nil { | ||||
| 				field = types.NewField(fpos, r.currPkg, fname, ftyp, emb) | ||||
| 			} | ||||
| 
 | ||||
| 			fields[i] = field | ||||
| 			tags[i] = tag | ||||
| 		} | ||||
| 		return types.NewStruct(fields, tags) | ||||
|  | @ -853,6 +910,11 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { | |||
| 
 | ||||
| 		methods := make([]*types.Func, r.uint64()) | ||||
| 		for i := range methods { | ||||
| 			var method *types.Func | ||||
| 			if r.p.shallow { | ||||
| 				method, _ = r.objectPathObject().(*types.Func) | ||||
| 			} | ||||
| 
 | ||||
| 			mpos := r.pos() | ||||
| 			mname := r.ident() | ||||
| 
 | ||||
|  | @ -862,9 +924,12 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { | |||
| 			if base != nil { | ||||
| 				recv = types.NewVar(token.NoPos, r.currPkg, "", base) | ||||
| 			} | ||||
| 
 | ||||
| 			msig := r.signature(recv, nil, nil) | ||||
| 			methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) | ||||
| 
 | ||||
| 			if method == nil { | ||||
| 				method = types.NewFunc(mpos, r.currPkg, mname, msig) | ||||
| 			} | ||||
| 			methods[i] = method | ||||
| 		} | ||||
| 
 | ||||
| 		typ := newInterface(methods, embeddeds) | ||||
|  | @ -902,6 +967,9 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { | |||
| 		// we must always use the methods of the base (orig) type.
 | ||||
| 		// TODO provide a non-nil *Environment
 | ||||
| 		t, _ := typeparams.Instantiate(nil, baseType, targs, false) | ||||
| 
 | ||||
| 		// Workaround for golang/go#61561. See the doc for instanceList for details.
 | ||||
| 		r.p.instanceList = append(r.p.instanceList, t) | ||||
| 		return t | ||||
| 
 | ||||
| 	case unionType: | ||||
|  | @ -920,6 +988,26 @@ func (r *importReader) kind() itag { | |||
| 	return itag(r.uint64()) | ||||
| } | ||||
| 
 | ||||
| // objectPathObject is the inverse of exportWriter.objectPath.
 | ||||
| //
 | ||||
| // In shallow mode, certain fields and methods may need to be looked up in an
 | ||||
| // imported package. See the doc for exportWriter.objectPath for a full
 | ||||
| // explanation.
 | ||||
| func (r *importReader) objectPathObject() types.Object { | ||||
| 	objPath := objectpath.Path(r.string()) | ||||
| 	if objPath == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| 	pkg := r.pkg() | ||||
| 	obj, err := objectpath.Object(pkg, objPath) | ||||
| 	if err != nil { | ||||
| 		if r.p.reportf != nil { | ||||
| 			r.p.reportf("failed to find object for objectPath %q: %v", objPath, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return obj | ||||
| } | ||||
| 
 | ||||
| func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature { | ||||
| 	params := r.paramList() | ||||
| 	results := r.paramList() | ||||
|  |  | |||
|  | @ -319,7 +319,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { | |||
| 					// Per https://pkg.go.dev/os#File.Close, the call to stdoutR.Close
 | ||||
| 					// should cause the Read call in io.Copy to unblock and return
 | ||||
| 					// immediately, but we still need to receive from stdoutErr to confirm
 | ||||
| 					// that that has happened.
 | ||||
| 					// that it has happened.
 | ||||
| 					<-stdoutErr | ||||
| 					err2 = ctx.Err() | ||||
| 				} | ||||
|  | @ -333,7 +333,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { | |||
| 			// one goroutine at a time will call Write.”
 | ||||
| 			//
 | ||||
| 			// Since we're starting a goroutine that writes to cmd.Stdout, we must
 | ||||
| 			// also update cmd.Stderr so that that still holds.
 | ||||
| 			// also update cmd.Stderr so that it still holds.
 | ||||
| 			func() { | ||||
| 				defer func() { recover() }() | ||||
| 				if cmd.Stderr == prevStdout { | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| package typeparams | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"go/ast" | ||||
| 	"go/token" | ||||
| 	"go/types" | ||||
|  | @ -125,6 +126,11 @@ func OriginMethod(fn *types.Func) *types.Func { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// In golang/go#61196, we observe another crash, this time inexplicable.
 | ||||
| 	if gfn == nil { | ||||
| 		panic(fmt.Sprintf("missing origin method for %s.%s; named == origin: %t, named.NumMethods(): %d, origin.NumMethods(): %d", named, fn, named == orig, named.NumMethods(), orig.NumMethods())) | ||||
| 	} | ||||
| 
 | ||||
| 	return gfn.(*types.Func) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -81,13 +81,13 @@ func CoreType(T types.Type) types.Type { | |||
| // restrictions may be arbitrarily complex. For example, consider the
 | ||||
| // following:
 | ||||
| //
 | ||||
| //  type A interface{ ~string|~[]byte }
 | ||||
| //	type A interface{ ~string|~[]byte }
 | ||||
| //
 | ||||
| //  type B interface{ int|string }
 | ||||
| //	type B interface{ int|string }
 | ||||
| //
 | ||||
| //  type C interface { ~string|~int }
 | ||||
| //	type C interface { ~string|~int }
 | ||||
| //
 | ||||
| //  type T[P interface{ A|B; C }] int
 | ||||
| //	type T[P interface{ A|B; C }] int
 | ||||
| //
 | ||||
| // In this example, the structural type restriction of P is ~string|int: A|B
 | ||||
| // expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ func (xl termlist) String() string { | |||
| 	var buf bytes.Buffer | ||||
| 	for i, x := range xl { | ||||
| 		if i > 0 { | ||||
| 			buf.WriteString(" ∪ ") | ||||
| 			buf.WriteString(" | ") | ||||
| 		} | ||||
| 		buf.WriteString(x.String()) | ||||
| 	} | ||||
|  |  | |||
|  | @ -129,7 +129,7 @@ func NamedTypeArgs(*types.Named) *TypeList { | |||
| } | ||||
| 
 | ||||
| // NamedTypeOrigin is the identity method at this Go version.
 | ||||
| func NamedTypeOrigin(named *types.Named) types.Type { | ||||
| func NamedTypeOrigin(named *types.Named) *types.Named { | ||||
| 	return named | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -103,7 +103,7 @@ func NamedTypeArgs(named *types.Named) *TypeList { | |||
| } | ||||
| 
 | ||||
| // NamedTypeOrigin returns named.Orig().
 | ||||
| func NamedTypeOrigin(named *types.Named) types.Type { | ||||
| func NamedTypeOrigin(named *types.Named) *types.Named { | ||||
| 	return named.Origin() | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,11 +10,10 @@ import "go/types" | |||
| 
 | ||||
| // A term describes elementary type sets:
 | ||||
| //
 | ||||
| //   ∅:  (*term)(nil)     == ∅                      // set of no types (empty set)
 | ||||
| //   𝓤:  &term{}          == 𝓤                      // set of all types (𝓤niverse)
 | ||||
| //   T:  &term{false, T}  == {T}                    // set of type T
 | ||||
| //  ~t:  &term{true, t}   == {t' | under(t') == t}  // set of types with underlying type t
 | ||||
| //
 | ||||
| //	 ∅:  (*term)(nil)     == ∅                      // set of no types (empty set)
 | ||||
| //	 𝓤:  &term{}          == 𝓤                      // set of all types (𝓤niverse)
 | ||||
| //	 T:  &term{false, T}  == {T}                    // set of type T
 | ||||
| //	~t:  &term{true, t}   == {t' | under(t') == t}  // set of types with underlying type t
 | ||||
| type term struct { | ||||
| 	tilde bool // valid if typ != nil
 | ||||
| 	typ   types.Type | ||||
|  |  | |||
|  | @ -0,0 +1,24 @@ | |||
| // Copyright 2023 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package typesinternal | ||||
| 
 | ||||
| import "go/types" | ||||
| 
 | ||||
| // This file contains back doors that allow gopls to avoid method sorting when
 | ||||
| // using the objectpath package.
 | ||||
| //
 | ||||
| // This is performance-critical in certain repositories, but changing the
 | ||||
| // behavior of the objectpath package is still being discussed in
 | ||||
| // golang/go#61443. If we decide to remove the sorting in objectpath we can
 | ||||
| // simply delete these back doors. Otherwise, we should add a new API to
 | ||||
| // objectpath that allows controlling the sorting.
 | ||||
| 
 | ||||
| // SkipEncoderMethodSorting marks enc (which must be an *objectpath.Encoder) as
 | ||||
| // not requiring sorted methods.
 | ||||
| var SkipEncoderMethodSorting func(enc interface{}) | ||||
| 
 | ||||
| // ObjectpathObject is like objectpath.Object, but allows suppressing method
 | ||||
| // sorting.
 | ||||
| var ObjectpathObject func(pkg *types.Package, p string, skipMethodSorting bool) (types.Object, error) | ||||
|  | @ -820,8 +820,8 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf | |||
| ## explicit; go 1.20 | ||||
| golang.org/x/exp/constraints | ||||
| golang.org/x/exp/slices | ||||
| # golang.org/x/mod v0.11.0 | ||||
| ## explicit; go 1.17 | ||||
| # golang.org/x/mod v0.13.0 | ||||
| ## explicit; go 1.18 | ||||
| golang.org/x/mod/internal/lazyregexp | ||||
| golang.org/x/mod/module | ||||
| golang.org/x/mod/semver | ||||
|  | @ -840,7 +840,7 @@ golang.org/x/net/trace | |||
| ## explicit; go 1.17 | ||||
| golang.org/x/oauth2 | ||||
| golang.org/x/oauth2/internal | ||||
| # golang.org/x/sync v0.3.0 | ||||
| # golang.org/x/sync v0.4.0 | ||||
| ## explicit; go 1.17 | ||||
| golang.org/x/sync/errgroup | ||||
| golang.org/x/sync/semaphore | ||||
|  | @ -865,12 +865,13 @@ golang.org/x/text/width | |||
| # golang.org/x/time v0.3.0 | ||||
| ## explicit | ||||
| golang.org/x/time/rate | ||||
| # golang.org/x/tools v0.10.0 | ||||
| # golang.org/x/tools v0.14.0 | ||||
| ## explicit; go 1.18 | ||||
| golang.org/x/tools/cmd/stringer | ||||
| golang.org/x/tools/go/gcexportdata | ||||
| golang.org/x/tools/go/internal/packagesdriver | ||||
| golang.org/x/tools/go/packages | ||||
| golang.org/x/tools/go/types/objectpath | ||||
| golang.org/x/tools/internal/event | ||||
| golang.org/x/tools/internal/event/core | ||||
| golang.org/x/tools/internal/event/keys | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue