@@ -22,30 +22,24 @@ func isBytestring(T types.Type) bool {
22
22
return false
23
23
}
24
24
25
- tset := typeSetOf (U )
26
- if tset .Len () != 2 {
27
- return false
28
- }
29
25
hasBytes , hasString := false , false
30
- underIs (tset , func (t types.Type ) bool {
26
+ ok := underIs (U , func (t types.Type ) bool {
31
27
switch {
32
28
case isString (t ):
33
29
hasString = true
30
+ return true
34
31
case isByteSlice (t ):
35
32
hasBytes = true
33
+ return true
34
+ default :
35
+ return false
36
36
}
37
- return hasBytes || hasString
38
37
})
39
- return hasBytes && hasString
38
+ return ok && hasBytes && hasString
40
39
}
41
40
42
- // termList is a list of types.
43
- type termList []* types.Term // type terms of the type set
44
- func (s termList ) Len () int { return len (s ) }
45
- func (s termList ) At (i int ) types.Type { return s [i ].Type () }
46
-
47
- // typeSetOf returns the type set of typ. Returns an empty typeset on an error.
48
- func typeSetOf (typ types.Type ) termList {
41
+ // typeSetOf returns the type set of typ as a normalized term set. Returns an empty set on an error.
42
+ func typeSetOf (typ types.Type ) []* types.Term {
49
43
// This is a adaptation of x/exp/typeparams.NormalTerms which x/tools cannot depend on.
50
44
var terms []* types.Term
51
45
var err error
@@ -65,20 +59,21 @@ func typeSetOf(typ types.Type) termList {
65
59
}
66
60
67
61
if err != nil {
68
- return termList ( nil )
62
+ return nil
69
63
}
70
- return termList ( terms )
64
+ return terms
71
65
}
72
66
73
- // underIs calls f with the underlying types of the specific type terms
74
- // of s and reports whether all calls to f returned true. If there are
75
- // no specific terms, underIs returns the result of f(nil).
76
- func underIs (s termList , f func (types.Type ) bool ) bool {
77
- if s .Len () == 0 {
67
+ // underIs calls f with the underlying types of the type terms
68
+ // of the type set of typ and reports whether all calls to f returned true.
69
+ // If there are no specific terms, underIs returns the result of f(nil).
70
+ func underIs (typ types.Type , f func (types.Type ) bool ) bool {
71
+ s := typeSetOf (typ )
72
+ if len (s ) == 0 {
78
73
return f (nil )
79
74
}
80
- for i := 0 ; i < s . Len (); i ++ {
81
- u := s . At ( i ).Underlying ()
75
+ for _ , t := range s {
76
+ u := t . Type ( ).Underlying ()
82
77
if ! f (u ) {
83
78
return false
84
79
}
@@ -87,7 +82,7 @@ func underIs(s termList, f func(types.Type) bool) bool {
87
82
}
88
83
89
84
// indexType returns the element type and index mode of a IndexExpr over a type.
90
- // It returns (nil, invalid) if the type is not indexable; this should never occur in a well-typed program.
85
+ // It returns an invalid mode if the type is not indexable; this should never occur in a well-typed program.
91
86
func indexType (typ types.Type ) (types.Type , indexMode ) {
92
87
switch U := typ .Underlying ().(type ) {
93
88
case * types.Array :
@@ -104,22 +99,22 @@ func indexType(typ types.Type) (types.Type, indexMode) {
104
99
return tByte , ixValue // must be a string
105
100
case * types.Interface :
106
101
tset := typeSetOf (U )
107
- if tset . Len ( ) == 0 {
102
+ if len ( tset ) == 0 {
108
103
return nil , ixInvalid // no underlying terms or error is empty.
109
104
}
110
-
111
- elem , mode := indexType (tset .At (0 ))
112
- for i := 1 ; i < tset .Len () && mode != ixInvalid ; i ++ {
113
- e , m := indexType (tset .At (i ))
105
+ elem , mode := indexType (tset [0 ].Type ())
106
+ for _ , t := range tset [1 :] {
107
+ e , m := indexType (t .Type ())
114
108
if ! types .Identical (elem , e ) { // if type checked, just a sanity check
115
109
return nil , ixInvalid
116
110
}
117
111
// Update the mode to the most constrained address type.
118
112
mode = mode .meet (m )
113
+ if mode == ixInvalid {
114
+ return nil , ixInvalid // fast exit
115
+ }
119
116
}
120
- if mode != ixInvalid {
121
- return elem , mode
122
- }
117
+ return elem , mode
123
118
}
124
119
return nil , ixInvalid
125
120
}
0 commit comments