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 import "iter" 11 12 // under returns the true expanded underlying type. 13 // If it doesn't exist, the result is Typ[Invalid]. 14 // under must only be called when a type is known 15 // to be fully set up. 16 func under(t Type) Type { 17 if t := asNamed(t); t != nil { 18 return t.under() 19 } 20 return t.Underlying() 21 } 22 23 // If typ is a type parameter, underIs returns the result of typ.underIs(f). 24 // Otherwise, underIs returns the result of f(under(typ)). 25 func underIs(typ Type, f func(Type) bool) bool { 26 return all(typ, func(_, u Type) bool { 27 return f(u) 28 }) 29 } 30 31 // all reports whether f(t, u) is true for all (type/underlying type) 32 // pairs in the typeset of t. See [typeset] for details of sequence. 33 func all(t Type, f func(t, u Type) bool) bool { 34 if p, _ := Unalias(t).(*TypeParam); p != nil { 35 return p.typeset(f) 36 } 37 return f(t, under(t)) 38 } 39 40 // typeset is an iterator over the (type/underlying type) pairs of the 41 // specific type terms of the type set implied by t. 42 // If t is a type parameter, the implied type set is the type set of t's constraint. 43 // In that case, if there are no specific terms, typeset calls yield with (nil, nil). 44 // If t is not a type parameter, the implied type set consists of just t. 45 // In any case, typeset is guaranteed to call yield at least once. 46 func typeset(t Type) iter.Seq2[Type, Type] { 47 return func(yield func(t, u Type) bool) { 48 _ = all(t, yield) 49 } 50 } 51 52 // A typeError describes a type error. 53 type typeError struct { 54 format_ string 55 args []any 56 } 57 58 var emptyTypeError typeError 59 60 func typeErrorf(format string, args ...any) *typeError { 61 if format == "" { 62 return &emptyTypeError 63 } 64 return &typeError{format, args} 65 } 66 67 // format formats a type error as a string. 68 // check may be nil. 69 func (err *typeError) format(check *Checker) string { 70 return check.sprintf(err.format_, err.args...) 71 } 72 73 // If t is a type parameter, cond is nil, and t's type set contains no channel types, 74 // commonUnder returns the common underlying type of all types in t's type set if 75 // it exists, or nil and a type error otherwise. 76 // 77 // If t is a type parameter, cond is nil, and there are channel types, t's type set 78 // must only contain channel types, they must all have the same element types, 79 // channel directions must not conflict, and commonUnder returns one of the most 80 // restricted channels. Otherwise, the function returns nil and a type error. 81 // 82 // If cond != nil, each pair (t, u) of type and underlying type in t's type set 83 // must satisfy the condition expressed by cond. If the result of cond is != nil, 84 // commonUnder returns nil and the type error reported by cond. 85 // Note that cond is called before any other conditions are checked; specifically 86 // cond may be called with (nil, nil) if the type set contains no specific types. 87 // 88 // If t is not a type parameter, commonUnder behaves as if t was a type parameter 89 // with the single type t in its type set. 90 func commonUnder(t Type, cond func(t, u Type) *typeError) (Type, *typeError) { 91 var ct, cu Type // type and respective common underlying type 92 for t, u := range typeset(t) { 93 if cond != nil { 94 if err := cond(t, u); err != nil { 95 return nil, err 96 } 97 } 98 99 if u == nil { 100 return nil, typeErrorf("no specific type") 101 } 102 103 // If this is the first type we're seeing, we're done. 104 if cu == nil { 105 ct, cu = t, u 106 continue 107 } 108 109 // If we've seen a channel before, and we have a channel now, they must be compatible. 110 if chu, _ := cu.(*Chan); chu != nil { 111 if ch, _ := u.(*Chan); ch != nil { 112 if !Identical(chu.elem, ch.elem) { 113 return nil, typeErrorf("channels %s and %s have different element types", ct, t) 114 } 115 // If we have different channel directions, keep the restricted one 116 // and complain if they conflict. 117 switch { 118 case chu.dir == ch.dir: 119 // nothing to do 120 case chu.dir == SendRecv: 121 ct, cu = t, u // switch to restricted channel 122 case ch.dir != SendRecv: 123 return nil, typeErrorf("channels %s and %s have conflicting directions", ct, t) 124 } 125 continue 126 } 127 } 128 129 // Otherwise, the current type must have the same underlying type as all previous types. 130 if !Identical(cu, u) { 131 return nil, typeErrorf("%s and %s have different underlying types", ct, t) 132 } 133 } 134 return cu, nil 135 } 136