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