Update go version

This commit is contained in:
dwrz
2026-08-21 10:23:37 +00:00
parent 78248a6145
commit c2e2d9ea02
466 changed files with 67766 additions and 2881 deletions

View File

@@ -45,6 +45,7 @@ import (
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/types/typeutil"
"golang.org/x/tools/internal/typesinternal"
)
// A Result holds the results of Rapid Type Analysis, which includes the
@@ -72,6 +73,10 @@ type Result struct {
// fmt.Println(new(A))
// Types *A, A and B are accessible to reflection, but the unnamed
// type struct{B} is not.
//
// TODO(adonovan): populating this field is expensive yet it
// is never used in x/tools. Add a revised [Analyze] API that
// provides the option not to set it.
RuntimeTypes typeutil.Map
}
@@ -114,15 +119,13 @@ type rta struct {
type concreteTypeInfo struct {
C types.Type
mset *types.MethodSet
fprint uint64 // fingerprint of method set
implements []*types.Interface // unordered set of implemented interfaces
}
type interfaceTypeInfo struct {
I *types.Interface
mset *types.MethodSet
fprint uint64
fprint uint64 // fingerprint of method set
implementations []types.Type // unordered set of concrete implementations
}
@@ -281,7 +284,7 @@ func (r *rta) visitFunc(f *ssa.Function) {
// interface materializes its runtime
// type, allowing any of its exported
// methods to be called though reflection.
r.addRuntimeType(instr.X.Type(), false)
r.addRuntimeType(instr.X.Type())
}
// Process all address-taken functions.
@@ -361,11 +364,9 @@ func (r *rta) interfaces(C types.Type) []*types.Interface {
if v := r.concreteTypes.At(C); v != nil {
cinfo = v.(*concreteTypeInfo)
} else {
mset := r.prog.MethodSets.MethodSet(C)
cinfo = &concreteTypeInfo{
C: C,
mset: mset,
fprint: fingerprint(mset),
fprint: fingerprint(r.prog.MethodSets.MethodSet(C)),
}
r.concreteTypes.Set(C, cinfo)
@@ -390,11 +391,9 @@ func (r *rta) implementations(I *types.Interface) []types.Type {
if v := r.interfaceTypes.At(I); v != nil {
iinfo = v.(*interfaceTypeInfo)
} else {
mset := r.prog.MethodSets.MethodSet(I)
iinfo = &interfaceTypeInfo{
I: I,
mset: mset,
fprint: fingerprint(mset),
fprint: fingerprint(r.prog.MethodSets.MethodSet(I)),
}
r.interfaceTypes.Set(I, iinfo)
@@ -413,127 +412,43 @@ func (r *rta) implementations(I *types.Interface) []types.Type {
// addRuntimeType is called for each concrete type that can be the
// dynamic type of some interface or reflect.Value.
// Adapted from needMethods in go/ssa/builder.go
func (r *rta) addRuntimeType(T types.Type, skip bool) {
// Never record aliases.
T = types.Unalias(T)
if prev, ok := r.result.RuntimeTypes.At(T).(bool); ok {
if skip && !prev {
r.result.RuntimeTypes.Set(T, skip)
func (r *rta) addRuntimeType(T types.Type) {
methodSetOf := r.prog.MethodSets.MethodSet
typesinternal.ForEachElement(methodSetOf, T, func(T types.Type, access bool) bool {
if prevInaccess, ok := r.result.RuntimeTypes.At(T).(bool); ok {
if prevInaccess && access {
// A type previously marked inaccessible (ok && prevInaccess)
// is now found to be accessible (access):
// record that it is no longer inaccessible (false).
// (The inverted sense of the map is regrettable.)
r.result.RuntimeTypes.Set(T, false)
}
return true // seen; prune traversal
}
return
}
r.result.RuntimeTypes.Set(T, skip)
r.result.RuntimeTypes.Set(T, !access) // record inaccessibility
mset := r.prog.MethodSets.MethodSet(T)
if !types.IsInterface(T) {
// T is a new concrete type.
if _, ok := T.Underlying().(*types.Interface); !ok {
// T is a new concrete type.
for i, n := 0, mset.Len(); i < n; i++ {
sel := mset.At(i)
m := sel.Obj()
// Exported methods are always potentially callable via reflection.
for sel := range methodSetOf(T).Methods() {
if sel.Obj().Exported() {
r.addReachable(r.prog.MethodValue(sel), true)
}
}
if m.Exported() {
// Exported methods are always potentially callable via reflection.
r.addReachable(r.prog.MethodValue(sel), true)
// Add callgraph edge for each existing dynamic
// "invoke"-mode call via that interface.
for _, I := range r.interfaces(T) {
sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
for _, site := range sites {
r.addInvokeEdge(site, T)
}
}
}
// Add callgraph edge for each existing dynamic
// "invoke"-mode call via that interface.
for _, I := range r.interfaces(T) {
sites, _ := r.invokeSites.At(I).([]ssa.CallInstruction)
for _, site := range sites {
r.addInvokeEdge(site, T)
}
}
}
// Precondition: T is not a method signature (*Signature with Recv()!=nil).
// Recursive case: skip => don't call makeMethods(T).
// Each package maintains its own set of types it has visited.
var n *types.Named
switch T := types.Unalias(T).(type) {
case *types.Named:
n = T
case *types.Pointer:
n, _ = types.Unalias(T.Elem()).(*types.Named)
}
if n != nil {
owner := n.Obj().Pkg()
if owner == nil {
return // built-in error type
}
}
// Recursion over signatures of each exported method.
for method := range mset.Methods() {
if method.Obj().Exported() {
sig := method.Type().(*types.Signature)
r.addRuntimeType(sig.Params(), true) // skip the Tuple itself
r.addRuntimeType(sig.Results(), true) // skip the Tuple itself
}
}
switch t := T.(type) {
case *types.Alias:
panic("unreachable")
case *types.Basic:
// nop
case *types.Interface:
// nop---handled by recursion over method set.
case *types.Pointer:
r.addRuntimeType(t.Elem(), false)
case *types.Slice:
r.addRuntimeType(t.Elem(), false)
case *types.Chan:
r.addRuntimeType(t.Elem(), false)
case *types.Map:
r.addRuntimeType(t.Key(), false)
r.addRuntimeType(t.Elem(), false)
case *types.Signature:
if t.Recv() != nil {
panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
}
r.addRuntimeType(t.Params(), true) // skip the Tuple itself
r.addRuntimeType(t.Results(), true) // skip the Tuple itself
case *types.Named:
// A pointer-to-named type can be derived from a named
// type via reflection. It may have methods too.
r.addRuntimeType(types.NewPointer(T), false)
// Consider 'type T struct{S}' where S has methods.
// Reflection provides no way to get from T to struct{S},
// only to S, so the method set of struct{S} is unwanted,
// so set 'skip' flag during recursion.
r.addRuntimeType(t.Underlying(), true)
case *types.Array:
r.addRuntimeType(t.Elem(), false)
case *types.Struct:
for i, n := 0, t.NumFields(); i < n; i++ {
r.addRuntimeType(t.Field(i).Type(), false)
}
case *types.Tuple:
for i, n := 0, t.Len(); i < n; i++ {
r.addRuntimeType(t.At(i).Type(), false)
}
default:
panic(T)
}
return false
})
}
// fingerprint returns a bitmask with one bit set per method id,
@@ -544,6 +459,9 @@ func fingerprint(mset *types.MethodSet) uint64 {
for method := range mset.Methods() {
method := method.Obj()
sig := method.Type().(*types.Signature)
if sig.TypeParams() != nil {
continue // skip generic methods since interfaces don't have them
}
sum := crc32.ChecksumIEEE(fmt.Appendf(space[:], "%s/%d/%d",
method.Id(),
sig.Params().Len(),

View File

@@ -101,6 +101,7 @@ func (g *Graph) DeleteSyntheticNodes() {
edges[*e] = true
}
}
// Note: these cross-products can exceed 100 x 100.
for fn, cgn := range g.Nodes {
if cgn == g.Root || isInit(cgn.Func) || fn.Syntax() != nil {
continue // keep

View File

@@ -16,10 +16,10 @@ type Scope struct {
id int32
}
var nextScopeId int32
var nextScopeId atomic.Int32
func newScope() Scope {
id := atomic.AddInt32(&nextScopeId, 1)
id := nextScopeId.Add(1)
return Scope{id: id}
}

View File

@@ -155,9 +155,9 @@ func propagate(graph *vtaGraph, canon *typeutil.Map) propTypeMap {
sccToTypes[sccID] = &typeSet
}
for i := len(sccs) - 1; i >= 0; i-- {
for i, scc := range slices.Backward(sccs) {
nextSccs := make(map[int]empty)
for _, n := range sccs[i] {
for _, n := range scc {
for succ := range graph.successors(n) {
nextSccs[idxToSccID[succ]] = empty{}
}

View File

@@ -73,6 +73,9 @@ import (
// CallGraph does not make any assumptions on initial types global variables
// and function/method inputs can have. CallGraph is then sound, modulo use of
// reflection and unsafe, if the initial call graph is sound.
//
// The supplied SSA functions must have been constructed with the
// [ssa.InstantiateGenerics] mode flag.
func CallGraph(funcs map[*ssa.Function]bool, initial *callgraph.Graph) *callgraph.Graph {
callees := makeCalleesFunc(funcs, initial)
vtaG, canon := typePropGraph(funcs, callees)