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