Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.0.1-2020.1.5 / go / types / typeutil / identical.go
1 package typeutil
2
3 import (
4         "go/types"
5 )
6
7 // Identical reports whether x and y are identical types.
8 // Unlike types.Identical, receivers of Signature types are not ignored.
9 // Unlike types.Identical, interfaces are compared via pointer equality (except for the empty interface, which gets deduplicated).
10 // Unlike types.Identical, structs are compared via pointer equality.
11 func Identical(x, y types.Type) (ret bool) {
12         if !types.Identical(x, y) {
13                 return false
14         }
15
16         switch x := x.(type) {
17         case *types.Struct:
18                 y, ok := y.(*types.Struct)
19                 if !ok {
20                         // should be impossible
21                         return true
22                 }
23                 return x == y
24         case *types.Interface:
25                 // The issue with interfaces, typeutil.Map and types.Identical
26                 //
27                 // types.Identical, when comparing two interfaces, only looks at the set
28                 // of all methods, not differentiating between implicit (embedded) and
29                 // explicit methods.
30                 //
31                 // When we see the following two types, in source order
32                 //
33                 // type I1 interface { foo() }
34                 // type I2 interface { I1 }
35                 //
36                 // then we will first correctly process I1 and its underlying type. When
37                 // we get to I2, we will see that its underlying type is identical to
38                 // that of I1 and not process it again. This, however, means that we will
39                 // not record the fact that I2 embeds I1. If only I2 is reachable via the
40                 // graph root, then I1 will not be considered used.
41                 //
42                 // We choose to be lazy and compare interfaces by their
43                 // pointers. This will obviously miss identical interfaces,
44                 // but this only has a runtime cost, it doesn't affect
45                 // correctness.
46                 y, ok := y.(*types.Interface)
47                 if !ok {
48                         // should be impossible
49                         return true
50                 }
51                 if x.NumEmbeddeds() == 0 &&
52                         y.NumEmbeddeds() == 0 &&
53                         x.NumMethods() == 0 &&
54                         y.NumMethods() == 0 {
55                         // all truly empty interfaces are the same
56                         return true
57                 }
58                 return x == y
59         case *types.Signature:
60                 y, ok := y.(*types.Signature)
61                 if !ok {
62                         // should be impossible
63                         return true
64                 }
65                 if x.Recv() == y.Recv() {
66                         return true
67                 }
68                 if x.Recv() == nil || y.Recv() == nil {
69                         return false
70                 }
71                 return Identical(x.Recv().Type(), y.Recv().Type())
72         default:
73                 return true
74         }
75 }