some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / apidiff / compatibility.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/apidiff/compatibility.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/apidiff/compatibility.go
deleted file mode 100644 (file)
index f78da8f..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-package apidiff
-
-import (
-       "fmt"
-       "go/types"
-       "reflect"
-)
-
-func (d *differ) checkCompatible(otn *types.TypeName, old, new types.Type) {
-       switch old := old.(type) {
-       case *types.Interface:
-               if new, ok := new.(*types.Interface); ok {
-                       d.checkCompatibleInterface(otn, old, new)
-                       return
-               }
-
-       case *types.Struct:
-               if new, ok := new.(*types.Struct); ok {
-                       d.checkCompatibleStruct(otn, old, new)
-                       return
-               }
-
-       case *types.Chan:
-               if new, ok := new.(*types.Chan); ok {
-                       d.checkCompatibleChan(otn, old, new)
-                       return
-               }
-
-       case *types.Basic:
-               if new, ok := new.(*types.Basic); ok {
-                       d.checkCompatibleBasic(otn, old, new)
-                       return
-               }
-
-       case *types.Named:
-               panic("unreachable")
-
-       default:
-               d.checkCorrespondence(otn, "", old, new)
-               return
-
-       }
-       // Here if old and new are different kinds of types.
-       d.typeChanged(otn, "", old, new)
-}
-
-func (d *differ) checkCompatibleChan(otn *types.TypeName, old, new *types.Chan) {
-       d.checkCorrespondence(otn, ", element type", old.Elem(), new.Elem())
-       if old.Dir() != new.Dir() {
-               if new.Dir() == types.SendRecv {
-                       d.compatible(otn, "", "removed direction")
-               } else {
-                       d.incompatible(otn, "", "changed direction")
-               }
-       }
-}
-
-func (d *differ) checkCompatibleBasic(otn *types.TypeName, old, new *types.Basic) {
-       // Certain changes to numeric types are compatible. Approximately, the info must
-       // be the same, and the new values must be a superset of the old.
-       if old.Kind() == new.Kind() {
-               // old and new are identical
-               return
-       }
-       if compatibleBasics[[2]types.BasicKind{old.Kind(), new.Kind()}] {
-               d.compatible(otn, "", "changed from %s to %s", old, new)
-       } else {
-               d.typeChanged(otn, "", old, new)
-       }
-}
-
-// All pairs (old, new) of compatible basic types.
-var compatibleBasics = map[[2]types.BasicKind]bool{
-       {types.Uint8, types.Uint16}:         true,
-       {types.Uint8, types.Uint32}:         true,
-       {types.Uint8, types.Uint}:           true,
-       {types.Uint8, types.Uint64}:         true,
-       {types.Uint16, types.Uint32}:        true,
-       {types.Uint16, types.Uint}:          true,
-       {types.Uint16, types.Uint64}:        true,
-       {types.Uint32, types.Uint}:          true,
-       {types.Uint32, types.Uint64}:        true,
-       {types.Uint, types.Uint64}:          true,
-       {types.Int8, types.Int16}:           true,
-       {types.Int8, types.Int32}:           true,
-       {types.Int8, types.Int}:             true,
-       {types.Int8, types.Int64}:           true,
-       {types.Int16, types.Int32}:          true,
-       {types.Int16, types.Int}:            true,
-       {types.Int16, types.Int64}:          true,
-       {types.Int32, types.Int}:            true,
-       {types.Int32, types.Int64}:          true,
-       {types.Int, types.Int64}:            true,
-       {types.Float32, types.Float64}:      true,
-       {types.Complex64, types.Complex128}: true,
-}
-
-// Interface compatibility:
-// If the old interface has an unexported method, the new interface is compatible
-// if its exported method set is a superset of the old. (Users could not implement,
-// only embed.)
-//
-// If the old interface did not have an unexported method, the new interface is
-// compatible if its exported method set is the same as the old, and it has no
-// unexported methods. (Adding an unexported method makes the interface
-// unimplementable outside the package.)
-//
-// TODO: must also check that if any methods were added or removed, every exposed
-// type in the package that implemented the interface in old still implements it in
-// new. Otherwise external assignments could fail.
-func (d *differ) checkCompatibleInterface(otn *types.TypeName, old, new *types.Interface) {
-       // Method sets are checked in checkCompatibleDefined.
-
-       // Does the old interface have an unexported method?
-       if unexportedMethod(old) != nil {
-               d.checkMethodSet(otn, old, new, additionsCompatible)
-       } else {
-               // Perform an equivalence check, but with more information.
-               d.checkMethodSet(otn, old, new, additionsIncompatible)
-               if u := unexportedMethod(new); u != nil {
-                       d.incompatible(otn, u.Name(), "added unexported method")
-               }
-       }
-}
-
-// Return an unexported method from the method set of t, or nil if there are none.
-func unexportedMethod(t *types.Interface) *types.Func {
-       for i := 0; i < t.NumMethods(); i++ {
-               if m := t.Method(i); !m.Exported() {
-                       return m
-               }
-       }
-       return nil
-}
-
-// We need to check three things for structs:
-// 1. The set of exported fields must be compatible. This ensures that keyed struct
-//    literals continue to compile. (There is no compatibility guarantee for unkeyed
-//    struct literals.)
-// 2. The set of exported *selectable* fields must be compatible. This includes the exported
-//    fields of all embedded structs. This ensures that selections continue to compile.
-// 3. If the old struct is comparable, so must the new one be. This ensures that equality
-//    expressions and uses of struct values as map keys continue to compile.
-//
-// An unexported embedded struct can't appear in a struct literal outside the
-// package, so it doesn't have to be present, or have the same name, in the new
-// struct.
-//
-// Field tags are ignored: they have no compile-time implications.
-func (d *differ) checkCompatibleStruct(obj types.Object, old, new *types.Struct) {
-       d.checkCompatibleObjectSets(obj, exportedFields(old), exportedFields(new))
-       d.checkCompatibleObjectSets(obj, exportedSelectableFields(old), exportedSelectableFields(new))
-       // Removing comparability from a struct is an incompatible change.
-       if types.Comparable(old) && !types.Comparable(new) {
-               d.incompatible(obj, "", "old is comparable, new is not")
-       }
-}
-
-// exportedFields collects all the immediate fields of the struct that are exported.
-// This is also the set of exported keys for keyed struct literals.
-func exportedFields(s *types.Struct) map[string]types.Object {
-       m := map[string]types.Object{}
-       for i := 0; i < s.NumFields(); i++ {
-               f := s.Field(i)
-               if f.Exported() {
-                       m[f.Name()] = f
-               }
-       }
-       return m
-}
-
-// exportedSelectableFields collects all the exported fields of the struct, including
-// exported fields of embedded structs.
-//
-// We traverse the struct breadth-first, because of the rule that a lower-depth field
-// shadows one at a higher depth.
-func exportedSelectableFields(s *types.Struct) map[string]types.Object {
-       var (
-               m    = map[string]types.Object{}
-               next []*types.Struct // embedded structs at the next depth
-               seen []*types.Struct // to handle recursive embedding
-       )
-       for cur := []*types.Struct{s}; len(cur) > 0; cur, next = next, nil {
-               seen = append(seen, cur...)
-               // We only want to consider unambiguous fields. Ambiguous fields (where there
-               // is more than one field of the same name at the same level) are legal, but
-               // cannot be selected.
-               for name, f := range unambiguousFields(cur) {
-                       // Record an exported field we haven't seen before. If we have seen it,
-                       // it occurred a lower depth, so it shadows this field.
-                       if f.Exported() && m[name] == nil {
-                               m[name] = f
-                       }
-                       // Remember embedded structs for processing at the next depth,
-                       // but only if we haven't seen the struct at this depth or above.
-                       if !f.Anonymous() {
-                               continue
-                       }
-                       t := f.Type().Underlying()
-                       if p, ok := t.(*types.Pointer); ok {
-                               t = p.Elem().Underlying()
-                       }
-                       if t, ok := t.(*types.Struct); ok && !contains(seen, t) {
-                               next = append(next, t)
-                       }
-               }
-       }
-       return m
-}
-
-func contains(ts []*types.Struct, t *types.Struct) bool {
-       for _, s := range ts {
-               if types.Identical(s, t) {
-                       return true
-               }
-       }
-       return false
-}
-
-// Given a set of structs at the same depth, the unambiguous fields are the ones whose
-// names appear exactly once.
-func unambiguousFields(structs []*types.Struct) map[string]*types.Var {
-       fields := map[string]*types.Var{}
-       seen := map[string]bool{}
-       for _, s := range structs {
-               for i := 0; i < s.NumFields(); i++ {
-                       f := s.Field(i)
-                       name := f.Name()
-                       if seen[name] {
-                               delete(fields, name)
-                       } else {
-                               seen[name] = true
-                               fields[name] = f
-                       }
-               }
-       }
-       return fields
-}
-
-// Anything removed or change from the old set is an incompatible change.
-// Anything added to the new set is a compatible change.
-func (d *differ) checkCompatibleObjectSets(obj types.Object, old, new map[string]types.Object) {
-       for name, oldo := range old {
-               newo := new[name]
-               if newo == nil {
-                       d.incompatible(obj, name, "removed")
-               } else {
-                       d.checkCorrespondence(obj, name, oldo.Type(), newo.Type())
-               }
-       }
-       for name := range new {
-               if old[name] == nil {
-                       d.compatible(obj, name, "added")
-               }
-       }
-}
-
-func (d *differ) checkCompatibleDefined(otn *types.TypeName, old *types.Named, new types.Type) {
-       // We've already checked that old and new correspond.
-       d.checkCompatible(otn, old.Underlying(), new.Underlying())
-       // If there are different kinds of types (e.g. struct and interface), don't bother checking
-       // the method sets.
-       if reflect.TypeOf(old.Underlying()) != reflect.TypeOf(new.Underlying()) {
-               return
-       }
-       // Interface method sets are checked in checkCompatibleInterface.
-       if _, ok := old.Underlying().(*types.Interface); ok {
-               return
-       }
-
-       // A new method set is compatible with an old if the new exported methods are a superset of the old.
-       d.checkMethodSet(otn, old, new, additionsCompatible)
-       d.checkMethodSet(otn, types.NewPointer(old), types.NewPointer(new), additionsCompatible)
-}
-
-const (
-       additionsCompatible   = true
-       additionsIncompatible = false
-)
-
-func (d *differ) checkMethodSet(otn *types.TypeName, oldt, newt types.Type, addcompat bool) {
-       // TODO: find a way to use checkCompatibleObjectSets for this.
-       oldMethodSet := exportedMethods(oldt)
-       newMethodSet := exportedMethods(newt)
-       msname := otn.Name()
-       if _, ok := oldt.(*types.Pointer); ok {
-               msname = "*" + msname
-       }
-       for name, oldMethod := range oldMethodSet {
-               newMethod := newMethodSet[name]
-               if newMethod == nil {
-                       var part string
-                       // Due to embedding, it's possible that the method's receiver type is not
-                       // the same as the defined type whose method set we're looking at. So for
-                       // a type T with removed method M that is embedded in some other type U,
-                       // we will generate two "removed" messages for T.M, one for its own type
-                       // T and one for the embedded type U. We want both messages to appear,
-                       // but the messageSet dedup logic will allow only one message for a given
-                       // object. So use the part string to distinguish them.
-                       if receiverNamedType(oldMethod).Obj() != otn {
-                               part = fmt.Sprintf(", method set of %s", msname)
-                       }
-                       d.incompatible(oldMethod, part, "removed")
-               } else {
-                       obj := oldMethod
-                       // If a value method is changed to a pointer method and has a signature
-                       // change, then we can get two messages for the same method definition: one
-                       // for the value method set that says it's removed, and another for the
-                       // pointer method set that says it changed. To keep both messages (since
-                       // messageSet dedups), use newMethod for the second. (Slight hack.)
-                       if !hasPointerReceiver(oldMethod) && hasPointerReceiver(newMethod) {
-                               obj = newMethod
-                       }
-                       d.checkCorrespondence(obj, "", oldMethod.Type(), newMethod.Type())
-               }
-       }
-
-       // Check for added methods.
-       for name, newMethod := range newMethodSet {
-               if oldMethodSet[name] == nil {
-                       if addcompat {
-                               d.compatible(newMethod, "", "added")
-                       } else {
-                               d.incompatible(newMethod, "", "added")
-                       }
-               }
-       }
-}
-
-// exportedMethods collects all the exported methods of type's method set.
-func exportedMethods(t types.Type) map[string]types.Object {
-       m := map[string]types.Object{}
-       ms := types.NewMethodSet(t)
-       for i := 0; i < ms.Len(); i++ {
-               obj := ms.At(i).Obj()
-               if obj.Exported() {
-                       m[obj.Name()] = obj
-               }
-       }
-       return m
-}
-
-func receiverType(method types.Object) types.Type {
-       return method.Type().(*types.Signature).Recv().Type()
-}
-
-func receiverNamedType(method types.Object) *types.Named {
-       switch t := receiverType(method).(type) {
-       case *types.Pointer:
-               return t.Elem().(*types.Named)
-       case *types.Named:
-               return t
-       default:
-               panic("unreachable")
-       }
-}
-
-func hasPointerReceiver(method types.Object) bool {
-       _, ok := receiverType(method).(*types.Pointer)
-       return ok
-}