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 // A typeError describes a type error. 47 type typeError struct { 48 format_ string 49 args []any 50 } 51 52 var emptyTypeError typeError 53 54 func typeErrorf(format string, args ...any) *typeError { 55 if format == "" { 56 return &emptyTypeError 57 } 58 return &typeError{format, args} 59 } 60 61 // format formats a type error as a string. 62 // check may be nil. 63 func (err *typeError) format(check *Checker) string { 64 return check.sprintf(err.format_, err.args...) 65 } 66 67 // If t is a type parameter, cond is nil, and t's type set contains no channel types, 68 // commonUnder returns the common underlying type of all types in t's type set if 69 // it exists, or nil and a type error otherwise. 70 // 71 // If t is a type parameter, cond is nil, and there are channel types, t's type set 72 // must only contain channel types, they must all have the same element types, 73 // channel directions must not conflict, and commonUnder returns one of the most 74 // restricted channels. Otherwise, the function returns nil and a type error. 75 // 76 // If cond != nil, each pair (t, u) of type and underlying type in t's type set 77 // must satisfy the condition expressed by cond. If the result of cond is != nil, 78 // commonUnder returns nil and the type error reported by cond. 79 // Note that cond is called before any other conditions are checked; specifically 80 // cond may be called with (nil, nil) if the type set contains no specific types. 81 // 82 // If t is not a type parameter, commonUnder behaves as if t was a type parameter 83 // with the single type t in its type set. 84 func commonUnder(t Type, cond func(t, u Type) *typeError) (Type, *typeError) { 85 var ct, cu Type // type and respective common underlying type 86 var err *typeError 87 88 bad := func(format string, args ...any) bool { 89 err = typeErrorf(format, args...) 90 return false 91 } 92 93 typeset(t, func(t, u Type) bool { 94 if cond != nil { 95 if err = cond(t, u); err != nil { 96 return false 97 } 98 } 99 100 if u == nil { 101 return bad("no specific type") 102 } 103 104 // If this is the first type we're seeing, we're done. 105 if cu == nil { 106 ct, cu = t, u 107 return true 108 } 109 110 // If we've seen a channel before, and we have a channel now, they must be compatible. 111 if chu, _ := cu.(*Chan); chu != nil { 112 if ch, _ := u.(*Chan); ch != nil { 113 if !Identical(chu.elem, ch.elem) { 114 return bad("channels %s and %s have different element types", ct, t) 115 } 116 // If we have different channel directions, keep the restricted one 117 // and complain if they conflict. 118 switch { 119 case chu.dir == ch.dir: 120 // nothing to do 121 case chu.dir == SendRecv: 122 ct, cu = t, u // switch to restricted channel 123 case ch.dir != SendRecv: 124 return bad("channels %s and %s have conflicting directions", ct, t) 125 } 126 return true 127 } 128 } 129 130 // Otherwise, the current type must have the same underlying type as all previous types. 131 if !Identical(cu, u) { 132 return bad("%s and %s have different underlying types", ct, t) 133 } 134 135 return true 136 }) 137 138 if err != nil { 139 return nil, err 140 } 141 return cu, nil 142 } 143