...
1
2
3
4
5 package ssa
6
7 import (
8 "go/types"
9
10 "golang.org/x/tools/internal/typeparams"
11 )
12
13
14
15
16
17
18
19 func isBytestring(T types.Type) bool {
20 U := T.Underlying()
21 if _, ok := U.(*types.Interface); !ok {
22 return false
23 }
24
25 tset := typeSetOf(U)
26 if tset.Len() != 2 {
27 return false
28 }
29 hasBytes, hasString := false, false
30 underIs(tset, func(t types.Type) bool {
31 switch {
32 case isString(t):
33 hasString = true
34 case isByteSlice(t):
35 hasBytes = true
36 }
37 return hasBytes || hasString
38 })
39 return hasBytes && hasString
40 }
41
42
43 type termList []*typeparams.Term
44 func (s termList) Len() int { return len(s) }
45 func (s termList) At(i int) types.Type { return s[i].Type() }
46
47
48 func typeSetOf(typ types.Type) termList {
49
50 var terms []*typeparams.Term
51 var err error
52 switch typ := typ.(type) {
53 case *typeparams.TypeParam:
54 terms, err = typeparams.StructuralTerms(typ)
55 case *typeparams.Union:
56 terms, err = typeparams.UnionTermSet(typ)
57 case *types.Interface:
58 terms, err = typeparams.InterfaceTermSet(typ)
59 default:
60
61
62
63 terms = []*typeparams.Term{typeparams.NewTerm(false, typ)}
64 }
65
66 if err != nil {
67 return termList(nil)
68 }
69 return termList(terms)
70 }
71
72
73
74
75 func underIs(s termList, f func(types.Type) bool) bool {
76 if s.Len() == 0 {
77 return f(nil)
78 }
79 for i := 0; i < s.Len(); i++ {
80 u := s.At(i).Underlying()
81 if !f(u) {
82 return false
83 }
84 }
85 return true
86 }
87
88
89
90 func indexType(typ types.Type) (types.Type, indexMode) {
91 switch U := typ.Underlying().(type) {
92 case *types.Array:
93 return U.Elem(), ixArrVar
94 case *types.Pointer:
95 if arr, ok := U.Elem().Underlying().(*types.Array); ok {
96 return arr.Elem(), ixVar
97 }
98 case *types.Slice:
99 return U.Elem(), ixVar
100 case *types.Map:
101 return U.Elem(), ixMap
102 case *types.Basic:
103 return tByte, ixValue
104 case *types.Interface:
105 tset := typeSetOf(U)
106 if tset.Len() == 0 {
107 return nil, ixInvalid
108 }
109
110 elem, mode := indexType(tset.At(0))
111 for i := 1; i < tset.Len() && mode != ixInvalid; i++ {
112 e, m := indexType(tset.At(i))
113 if !types.Identical(elem, e) {
114 return nil, ixInvalid
115 }
116
117 mode = mode.meet(m)
118 }
119 if mode != ixInvalid {
120 return elem, mode
121 }
122 }
123 return nil, ixInvalid
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 type indexMode byte
140
141 const (
142 ixInvalid indexMode = iota
143 ixValue
144 ixArrVar
145 ixVar
146 ixMap
147 )
148
149
150 func (x indexMode) meet(y indexMode) indexMode {
151 if (x == ixMap || y == ixMap) && x != y {
152 return ixInvalid
153 }
154
155 if x < y {
156 return y
157 }
158 return x
159 }
160
View as plain text