.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / go / ssa / methods.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/go/ssa/methods.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/go/ssa/methods.go
new file mode 100644 (file)
index 0000000..9cf3839
--- /dev/null
@@ -0,0 +1,239 @@
+// 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 utilities for population of method sets.
+
+import (
+       "fmt"
+       "go/types"
+)
+
+// MethodValue returns the Function implementing method sel, building
+// wrapper methods on demand.  It returns nil if sel denotes an
+// abstract (interface) method.
+//
+// Precondition: sel.Kind() == MethodVal.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) MethodValue(sel *types.Selection) *Function {
+       if sel.Kind() != types.MethodVal {
+               panic(fmt.Sprintf("MethodValue(%s) kind != MethodVal", sel))
+       }
+       T := sel.Recv()
+       if isInterface(T) {
+               return nil // abstract method
+       }
+       if prog.mode&LogSource != 0 {
+               defer logStack("MethodValue %s %v", T, sel)()
+       }
+
+       prog.methodsMu.Lock()
+       defer prog.methodsMu.Unlock()
+
+       return prog.addMethod(prog.createMethodSet(T), sel)
+}
+
+// LookupMethod returns the implementation of the method of type T
+// identified by (pkg, name).  It returns nil if the method exists but
+// is abstract, and panics if T has no such method.
+//
+func (prog *Program) LookupMethod(T types.Type, pkg *types.Package, name string) *Function {
+       sel := prog.MethodSets.MethodSet(T).Lookup(pkg, name)
+       if sel == nil {
+               panic(fmt.Sprintf("%s has no method %s", T, types.Id(pkg, name)))
+       }
+       return prog.MethodValue(sel)
+}
+
+// methodSet contains the (concrete) methods of a non-interface type.
+type methodSet struct {
+       mapping  map[string]*Function // populated lazily
+       complete bool                 // mapping contains all methods
+}
+
+// Precondition: !isInterface(T).
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) createMethodSet(T types.Type) *methodSet {
+       mset, ok := prog.methodSets.At(T).(*methodSet)
+       if !ok {
+               mset = &methodSet{mapping: make(map[string]*Function)}
+               prog.methodSets.Set(T, mset)
+       }
+       return mset
+}
+
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+func (prog *Program) addMethod(mset *methodSet, sel *types.Selection) *Function {
+       if sel.Kind() == types.MethodExpr {
+               panic(sel)
+       }
+       id := sel.Obj().Id()
+       fn := mset.mapping[id]
+       if fn == nil {
+               obj := sel.Obj().(*types.Func)
+
+               needsPromotion := len(sel.Index()) > 1
+               needsIndirection := !isPointer(recvType(obj)) && isPointer(sel.Recv())
+               if needsPromotion || needsIndirection {
+                       fn = makeWrapper(prog, sel)
+               } else {
+                       fn = prog.declaredFunc(obj)
+               }
+               if fn.Signature.Recv() == nil {
+                       panic(fn) // missing receiver
+               }
+               mset.mapping[id] = fn
+       }
+       return fn
+}
+
+// RuntimeTypes returns a new unordered slice containing all
+// concrete types in the program for which a complete (non-empty)
+// method set is required at run-time.
+//
+// Thread-safe.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) RuntimeTypes() []types.Type {
+       prog.methodsMu.Lock()
+       defer prog.methodsMu.Unlock()
+
+       var res []types.Type
+       prog.methodSets.Iterate(func(T types.Type, v interface{}) {
+               if v.(*methodSet).complete {
+                       res = append(res, T)
+               }
+       })
+       return res
+}
+
+// declaredFunc returns the concrete function/method denoted by obj.
+// Panic ensues if there is none.
+//
+func (prog *Program) declaredFunc(obj *types.Func) *Function {
+       if v := prog.packageLevelValue(obj); v != nil {
+               return v.(*Function)
+       }
+       panic("no concrete method: " + obj.String())
+}
+
+// needMethodsOf ensures that runtime type information (including the
+// complete method set) is available for the specified type T and all
+// its subcomponents.
+//
+// needMethodsOf must be called for at least every type that is an
+// operand of some MakeInterface instruction, and for the type of
+// every exported package member.
+//
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+//
+// Thread-safe.  (Called via emitConv from multiple builder goroutines.)
+//
+// TODO(adonovan): make this faster.  It accounts for 20% of SSA build time.
+//
+// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
+//
+func (prog *Program) needMethodsOf(T types.Type) {
+       prog.methodsMu.Lock()
+       prog.needMethods(T, false)
+       prog.methodsMu.Unlock()
+}
+
+// Precondition: T is not a method signature (*Signature with Recv()!=nil).
+// Recursive case: skip => don't create methods for T.
+//
+// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
+//
+func (prog *Program) needMethods(T types.Type, skip bool) {
+       // Each package maintains its own set of types it has visited.
+       if prevSkip, ok := prog.runtimeTypes.At(T).(bool); ok {
+               // needMethods(T) was previously called
+               if !prevSkip || skip {
+                       return // already seen, with same or false 'skip' value
+               }
+       }
+       prog.runtimeTypes.Set(T, skip)
+
+       tmset := prog.MethodSets.MethodSet(T)
+
+       if !skip && !isInterface(T) && tmset.Len() > 0 {
+               // Create methods of T.
+               mset := prog.createMethodSet(T)
+               if !mset.complete {
+                       mset.complete = true
+                       n := tmset.Len()
+                       for i := 0; i < n; i++ {
+                               prog.addMethod(mset, tmset.At(i))
+                       }
+               }
+       }
+
+       // Recursion over signatures of each method.
+       for i := 0; i < tmset.Len(); i++ {
+               sig := tmset.At(i).Type().(*types.Signature)
+               prog.needMethods(sig.Params(), false)
+               prog.needMethods(sig.Results(), false)
+       }
+
+       switch t := T.(type) {
+       case *types.Basic:
+               // nop
+
+       case *types.Interface:
+               // nop---handled by recursion over method set.
+
+       case *types.Pointer:
+               prog.needMethods(t.Elem(), false)
+
+       case *types.Slice:
+               prog.needMethods(t.Elem(), false)
+
+       case *types.Chan:
+               prog.needMethods(t.Elem(), false)
+
+       case *types.Map:
+               prog.needMethods(t.Key(), false)
+               prog.needMethods(t.Elem(), false)
+
+       case *types.Signature:
+               if t.Recv() != nil {
+                       panic(fmt.Sprintf("Signature %s has Recv %s", t, t.Recv()))
+               }
+               prog.needMethods(t.Params(), false)
+               prog.needMethods(t.Results(), false)
+
+       case *types.Named:
+               // A pointer-to-named type can be derived from a named
+               // type via reflection.  It may have methods too.
+               prog.needMethods(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.
+               prog.needMethods(t.Underlying(), true)
+
+       case *types.Array:
+               prog.needMethods(t.Elem(), false)
+
+       case *types.Struct:
+               for i, n := 0, t.NumFields(); i < n; i++ {
+                       prog.needMethods(t.Field(i).Type(), false)
+               }
+
+       case *types.Tuple:
+               for i, n := 0, t.Len(); i < n; i++ {
+                       prog.needMethods(t.At(i).Type(), false)
+               }
+
+       default:
+               panic(T)
+       }
+}