summaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/tools/go/ssa/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/tools/go/ssa/util.go')
-rw-r--r--vendor/golang.org/x/tools/go/ssa/util.go430
1 files changed, 0 insertions, 430 deletions
diff --git a/vendor/golang.org/x/tools/go/ssa/util.go b/vendor/golang.org/x/tools/go/ssa/util.go
deleted file mode 100644
index 549c9c8..0000000
--- a/vendor/golang.org/x/tools/go/ssa/util.go
+++ /dev/null
@@ -1,430 +0,0 @@
-// Copyright 2013 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
-
-// This file defines a number of miscellaneous utility functions.
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "go/types"
- "io"
- "os"
- "sync"
-
- "golang.org/x/tools/go/ast/astutil"
- "golang.org/x/tools/go/types/typeutil"
- "golang.org/x/tools/internal/aliases"
- "golang.org/x/tools/internal/typeparams"
- "golang.org/x/tools/internal/typesinternal"
-)
-
-type unit struct{}
-
-//// Sanity checking utilities
-
-// assert panics with the mesage msg if p is false.
-// Avoid combining with expensive string formatting.
-func assert(p bool, msg string) {
- if !p {
- panic(msg)
- }
-}
-
-//// AST utilities
-
-func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
-
-// isBlankIdent returns true iff e is an Ident with name "_".
-// They have no associated types.Object, and thus no type.
-func isBlankIdent(e ast.Expr) bool {
- id, ok := e.(*ast.Ident)
- return ok && id.Name == "_"
-}
-
-// rangePosition is the position to give for the `range` token in a RangeStmt.
-var rangePosition = func(rng *ast.RangeStmt) token.Pos {
- // Before 1.20, this is unreachable.
- // rng.For is a close, but incorrect position.
- return rng.For
-}
-
-//// Type utilities. Some of these belong in go/types.
-
-// isNonTypeParamInterface reports whether t is an interface type but not a type parameter.
-func isNonTypeParamInterface(t types.Type) bool {
- return !typeparams.IsTypeParam(t) && types.IsInterface(t)
-}
-
-// isBasic reports whether t is a basic type.
-// t is assumed to be an Underlying type (not Named or Alias).
-func isBasic(t types.Type) bool {
- _, ok := t.(*types.Basic)
- return ok
-}
-
-// isString reports whether t is exactly a string type.
-// t is assumed to be an Underlying type (not Named or Alias).
-func isString(t types.Type) bool {
- basic, ok := t.(*types.Basic)
- return ok && basic.Info()&types.IsString != 0
-}
-
-// isByteSlice reports whether t is of the form []~bytes.
-// t is assumed to be an Underlying type (not Named or Alias).
-func isByteSlice(t types.Type) bool {
- if b, ok := t.(*types.Slice); ok {
- e, _ := b.Elem().Underlying().(*types.Basic)
- return e != nil && e.Kind() == types.Byte
- }
- return false
-}
-
-// isRuneSlice reports whether t is of the form []~runes.
-// t is assumed to be an Underlying type (not Named or Alias).
-func isRuneSlice(t types.Type) bool {
- if b, ok := t.(*types.Slice); ok {
- e, _ := b.Elem().Underlying().(*types.Basic)
- return e != nil && e.Kind() == types.Rune
- }
- return false
-}
-
-// isBasicConvTypes returns true when a type set can be
-// one side of a Convert operation. This is when:
-// - All are basic, []byte, or []rune.
-// - At least 1 is basic.
-// - At most 1 is []byte or []rune.
-func isBasicConvTypes(tset termList) bool {
- basics := 0
- all := underIs(tset, func(t types.Type) bool {
- if isBasic(t) {
- basics++
- return true
- }
- return isByteSlice(t) || isRuneSlice(t)
- })
- return all && basics >= 1 && tset.Len()-basics <= 1
-}
-
-// isPointer reports whether t's underlying type is a pointer.
-func isPointer(t types.Type) bool {
- return is[*types.Pointer](t.Underlying())
-}
-
-// isPointerCore reports whether t's core type is a pointer.
-//
-// (Most pointer manipulation is related to receivers, in which case
-// isPointer is appropriate. tecallers can use isPointer(t).
-func isPointerCore(t types.Type) bool {
- return is[*types.Pointer](typeparams.CoreType(t))
-}
-
-func is[T any](x any) bool {
- _, ok := x.(T)
- return ok
-}
-
-// recvType returns the receiver type of method obj.
-func recvType(obj *types.Func) types.Type {
- return obj.Type().(*types.Signature).Recv().Type()
-}
-
-// fieldOf returns the index'th field of the (core type of) a struct type;
-// otherwise returns nil.
-func fieldOf(typ types.Type, index int) *types.Var {
- if st, ok := typeparams.CoreType(typ).(*types.Struct); ok {
- if 0 <= index && index < st.NumFields() {
- return st.Field(index)
- }
- }
- return nil
-}
-
-// isUntyped reports whether typ is the type of an untyped constant.
-func isUntyped(typ types.Type) bool {
- // No Underlying/Unalias: untyped constant types cannot be Named or Alias.
- b, ok := typ.(*types.Basic)
- return ok && b.Info()&types.IsUntyped != 0
-}
-
-// declaredWithin reports whether an object is declared within a function.
-//
-// obj must not be a method or a field.
-func declaredWithin(obj types.Object, fn *types.Func) bool {
- if obj.Pos() != token.NoPos {
- return fn.Scope().Contains(obj.Pos()) // trust the positions if they exist.
- }
- if fn.Pkg() != obj.Pkg() {
- return false // fast path for different packages
- }
-
- // Traverse Parent() scopes for fn.Scope().
- for p := obj.Parent(); p != nil; p = p.Parent() {
- if p == fn.Scope() {
- return true
- }
- }
- return false
-}
-
-// logStack prints the formatted "start" message to stderr and
-// returns a closure that prints the corresponding "end" message.
-// Call using 'defer logStack(...)()' to show builder stack on panic.
-// Don't forget trailing parens!
-func logStack(format string, args ...interface{}) func() {
- msg := fmt.Sprintf(format, args...)
- io.WriteString(os.Stderr, msg)
- io.WriteString(os.Stderr, "\n")
- return func() {
- io.WriteString(os.Stderr, msg)
- io.WriteString(os.Stderr, " end\n")
- }
-}
-
-// newVar creates a 'var' for use in a types.Tuple.
-func newVar(name string, typ types.Type) *types.Var {
- return types.NewParam(token.NoPos, nil, name, typ)
-}
-
-// anonVar creates an anonymous 'var' for use in a types.Tuple.
-func anonVar(typ types.Type) *types.Var {
- return newVar("", typ)
-}
-
-var lenResults = types.NewTuple(anonVar(tInt))
-
-// makeLen returns the len builtin specialized to type func(T)int.
-func makeLen(T types.Type) *Builtin {
- lenParams := types.NewTuple(anonVar(T))
- return &Builtin{
- name: "len",
- sig: types.NewSignature(nil, lenParams, lenResults, false),
- }
-}
-
-// receiverTypeArgs returns the type arguments to a method's receiver.
-// Returns an empty list if the receiver does not have type arguments.
-func receiverTypeArgs(method *types.Func) []types.Type {
- recv := method.Type().(*types.Signature).Recv()
- _, named := typesinternal.ReceiverNamed(recv)
- if named == nil {
- return nil // recv is anonymous struct/interface
- }
- ts := named.TypeArgs()
- if ts.Len() == 0 {
- return nil
- }
- targs := make([]types.Type, ts.Len())
- for i := 0; i < ts.Len(); i++ {
- targs[i] = ts.At(i)
- }
- return targs
-}
-
-// recvAsFirstArg takes a method signature and returns a function
-// signature with receiver as the first parameter.
-func recvAsFirstArg(sig *types.Signature) *types.Signature {
- params := make([]*types.Var, 0, 1+sig.Params().Len())
- params = append(params, sig.Recv())
- for i := 0; i < sig.Params().Len(); i++ {
- params = append(params, sig.Params().At(i))
- }
- return types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
-}
-
-// instance returns whether an expression is a simple or qualified identifier
-// that is a generic instantiation.
-func instance(info *types.Info, expr ast.Expr) bool {
- // Compare the logic here against go/types.instantiatedIdent,
- // which also handles *IndexExpr and *IndexListExpr.
- var id *ast.Ident
- switch x := expr.(type) {
- case *ast.Ident:
- id = x
- case *ast.SelectorExpr:
- id = x.Sel
- default:
- return false
- }
- _, ok := info.Instances[id]
- return ok
-}
-
-// instanceArgs returns the Instance[id].TypeArgs as a slice.
-func instanceArgs(info *types.Info, id *ast.Ident) []types.Type {
- targList := info.Instances[id].TypeArgs
- if targList == nil {
- return nil
- }
-
- targs := make([]types.Type, targList.Len())
- for i, n := 0, targList.Len(); i < n; i++ {
- targs[i] = targList.At(i)
- }
- return targs
-}
-
-// Mapping of a type T to a canonical instance C s.t. types.Indentical(T, C).
-// Thread-safe.
-type canonizer struct {
- mu sync.Mutex
- types typeutil.Map // map from type to a canonical instance
- lists typeListMap // map from a list of types to a canonical instance
-}
-
-func newCanonizer() *canonizer {
- c := &canonizer{}
- h := typeutil.MakeHasher()
- c.types.SetHasher(h)
- c.lists.hasher = h
- return c
-}
-
-// List returns a canonical representative of a list of types.
-// Representative of the empty list is nil.
-func (c *canonizer) List(ts []types.Type) *typeList {
- if len(ts) == 0 {
- return nil
- }
-
- unaliasAll := func(ts []types.Type) []types.Type {
- // Is there some top level alias?
- var found bool
- for _, t := range ts {
- if _, ok := t.(*aliases.Alias); ok {
- found = true
- break
- }
- }
- if !found {
- return ts // no top level alias
- }
-
- cp := make([]types.Type, len(ts)) // copy with top level aliases removed.
- for i, t := range ts {
- cp[i] = aliases.Unalias(t)
- }
- return cp
- }
- l := unaliasAll(ts)
-
- c.mu.Lock()
- defer c.mu.Unlock()
- return c.lists.rep(l)
-}
-
-// Type returns a canonical representative of type T.
-// Removes top-level aliases.
-//
-// For performance, reasons the canonical instance is order-dependent,
-// and may contain deeply nested aliases.
-func (c *canonizer) Type(T types.Type) types.Type {
- T = aliases.Unalias(T) // remove the top level alias.
-
- c.mu.Lock()
- defer c.mu.Unlock()
-
- if r := c.types.At(T); r != nil {
- return r.(types.Type)
- }
- c.types.Set(T, T)
- return T
-}
-
-// A type for representing a canonized list of types.
-type typeList []types.Type
-
-func (l *typeList) identical(ts []types.Type) bool {
- if l == nil {
- return len(ts) == 0
- }
- n := len(*l)
- if len(ts) != n {
- return false
- }
- for i, left := range *l {
- right := ts[i]
- if !types.Identical(left, right) {
- return false
- }
- }
- return true
-}
-
-type typeListMap struct {
- hasher typeutil.Hasher
- buckets map[uint32][]*typeList
-}
-
-// rep returns a canonical representative of a slice of types.
-func (m *typeListMap) rep(ts []types.Type) *typeList {
- if m == nil || len(ts) == 0 {
- return nil
- }
-
- if m.buckets == nil {
- m.buckets = make(map[uint32][]*typeList)
- }
-
- h := m.hash(ts)
- bucket := m.buckets[h]
- for _, l := range bucket {
- if l.identical(ts) {
- return l
- }
- }
-
- // not present. create a representative.
- cp := make(typeList, len(ts))
- copy(cp, ts)
- rep := &cp
-
- m.buckets[h] = append(bucket, rep)
- return rep
-}
-
-func (m *typeListMap) hash(ts []types.Type) uint32 {
- if m == nil {
- return 0
- }
- // Some smallish prime far away from typeutil.Hash.
- n := len(ts)
- h := uint32(13619) + 2*uint32(n)
- for i := 0; i < n; i++ {
- h += 3 * m.hasher.Hash(ts[i])
- }
- return h
-}
-
-// instantiateMethod instantiates m with targs and returns a canonical representative for this method.
-func (canon *canonizer) instantiateMethod(m *types.Func, targs []types.Type, ctxt *types.Context) *types.Func {
- recv := recvType(m)
- if p, ok := aliases.Unalias(recv).(*types.Pointer); ok {
- recv = p.Elem()
- }
- named := aliases.Unalias(recv).(*types.Named)
- inst, err := types.Instantiate(ctxt, named.Origin(), targs, false)
- if err != nil {
- panic(err)
- }
- rep := canon.Type(inst)
- obj, _, _ := types.LookupFieldOrMethod(rep, true, m.Pkg(), m.Name())
- return obj.(*types.Func)
-}
-
-// Exposed to ssautil using the linkname hack.
-func isSyntactic(pkg *Package) bool { return pkg.syntax }
-
-// mapValues returns a new unordered array of map values.
-func mapValues[K comparable, V any](m map[K]V) []V {
- vals := make([]V, 0, len(m))
- for _, fn := range m {
- vals = append(vals, fn)
- }
- return vals
-
-}