Merge pull request #2956 from opencloud-eu/dependabot/go_modules/golang.org/x/text-0.38.0

build(deps): bump golang.org/x/text from 0.37.0 to 0.38.0
This commit is contained in:
Ralf Haferkamp
2026-06-17 10:18:46 +02:00
committed by GitHub
14 changed files with 475 additions and 296 deletions

8
go.mod
View File

@@ -107,9 +107,9 @@ require (
golang.org/x/image v0.40.0
golang.org/x/net v0.55.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.20.0
golang.org/x/sync v0.21.0
golang.org/x/term v0.43.0
golang.org/x/text v0.37.0
golang.org/x/text v0.38.0
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa
google.golang.org/grpc v1.81.1
google.golang.org/protobuf v1.36.11
@@ -389,10 +389,10 @@ require (
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.35.0 // indirect
golang.org/x/mod v0.36.0 // indirect
golang.org/x/sys v0.45.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.44.0 // indirect
golang.org/x/tools v0.45.0 // indirect
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect

16
go.sum
View File

@@ -1400,8 +1400,8 @@ 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
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=
@@ -1477,8 +1477,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1583,8 +1583,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1645,8 +1645,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -109,7 +109,7 @@ func (g *Group) TryGo(f func() error) bool {
if g.sem != nil {
select {
case g.sem <- token{}:
// Note: this allows barging iff channels in general allow barging.
// Note: this allows barging if and only if channels in general allow barging.
default:
return false
}

View File

@@ -83,7 +83,7 @@ func (s *Weighted) Acquire(ctx context.Context, n int64) error {
default:
isFront := s.waiters.Front() == elem
s.waiters.Remove(elem)
// If we're at the front and there're extra tokens left, notify other waiters.
// If we're at the front and there are extra tokens left, notify other waiters.
if isFront && s.size > s.cur {
s.notifyWaiters()
}
@@ -139,15 +139,15 @@ func (s *Weighted) notifyWaiters() {
w := next.Value.(waiter)
if s.size-s.cur < w.n {
// Not enough tokens for the next waiter. We could keep going (to try to
// Not enough tokens for the next waiter. We could keep going (to try to
// find a waiter with a smaller request), but under load that could cause
// starvation for large requests; instead, we leave all remaining waiters
// blocked.
//
// Consider a semaphore used as a read-write lock, with N tokens, N
// readers, and one writer. Each reader can Acquire(1) to obtain a read
// lock. The writer can Acquire(N) to obtain a write lock, excluding all
// of the readers. If we allow the readers to jump ahead in the queue,
// readers, and one writer. Each reader can Acquire(1) to obtain a read
// lock. The writer can Acquire(N) to obtain a write lock, excluding all
// of the readers. If we allow the readers to jump ahead in the queue,
// the writer will starve — there is always one token available for every
// reader.
break

View File

@@ -15,12 +15,12 @@ import (
"sync"
)
// errGoexit indicates the runtime.Goexit was called in
// the user given function.
// errGoexit indicates runtime.Goexit was called in
// the user-given function.
var errGoexit = errors.New("runtime.Goexit was called")
// A panicError is an arbitrary value recovered from a panic
// with the stack trace during the execution of given function.
// with the stack trace during the execution of the given function.
type panicError struct {
value any
stack []byte
@@ -204,7 +204,7 @@ func (g *Group) doCall(c *call, key string, fn func() (any, error)) {
}
}
// Forget tells the singleflight to forget about a key. Future calls
// Forget tells the singleflight to forget about a key. Future calls
// to Do for this key will call the function rather than waiting for
// an earlier call to complete.
func (g *Group) Forget(key string) {

View File

@@ -12,7 +12,7 @@ import (
"reflect"
)
// A Kind describes a field of an ast.Node struct.
// A Kind describes a field of an [ast.Node] struct.
type Kind uint8
// String returns a description of the edge kind.
@@ -41,21 +41,25 @@ func (k Kind) Get(n ast.Node, idx int) ast.Node {
panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n))
}
v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)
if idx != -1 {
v = v.Index(idx) // asserts valid index
} else {
// (The type assertion below asserts that v is not a slice.)
if v.Kind() == reflect.Slice {
v = v.Index(idx) // asserts valid idx
} else if idx != -1 {
panic(fmt.Sprintf("%v, Get(%T, %d): cannot index non-slice", v, n, idx))
}
return v.Interface().(ast.Node) // may be nil
out, _ := v.Interface().(ast.Node) // may be nil
return out
}
// Each [Kind] is named Type_Field, where Type is the
// [ast.Node] struct type and Field is the name of the field
const (
Invalid Kind = iota // for nodes at the root of the traversal
// Kinds are sorted alphabetically.
// Numbering is not stable.
// Each is named Type_Field, where Type is the
// ast.Node struct type and Field is the name of the field
// As of Go1.26 these kinds are sorted alphabetically, but
// numbering must be stable, so any new addition of const should
// use a new value (be added at the end of the list).
ArrayType_Elt
ArrayType_Len

View File

@@ -207,11 +207,10 @@ func goListDriver(cfg *Config, runner *gocommand.Runner, overlay string, pattern
// doesn't exist.
extractQueries:
for _, pattern := range patterns {
eqidx := strings.Index(pattern, "=")
if eqidx < 0 {
query, value, ok := strings.Cut(pattern, "=")
if !ok {
restPatterns = append(restPatterns, pattern)
} else {
query, value := pattern[:eqidx], pattern[eqidx+len("="):]
switch query {
case "file":
containFiles = append(containFiles, value)
@@ -563,8 +562,18 @@ func (state *golistState) createDriverResponse(words ...string) (*DriverResponse
} else {
// golang/go#38990: go list silently fails to do cgo processing
pkg.CompiledGoFiles = nil
var msg strings.Builder
fmt.Fprintf(&msg, "go list failed to return CompiledGoFiles for %q.\n", p.Name)
for _, err := range p.DepsErrors {
msg.WriteString(strings.TrimSpace(err.Err))
msg.WriteByte('\n')
}
msg.WriteString("This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.")
pkg.Errors = append(pkg.Errors, Error{
Msg: "go list failed to return CompiledGoFiles. This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.",
Msg: msg.String(),
Kind: ListError,
})
}

View File

@@ -539,6 +539,11 @@ type Package struct {
// depsErrors is the DepsErrors field from the go list response, if any.
depsErrors []*packagesinternal.PackageError
// exportDataError is the error encountered reading export data, if any.
// Decoding export data should ordinarily be infallible, so this typically
// indicates a producer/consumer version skew.
exportDataError error
}
// Module provides module information for a package.
@@ -1073,10 +1078,11 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
}
// TODO(adonovan): this condition looks wrong:
// I think it should be lpkg.needtypes && !lpg.needsrc,
// I think it should be lpkg.needtypes && !lpkg.needsrc,
// so that NeedSyntax without NeedTypes can be satisfied by export data.
if !lpkg.needsrc {
if err := ld.loadFromExportData(lpkg); err != nil {
lpkg.exportDataError = err
lpkg.Errors = append(lpkg.Errors, Error{
Pos: "-",
Msg: err.Error(),
@@ -1215,7 +1221,13 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
if ipkg.Types != nil && ipkg.Types.Complete() {
return ipkg.Types, nil
}
log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
// If types are unavailable, there must be an export data error.
if ipkg.exportDataError != nil {
return nil, ipkg.exportDataError
}
log.Fatalf("internal error: expected complete types for package %q", path)
panic("unreachable")
})

View File

@@ -24,8 +24,10 @@
package objectpath
import (
"encoding/binary"
"fmt"
"go/types"
"slices"
"strconv"
"strings"
@@ -124,7 +126,66 @@ func For(obj types.Object) (Path, error) {
// 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
pkgIndex map[*types.Package]*pkgIndex
}
// A traversal encapsulates the state of a single traversal of the object/type graph.
type traversal struct {
pkg *types.Package
ix *pkgIndex // non-nil if we are building the index
target types.Object // the sought symbol (if ix == nil)
found Path // the found path (if ix == nil)
// These maps are used to short circuit cycles through
// interface methods, such as occur in the following example:
//
// type I interface { f() interface{I} }
//
// See golang/go#68046 for details.
seenTParamNames map[*types.TypeName]bool // global cycle breaking through type parameters
seenMethods map[*types.Func]bool // global cycle breaking through recursive interfaces
}
// A pkgIndex holds a compressed index of objectpaths of all symbols
// (fields, methods, params) requiring search for an entire package.
//
// The first time a search for a given package is requested, we simply
// traverse the type graph for the target object, maintaining the
// current object path as a stack. If we find the target object, we
// save the path and terminate the main loop (but it's not worth
// breaking out of the current recursion).
//
// On the second search (a pkgIndex exists but its data is nil), we
// build an index of the traversal, which we use for all subsequent
// searches.
//
// The traversal index is encoded in the data field as a list of records,
// one per node, in preorder. Records are of two types:
//
// - A record for a package-level object consists of a pair
// (parent, nameIndex uvarint), where parent is zero and
// nameIndex is the index of the object's name in the sorted
// pkg.Scope().Names() slice.
//
// - A record for a nested node (a segment of an object path)
// consists of (parent uvarint, op byte, index uvarint), where
// parent is the index of the record for the parent node,
// op is the destructuring operator, and index (if op = [AFMTr])
// is its integer operand.
//
// Since data[0] = 0 all nodes have positive offsets. In effect the
// encoding is a trie in which each node stores one path segment
// and points to the node for its prefix.
//
// TODO(adonovan): opt: evaluate an only 2-level tree with nodes for
// package-level objects and the-rest-of-the-path. One calculation
// suggested that it might be similar speed but 30% more compact.
type pkgIndex struct {
pkg *types.Package
data []byte // encoding of traversal; nil if not yet constructed
scopeNames []string // memo of pkg.Scope().Names() to avoid O(n) alloc/sort at lookup
offsets map[types.Object]uint32 // each object's node offset within encoded traversal data
}
// For returns the path to an object relative to its package,
@@ -211,10 +272,9 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
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 {
if pkg.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() {
@@ -232,19 +292,18 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
// 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.
// A var, if not package-level, must be a
// parameter (incl. receiver) or result, or a struct field.
if obj.Kind() == types.LocalVar {
return "", fmt.Errorf("no path for local %v", obj)
}
case *types.Func:
// A func, if not package-level, must be a method.
@@ -261,89 +320,311 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
panic(obj)
}
// 4. Search the API for the path to the var (field/param/result) or method.
// 4. Search the object/type graph for the path to
// the var (field/param/result) or method.
ix, ok := enc.pkgIndex[pkg]
if !ok {
// First search: don't build an index, just traverse.
// This avoids allocation in [For], whose Encoder
// lives for a single call.
ix = &pkgIndex{pkg: pkg}
// 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
if enc.pkgIndex == nil {
enc.pkgIndex = make(map[*types.Package]*pkgIndex)
}
enc.pkgIndex[pkg] = ix // build the index next time
f := traversal{pkg: pkg, target: obj}
f.traverse()
if f.found != "" {
return f.found, nil
}
} else {
// Second search: build an index while traversing.
if ix.data == nil {
ix.offsets = make(map[types.Object]uint32)
ix.data = []byte{0} // offset 0 is sentinel
(&traversal{pkg: pkg, ix: ix}).traverse()
}
path := append(empty, o.Name()...)
path = append(path, opType)
T := o.Type()
if alias, ok := T.(*types.Alias); ok {
if r := findTypeParam(obj, alias.TypeParams(), path, opTypeParam); r != nil {
return Path(r), nil
}
if r := find(obj, alias.Rhs(), append(path, opRhs)); r != nil {
return Path(r), nil
}
} else if tname.IsAlias() {
// legacy alias
if r := find(obj, T, path); r != nil {
return Path(r), nil
}
} else if named, ok := T.(*types.Named); ok {
// defined (named) type
if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam); r != nil {
return Path(r), nil
}
if r := find(obj, named.Underlying(), append(path, opUnderlying)); 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)); r != nil {
return Path(r), nil
}
}
continue
}
// Inspect declared methods of defined types.
if T, ok := types.Unalias(o.Type()).(*types.Named); ok {
path = append(path, opType)
// The method index here is always with respect
// to the underlying go/types data structures,
// which ultimately derives from source order
// and must be preserved by export data.
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)); r != nil {
return Path(r), nil
}
}
// Second and later searches: consult the index.
if offset, ok := ix.offsets[obj]; ok {
return ix.path(offset), nil
}
}
return "", fmt.Errorf("can't find path for %v in %s", obj, pkg.Path())
}
func appendOpArg(path []byte, op byte, arg int) []byte {
// traverse performs a complete traversal of all symbols reachable from the package.
func (tr *traversal) traverse() {
scope := tr.pkg.Scope()
names := scope.Names()
if tr.ix != nil {
tr.ix.scopeNames = names
}
empty := make([]byte, 0, 48) // initial space for stack (ix == nil)
// First inspect package-level type names.
// In the presence of path aliases, these give
// the best paths because non-types may
// refer to types, but not the reverse.
for i, name := range names {
if tr.found != "" {
return // found (ix == nil)
}
obj := scope.Lookup(name)
if _, ok := obj.(*types.TypeName); !ok {
continue // handle non-types in second pass
}
// emit (name, opType)
var path []byte
var offset uint32
if tr.ix == nil {
path = append(empty, name...)
path = append(path, opType)
} else {
offset = tr.ix.emitPackageLevel(i)
tr.ix.offsets[obj] = offset
offset = tr.ix.emitPathSegment(offset, opType, -1)
}
// A TypeName (for Named or Alias) may have type parameters.
switch t := obj.Type().(type) {
case *types.Alias:
tr.tparams(t.TypeParams(), path, offset, opTypeParam)
tr.typ(path, offset, opRhs, -1, t.Rhs())
case *types.Named:
tr.tparams(t.TypeParams(), path, offset, opTypeParam)
tr.typ(path, offset, opUnderlying, -1, t.Underlying())
}
}
// Then inspect everything else:
// exported non-types, and declared methods of defined types.
for i, name := range names {
if tr.found != "" {
return // found (ix == nil)
}
obj := scope.Lookup(name)
if tname, ok := obj.(*types.TypeName); !ok {
if obj.Exported() {
// exported non-type (const, var, func)
var path []byte
var offset uint32
if tr.ix == nil {
path = append(empty, name...)
} else {
offset = tr.ix.emitPackageLevel(i)
tr.ix.offsets[obj] = offset
}
tr.typ(path, offset, opType, -1, obj.Type())
}
} else if T, ok := types.Unalias(tname.Type()).(*types.Named); ok {
// defined type
var path []byte
var offset uint32
if tr.ix == nil {
path = append(empty, name...)
path = append(path, opType)
} else {
// Inv: map entry for obj was populated in first pass.
offset = tr.ix.emitPathSegment(tr.ix.offsets[obj], opType, -1)
}
// Inspect declared methods of defined types.
//
// The method index here is always with respect
// to the underlying go/types data structures,
// which ultimately derives from source order
// and must be preserved by export data.
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
tr.object(path, offset, opMethod, i, m)
}
}
}
}
func (tr *traversal) visitType(path []byte, offset uint32, T types.Type) {
switch T := T.(type) {
case *types.Alias:
tr.typ(path, offset, opRhs, -1, T.Rhs())
case *types.Basic, *types.Named:
// Named types belonging to pkg were handled already,
// so T must belong to another package. No path.
return
case *types.Pointer, *types.Slice, *types.Array, *types.Chan:
type hasElem interface{ Elem() types.Type } // note: includes Map
tr.typ(path, offset, opElem, -1, T.(hasElem).Elem())
case *types.Map:
tr.typ(path, offset, opKey, -1, T.Key())
tr.typ(path, offset, opElem, -1, T.Elem())
case *types.Signature:
tr.tparams(T.RecvTypeParams(), path, offset, opRecvTypeParam)
tr.tparams(T.TypeParams(), path, offset, opTypeParam)
tr.typ(path, offset, opParams, -1, T.Params())
tr.typ(path, offset, opResults, -1, T.Results())
case *types.Struct:
for i := 0; i < T.NumFields(); i++ {
tr.object(path, offset, opField, i, T.Field(i))
}
case *types.Tuple:
for i := 0; i < T.Len(); i++ {
tr.object(path, offset, opAt, i, T.At(i))
}
case *types.Interface:
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
if m.Pkg() != nil && m.Pkg() != tr.pkg {
continue // embedded method from another package
}
if !tr.seenMethods[m] {
if tr.seenMethods == nil {
tr.seenMethods = make(map[*types.Func]bool)
}
tr.seenMethods[m] = true
tr.object(path, offset, opMethod, i, m)
}
}
case *types.TypeParam:
tname := T.Obj()
if tname.Pkg() != nil && tname.Pkg() != tr.pkg {
return // type parameter from another package
}
if !tr.seenTParamNames[tname] {
if tr.seenTParamNames == nil {
tr.seenTParamNames = make(map[*types.TypeName]bool)
}
tr.seenTParamNames[tname] = true
tr.object(path, offset, opObj, -1, tname)
tr.typ(path, offset, opConstraint, -1, T.Constraint())
}
}
}
func (tr *traversal) tparams(list *types.TypeParamList, path []byte, offset uint32, op byte) {
for i := 0; i < list.Len(); i++ {
tr.typ(path, offset, op, i, list.At(i))
}
}
// typ descends the type graph edge (op, index), then proceeds to traverse type t.
func (tr *traversal) typ(path []byte, offset uint32, op byte, index int, t types.Type) {
if tr.ix == nil {
path = appendOpArg(path, op, index)
} else {
offset = tr.ix.emitPathSegment(offset, op, index)
}
tr.visitType(path, offset, t)
}
// object descends the type graph edge (op, index), records object
// obj, then proceeds to traverse its type.
func (tr *traversal) object(path []byte, offset uint32, op byte, index int, obj types.Object) {
if tr.ix == nil {
path = appendOpArg(path, op, index)
if obj == tr.target && tr.found == "" {
tr.found = Path(path)
}
path = append(path, opType)
} else {
offset = tr.ix.emitPathSegment(offset, op, index)
if _, ok := tr.ix.offsets[obj]; !ok {
tr.ix.offsets[obj] = offset
}
offset = tr.ix.emitPathSegment(offset, opType, -1)
}
tr.visitType(path, offset, obj.Type())
}
// emitPackageLevel encodes a record for a package-level symbol,
// identified by its index in ix.scopeNames.
func (p *pkgIndex) emitPackageLevel(index int) uint32 {
off := uint32(len(p.data))
p.data = append(p.data, 0) // zero varint => no parent
p.data = binary.AppendUvarint(p.data, uint64(index))
return off
}
// emitPathSegment emits a record for a non-initial object path segment.
func (p *pkgIndex) emitPathSegment(parent uint32, op byte, index int) uint32 {
off := uint32(len(p.data))
p.data = binary.AppendUvarint(p.data, uint64(parent))
p.data = append(p.data, op)
switch op {
case opAt, opField, opMethod, opTypeParam, opRecvTypeParam:
p.data = binary.AppendUvarint(p.data, uint64(index))
}
return off
}
// path returns the Path for the encoded node at the specified offset.
func (p *pkgIndex) path(offset uint32) Path {
var elems []string // path elements in reverse
for {
// Read parent index.
parent, n := binary.Uvarint(p.data[offset:])
offset += uint32(n)
if parent == 0 {
break // root (end of path)
}
op := p.data[offset]
offset++
// The [AFMTr] operators have a numeric operand.
switch op {
case opAt, opField, opMethod, opTypeParam, opRecvTypeParam:
val, n := binary.Uvarint(p.data[offset:])
offset += uint32(n)
elems = append(elems, strconv.Itoa(int(val)))
}
elems = append(elems, string([]byte{op}))
offset = uint32(parent)
}
idx, _ := binary.Uvarint(p.data[offset:])
// Convert index to Path string.
name := p.scopeNames[idx]
sz := len(name)
for _, elem := range elems {
sz += len(elem)
}
var buf strings.Builder
buf.Grow(sz)
buf.WriteString(name)
for _, elem := range slices.Backward(elems) {
buf.WriteString(elem)
}
return Path(buf.String())
}
// appendOpArg appends (op, index) to the object path.
// A negative index is ignored.
func appendOpArg(path []byte, op byte, index int) []byte {
path = append(path, op)
path = strconv.AppendInt(path, int64(arg), 10)
if index >= 0 {
path = strconv.AppendInt(path, int64(index), 10)
}
return path
}
@@ -442,138 +723,6 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
// 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.
//
// The seenMethods map is used internally to short circuit cycles through
// interface methods, such as occur in the following example:
//
// type I interface { f() interface{I} }
//
// See golang/go#68046 for details.
func find(obj types.Object, T types.Type, path []byte) []byte {
return (&finder{obj: obj}).find(T, path)
}
// finder closes over search state for a call to find.
type finder struct {
obj types.Object // the sought object
seenTParamNames map[*types.TypeName]bool // for cycle breaking through type parameters
seenMethods map[*types.Func]bool // for cycle breaking through recursive interfaces
}
func (f *finder) find(T types.Type, path []byte) []byte {
switch T := T.(type) {
case *types.Alias:
return f.find(types.Unalias(T), path)
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 f.find(T.Elem(), append(path, opElem))
case *types.Slice:
return f.find(T.Elem(), append(path, opElem))
case *types.Array:
return f.find(T.Elem(), append(path, opElem))
case *types.Chan:
return f.find(T.Elem(), append(path, opElem))
case *types.Map:
if r := f.find(T.Key(), append(path, opKey)); r != nil {
return r
}
return f.find(T.Elem(), append(path, opElem))
case *types.Signature:
if r := f.findTypeParam(T.RecvTypeParams(), path, opRecvTypeParam); r != nil {
return r
}
if r := f.findTypeParam(T.TypeParams(), path, opTypeParam); r != nil {
return r
}
if r := f.find(T.Params(), append(path, opParams)); r != nil {
return r
}
return f.find(T.Results(), append(path, opResults))
case *types.Struct:
for i := 0; i < T.NumFields(); i++ {
fld := T.Field(i)
path2 := appendOpArg(path, opField, i)
if fld == f.obj {
return path2 // found field var
}
if r := f.find(fld.Type(), append(path2, opType)); 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 == f.obj {
return path2 // found param/result var
}
if r := f.find(v.Type(), append(path2, opType)); r != nil {
return r
}
}
return nil
case *types.Interface:
for i := 0; i < T.NumMethods(); i++ {
m := T.Method(i)
if f.seenMethods[m] {
continue // break cycles (see TestIssue70418)
}
path2 := appendOpArg(path, opMethod, i)
if m == f.obj {
return path2 // found interface method
}
if f.seenMethods == nil {
f.seenMethods = make(map[*types.Func]bool)
}
f.seenMethods[m] = true
if r := f.find(m.Type(), append(path2, opType)); r != nil {
return r
}
}
return nil
case *types.TypeParam:
name := T.Obj()
if f.seenTParamNames[name] {
return nil
}
if name == f.obj {
return append(path, opObj)
}
if f.seenTParamNames == nil {
f.seenTParamNames = make(map[*types.TypeName]bool)
}
f.seenTParamNames[name] = true
if r := f.find(T.Constraint(), append(path, opConstraint)); r != nil {
return r
}
return nil
}
panic(T)
}
func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte) []byte {
return (&finder{obj: obj}).findTypeParam(list, path, op)
}
func (f *finder) findTypeParam(list *types.TypeParamList, path []byte, op byte) []byte {
for i := 0; i < list.Len(); i++ {
tparam := list.At(i)
path2 := appendOpArg(path, op, i)
if r := f.find(tparam, path2); 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) {
pathstr := string(p)
@@ -708,7 +857,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
}
tparams := hasTypeParams.TypeParams()
if n := tparams.Len(); index >= n {
return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n)
return nil, fmt.Errorf("type parameter index %d out of range [0-%d)", index, n)
}
t = tparams.At(index)
@@ -719,7 +868,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
}
rtparams := sig.RecvTypeParams()
if n := rtparams.Len(); index >= n {
return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n)
return nil, fmt.Errorf("receiver type parameter index %d out of range [0-%d)", index, n)
}
t = rtparams.At(index)
@@ -794,23 +943,3 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
return obj, nil // success
}
// 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
}

View File

@@ -11,6 +11,7 @@ import (
"go/token"
"go/types"
"sort"
"strings"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/pkgbits"
@@ -523,6 +524,12 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
return objPkg, objName
}
// TODO(mark): This, like the above splitVargenSuffix, is not ideal.
// Ignore generic methods promoted to global scope.
if strings.Contains(objName, ".") {
return objPkg, objName
}
if objPkg.Scope().Lookup(objName) == nil {
dict := pr.objDictIdx(idx)
@@ -554,15 +561,11 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
case pkgbits.ObjFunc:
pos := r.pos()
var rtparams []*types.TypeParam
var recv *types.Var
if r.Version().Has(pkgbits.GenericMethods) && r.Bool() {
r.selector()
rtparams = r.typeParamNames(true)
recv = r.param()
if r.Version().Has(pkgbits.GenericMethods) {
assert(!r.Bool()) // generic methods are read in their defining type
}
tparams := r.typeParamNames(false)
sig := r.signature(recv, rtparams, tparams)
sig := r.signature(nil, nil, tparams)
declare(types.NewFunc(pos, objPkg, objName, sig))
case pkgbits.ObjType:
@@ -630,6 +633,29 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
named.AddMethod(r.method())
}
if r.Version().Has(pkgbits.GenericMethods) {
for range r.Len() {
// Careful: objIdx is used to read in package-scoped declarations, which
// methods are not. Instead, decode it here. This makes it easier to
// associate it with the type and avoids the main objIdx loop.
idx := r.Reloc(pkgbits.RelocObj)
r := pr.tempReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
r.dict = pr.objDictIdx(idx)
pos := r.pos()
assert(r.Bool()) // generic method
pkg, name := r.selector()
rtparams := r.typeParamNames(true)
recv := r.param()
tparams := r.typeParamNames(false)
sig := r.signature(recv, rtparams, tparams)
pr.retireReader(r)
named.AddMethod(types.NewFunc(pos, pkg, name, sig))
}
}
case pkgbits.ObjVar:
pos := r.pos()
typ := r.typ()
@@ -653,7 +679,7 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
}
nreceivers := 0
if r.Version().Has(pkgbits.GenericMethods) && r.Bool() {
if r.Version().Has(pkgbits.GenericMethods) {
nreceivers = r.Len()
}
nexplicits := r.Len()

View File

@@ -8,6 +8,7 @@ import (
"context"
"fmt"
"regexp"
"slices"
"strings"
)
@@ -41,9 +42,9 @@ func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {
}
// Split up "[go1.1 go1.15]" and return highest go1.X value.
tags := strings.Fields(stdout[1 : len(stdout)-2])
for i := len(tags) - 1; i >= 0; i-- {
for _, tag := range slices.Backward(tags) {
var version int
if _, err := fmt.Sscanf(tags[i], "go1.%d", &version); err != nil {
if _, err := fmt.Sscanf(tag, "go1.%d", &version); err != nil {
continue
}
return version, nil

View File

@@ -1650,9 +1650,7 @@ func (s *symbolSearcher) search(ctx context.Context, candidates []pkgDistance, p
}()
// Start the search.
wg.Add(1)
go func() {
defer wg.Done()
wg.Go(func() {
for i, c := range candidates {
select {
case loadExportsSem <- struct{}{}:
@@ -1681,7 +1679,7 @@ func (s *symbolSearcher) search(ctx context.Context, candidates []pkgDistance, p
rescv[i] <- pkg // may be nil
}()
}
}()
})
// Await the first (best) result.
for _, resc := range rescv {

View File

@@ -679,11 +679,11 @@ func modRelevance(mod *gocommand.ModuleJSON) float64 {
_, versionString, ok := module.SplitPathVersion(mod.Path)
if ok {
index := strings.Index(versionString, "v")
if index == -1 {
_, after, ok := strings.Cut(versionString, "v")
if !ok {
return relevance
}
if versionNumber, err := strconv.ParseFloat(versionString[index+1:], 64); err == nil {
if versionNumber, err := strconv.ParseFloat(after, 64); err == nil {
relevance += versionNumber / 1000
}
}

8
vendor/modules.txt vendored
View File

@@ -2466,7 +2466,7 @@ golang.org/x/image/vector
golang.org/x/image/vp8
golang.org/x/image/vp8l
golang.org/x/image/webp
# golang.org/x/mod v0.35.0
# golang.org/x/mod v0.36.0
## explicit; go 1.25.0
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/module
@@ -2500,7 +2500,7 @@ golang.org/x/net/trace
## explicit; go 1.25.0
golang.org/x/oauth2
golang.org/x/oauth2/internal
# golang.org/x/sync v0.20.0
# golang.org/x/sync v0.21.0
## explicit; go 1.25.0
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
@@ -2519,7 +2519,7 @@ golang.org/x/sys/windows/svc/mgr
# golang.org/x/term v0.43.0
## explicit; go 1.25.0
golang.org/x/term
# golang.org/x/text v0.37.0
# golang.org/x/text v0.38.0
## explicit; go 1.25.0
golang.org/x/text/cases
golang.org/x/text/collate
@@ -2549,7 +2549,7 @@ golang.org/x/text/width
# golang.org/x/time v0.15.0
## explicit; go 1.25.0
golang.org/x/time/rate
# golang.org/x/tools v0.44.0
# golang.org/x/tools v0.45.0
## explicit; go 1.25.0
golang.org/x/tools/cover
golang.org/x/tools/go/ast/astutil