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) {
16 switch x := x.(type) {
18 y, ok := y.(*types.Struct)
20 // should be impossible
24 case *types.Interface:
25 // The issue with interfaces, typeutil.Map and types.Identical
27 // types.Identical, when comparing two interfaces, only looks at the set
28 // of all methods, not differentiating between implicit (embedded) and
31 // When we see the following two types, in source order
33 // type I1 interface { foo() }
34 // type I2 interface { I1 }
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.
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
46 y, ok := y.(*types.Interface)
48 // should be impossible
51 if x.NumEmbeddeds() == 0 &&
52 y.NumEmbeddeds() == 0 &&
53 x.NumMethods() == 0 &&
55 // all truly empty interfaces are the same
59 case *types.Signature:
60 y, ok := y.(*types.Signature)
62 // should be impossible
65 if x.Recv() == y.Recv() {
68 if x.Recv() == nil || y.Recv() == nil {
71 return Identical(x.Recv().Type(), y.Recv().Type())