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