@@ -22,30 +22,24 @@ func isBytestring(T types.Type) bool {
2222 return false
2323 }
2424
25- tset := typeSetOf (U )
26- if tset .Len () != 2 {
27- return false
28- }
2925 hasBytes , hasString := false , false
30- underIs (tset , func (t types.Type ) bool {
26+ ok := underIs (U , func (t types.Type ) bool {
3127 switch {
3228 case isString (t ):
3329 hasString = true
30+ return true
3431 case isByteSlice (t ):
3532 hasBytes = true
33+ return true
34+ default :
35+ return false
3636 }
37- return hasBytes || hasString
3837 })
39- return hasBytes && hasString
38+ return ok && hasBytes && hasString
4039}
4140
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 {
4943 // This is a adaptation of x/exp/typeparams.NormalTerms which x/tools cannot depend on.
5044 var terms []* types.Term
5145 var err error
@@ -65,20 +59,21 @@ func typeSetOf(typ types.Type) termList {
6559 }
6660
6761 if err != nil {
68- return termList ( nil )
62+ return nil
6963 }
70- return termList ( terms )
64+ return terms
7165}
7266
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 {
7873 return f (nil )
7974 }
80- for i := 0 ; i < s . Len (); i ++ {
81- u := s . At ( i ).Underlying ()
75+ for _ , t := range s {
76+ u := t . Type ( ).Underlying ()
8277 if ! f (u ) {
8378 return false
8479 }
@@ -87,7 +82,7 @@ func underIs(s termList, f func(types.Type) bool) bool {
8782}
8883
8984// 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.
9186func indexType (typ types.Type ) (types.Type , indexMode ) {
9287 switch U := typ .Underlying ().(type ) {
9388 case * types.Array :
@@ -104,22 +99,22 @@ func indexType(typ types.Type) (types.Type, indexMode) {
10499 return tByte , ixValue // must be a string
105100 case * types.Interface :
106101 tset := typeSetOf (U )
107- if tset . Len ( ) == 0 {
102+ if len ( tset ) == 0 {
108103 return nil , ixInvalid // no underlying terms or error is empty.
109104 }
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 ())
114108 if ! types .Identical (elem , e ) { // if type checked, just a sanity check
115109 return nil , ixInvalid
116110 }
117111 // Update the mode to the most constrained address type.
118112 mode = mode .meet (m )
113+ if mode == ixInvalid {
114+ return nil , ixInvalid // fast exit
115+ }
119116 }
120- if mode != ixInvalid {
121- return elem , mode
122- }
117+ return elem , mode
123118 }
124119 return nil , ixInvalid
125120}
0 commit comments