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