Source file src/go/types/under.go
1 // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT. 2 // Source: ../../cmd/compile/internal/types2/under.go 3 4 // Copyright 2011 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package types 9 10 // under returns the true expanded underlying type. 11 // If it doesn't exist, the result is Typ[Invalid]. 12 // under must only be called when a type is known 13 // to be fully set up. 14 func under(t Type) Type { 15 if t := asNamed(t); t != nil { 16 return t.under() 17 } 18 return t.Underlying() 19 } 20 21 // If typ is a type parameter, underIs returns the result of typ.underIs(f). 22 // Otherwise, underIs returns the result of f(under(typ)). 23 func underIs(typ Type, f func(Type) bool) bool { 24 var ok bool 25 typeset(typ, func(_, u Type) bool { 26 ok = f(u) 27 return ok 28 }) 29 return ok 30 } 31 32 // typeset is an iterator over the (type/underlying type) pairs of the 33 // specific type terms of the type set implied by t. 34 // If t is a type parameter, the implied type set is the type set of t's constraint. 35 // In that case, if there are no specific terms, typeset calls yield with (nil, nil). 36 // If t is not a type parameter, the implied type set consists of just t. 37 // In any case, typeset is guaranteed to call yield at least once. 38 func typeset(t Type, yield func(t, u Type) bool) { 39 if p, _ := Unalias(t).(*TypeParam); p != nil { 40 p.typeset(yield) 41 return 42 } 43 yield(t, under(t)) 44 } 45 46 // If t is not a type parameter, coreType returns the underlying type. 47 // If t is a type parameter, coreType returns the single underlying 48 // type of all types in its type set if it exists, or nil otherwise. If the 49 // type set contains only unrestricted and restricted channel types (with 50 // identical element types), the single underlying type is the restricted 51 // channel type if the restrictions are always the same, or nil otherwise. 52 func coreType(t Type) Type { 53 var su Type 54 typeset(t, func(_, u Type) bool { 55 if u == nil { 56 return false 57 } 58 if su != nil { 59 u = match(su, u) 60 if u == nil { 61 su = nil 62 return false 63 } 64 } 65 // su == nil || match(su, u) != nil 66 su = u 67 return true 68 }) 69 return su 70 } 71 72 // coreString is like coreType but also considers []byte 73 // and strings as identical. In this case, if successful and we saw 74 // a string, the result is of type (possibly untyped) string. 75 func coreString(t Type) Type { 76 // This explicit case is needed because otherwise the 77 // result would be string if t is an untyped string. 78 if !isTypeParam(t) { 79 return under(t) // untyped string remains untyped 80 } 81 82 var su Type 83 hasString := false 84 typeset(t, func(_, u Type) bool { 85 if u == nil { 86 return false 87 } 88 if isString(u) { 89 u = NewSlice(universeByte) 90 hasString = true 91 } 92 if su != nil { 93 u = match(su, u) 94 if u == nil { 95 su = nil 96 hasString = false 97 return false 98 } 99 } 100 // su == nil || match(su, u) != nil 101 su = u 102 return true 103 }) 104 if hasString { 105 return Typ[String] 106 } 107 return su 108 } 109 110 // If x and y are identical, match returns x. 111 // If x and y are identical channels but for their direction 112 // and one of them is unrestricted, match returns the channel 113 // with the restricted direction. 114 // In all other cases, match returns nil. 115 func match(x, y Type) Type { 116 // Common case: we don't have channels. 117 if Identical(x, y) { 118 return x 119 } 120 121 // We may have channels that differ in direction only. 122 if x, _ := x.(*Chan); x != nil { 123 if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { 124 // We have channels that differ in direction only. 125 // If there's an unrestricted channel, select the restricted one. 126 switch { 127 case x.dir == SendRecv: 128 return y 129 case y.dir == SendRecv: 130 return x 131 } 132 } 133 } 134 135 // types are different 136 return nil 137 } 138