Initialize module and dependencies
This commit is contained in:
127
vendor/golang.org/x/tools/go/ssa/instantiate.go
generated
vendored
Normal file
127
vendor/golang.org/x/tools/go/ssa/instantiate.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"slices"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A generic records information about a generic origin function,
|
||||
// including a cache of existing instantiations.
|
||||
type generic struct {
|
||||
instancesMu sync.Mutex
|
||||
instances map[*typeList]*Function // canonical type arguments to an instance.
|
||||
}
|
||||
|
||||
// instance returns a Function that is the instantiation of generic
|
||||
// origin function fn with the type arguments targs.
|
||||
//
|
||||
// Any created instance is added to cr.
|
||||
//
|
||||
// Acquires fn.generic.instancesMu.
|
||||
func (fn *Function) instance(targs []types.Type, b *builder) *Function {
|
||||
key := fn.Prog.canon.List(targs)
|
||||
|
||||
gen := fn.generic
|
||||
|
||||
gen.instancesMu.Lock()
|
||||
defer gen.instancesMu.Unlock()
|
||||
inst, ok := gen.instances[key]
|
||||
if !ok {
|
||||
inst = createInstance(fn, targs)
|
||||
inst.buildshared = b.shared()
|
||||
b.enqueue(inst)
|
||||
|
||||
if gen.instances == nil {
|
||||
gen.instances = make(map[*typeList]*Function)
|
||||
}
|
||||
gen.instances[key] = inst
|
||||
} else {
|
||||
b.waitForSharedFunction(inst)
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
// createInstance returns the instantiation of generic function fn using targs.
|
||||
//
|
||||
// Requires fn.generic.instancesMu.
|
||||
func createInstance(fn *Function, targs []types.Type) *Function {
|
||||
prog := fn.Prog
|
||||
|
||||
// Compute signature.
|
||||
var sig *types.Signature
|
||||
var obj *types.Func
|
||||
if recv := fn.Signature.Recv(); recv != nil {
|
||||
// method
|
||||
obj = prog.canon.instantiateMethod(fn.object, targs, prog.ctxt)
|
||||
sig = obj.Type().(*types.Signature)
|
||||
} else {
|
||||
// function
|
||||
instSig, err := types.Instantiate(prog.ctxt, fn.Signature, targs, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
instance, ok := instSig.(*types.Signature)
|
||||
if !ok {
|
||||
panic("Instantiate of a Signature returned a non-signature")
|
||||
}
|
||||
obj = fn.object // instantiation does not exist yet
|
||||
sig = prog.canon.Type(instance).(*types.Signature)
|
||||
}
|
||||
|
||||
// Choose strategy (instance or wrapper).
|
||||
var (
|
||||
synthetic string
|
||||
subst *subster
|
||||
build buildFunc
|
||||
)
|
||||
if prog.mode&InstantiateGenerics != 0 && !prog.isParameterized(targs...) {
|
||||
synthetic = fmt.Sprintf("instance of %s", fn.Name())
|
||||
if fn.syntax != nil {
|
||||
subst = makeSubster(prog.ctxt, obj, fn.typeparams, targs)
|
||||
build = (*builder).buildFromSyntax
|
||||
} else {
|
||||
build = (*builder).buildParamsOnly
|
||||
}
|
||||
} else {
|
||||
synthetic = fmt.Sprintf("instantiation wrapper of %s", fn.Name())
|
||||
build = (*builder).buildInstantiationWrapper
|
||||
}
|
||||
|
||||
/* generic instance or instantiation wrapper */
|
||||
return &Function{
|
||||
name: fmt.Sprintf("%s%s", fn.Name(), targs), // may not be unique
|
||||
object: obj,
|
||||
Signature: sig,
|
||||
Synthetic: synthetic,
|
||||
syntax: fn.syntax, // \
|
||||
info: fn.info, // } empty for non-created packages
|
||||
goversion: fn.goversion, // /
|
||||
build: build,
|
||||
topLevelOrigin: fn,
|
||||
pos: obj.Pos(),
|
||||
Pkg: nil,
|
||||
Prog: fn.Prog,
|
||||
typeparams: fn.typeparams, // share with origin
|
||||
typeargs: targs,
|
||||
subst: subst,
|
||||
}
|
||||
}
|
||||
|
||||
// isParameterized reports whether any of the specified types contains
|
||||
// a free type parameter. It is safe to call concurrently.
|
||||
func (prog *Program) isParameterized(ts ...types.Type) bool {
|
||||
prog.hasParamsMu.Lock()
|
||||
defer prog.hasParamsMu.Unlock()
|
||||
|
||||
// TODO(adonovan): profile. If this operation is expensive,
|
||||
// handle the most common but shallow cases such as T, pkg.T,
|
||||
// *T without consulting the cache under the lock.
|
||||
|
||||
return slices.ContainsFunc(ts, prog.hasParams.Has)
|
||||
}
|
||||
Reference in New Issue
Block a user