github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/types2/under.go (about) 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 tpar, _ := t.(*TypeParam) 26 if tpar == nil { 27 return under(t) 28 } 29 30 var su Type 31 if tpar.underIs(func(u Type) bool { 32 if u == nil { 33 return false 34 } 35 if su != nil { 36 u = match(su, u) 37 if u == nil { 38 return false 39 } 40 } 41 // su == nil || match(su, u) != nil 42 su = u 43 return true 44 }) { 45 return su 46 } 47 return nil 48 } 49 50 // coreString is like coreType but also considers []byte 51 // and strings as identical. In this case, if successful and we saw 52 // a string, the result is of type (possibly untyped) string. 53 func coreString(t Type) Type { 54 tpar, _ := t.(*TypeParam) 55 if tpar == nil { 56 return under(t) // string or untyped string 57 } 58 59 var su Type 60 hasString := false 61 if tpar.underIs(func(u Type) bool { 62 if u == nil { 63 return false 64 } 65 if isString(u) { 66 u = NewSlice(universeByte) 67 hasString = true 68 } 69 if su != nil { 70 u = match(su, u) 71 if u == nil { 72 return false 73 } 74 } 75 // su == nil || match(su, u) != nil 76 su = u 77 return true 78 }) { 79 if hasString { 80 return Typ[String] 81 } 82 return su 83 } 84 return nil 85 } 86 87 // If x and y are identical, match returns x. 88 // If x and y are identical channels but for their direction 89 // and one of them is unrestricted, match returns the channel 90 // with the restricted direction. 91 // In all other cases, match returns nil. 92 func match(x, y Type) Type { 93 // Common case: we don't have channels. 94 if Identical(x, y) { 95 return x 96 } 97 98 // We may have channels that differ in direction only. 99 if x, _ := x.(*Chan); x != nil { 100 if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { 101 // We have channels that differ in direction only. 102 // If there's an unrestricted channel, select the restricted one. 103 switch { 104 case x.dir == SendRecv: 105 return y 106 case y.dir == SendRecv: 107 return x 108 } 109 } 110 } 111 112 // types are different 113 return nil 114 }