4
4
5
5
package types2
6
6
7
+ import "iter"
8
+
7
9
// under returns the true expanded underlying type.
8
10
// If it doesn't exist, the result is Typ[Invalid].
9
11
// under must only be called when a type is known
@@ -18,12 +20,18 @@ func under(t Type) Type {
18
20
// If typ is a type parameter, underIs returns the result of typ.underIs(f).
19
21
// Otherwise, underIs returns the result of f(under(typ)).
20
22
func underIs (typ Type , f func (Type ) bool ) bool {
21
- var ok bool
22
- typeset (typ , func (_ , u Type ) bool {
23
- ok = f (u )
24
- return ok
23
+ return all (typ , func (_ , u Type ) bool {
24
+ return f (u )
25
25
})
26
- return ok
26
+ }
27
+
28
+ // all reports whether f(t, u) is true for all (type/underlying type)
29
+ // pairs in the typeset of t. See [typeset] for details of sequence.
30
+ func all (t Type , f func (t , u Type ) bool ) bool {
31
+ if p , _ := Unalias (t ).(* TypeParam ); p != nil {
32
+ return p .typeset (f )
33
+ }
34
+ return f (t , under (t ))
27
35
}
28
36
29
37
// typeset is an iterator over the (type/underlying type) pairs of the
@@ -32,12 +40,10 @@ func underIs(typ Type, f func(Type) bool) bool {
32
40
// In that case, if there are no specific terms, typeset calls yield with (nil, nil).
33
41
// If t is not a type parameter, the implied type set consists of just t.
34
42
// In any case, typeset is guaranteed to call yield at least once.
35
- func typeset (t Type , yield func (t , u Type ) bool ) {
36
- if p , _ := Unalias (t ).(* TypeParam ); p != nil {
37
- p .typeset (yield )
38
- return
43
+ func typeset (t Type ) iter.Seq2 [Type , Type ] {
44
+ return func (yield func (t , u Type ) bool ) {
45
+ _ = all (t , yield )
39
46
}
40
- yield (t , under (t ))
41
47
}
42
48
43
49
// A typeError describes a type error.
@@ -80,35 +86,28 @@ func (err *typeError) format(check *Checker) string {
80
86
// with the single type t in its type set.
81
87
func commonUnder (t Type , cond func (t , u Type ) * typeError ) (Type , * typeError ) {
82
88
var ct , cu Type // type and respective common underlying type
83
- var err * typeError
84
-
85
- bad := func (format string , args ... any ) bool {
86
- err = typeErrorf (format , args ... )
87
- return false
88
- }
89
-
90
- typeset (t , func (t , u Type ) bool {
89
+ for t , u := range typeset (t ) {
91
90
if cond != nil {
92
- if err = cond (t , u ); err != nil {
93
- return false
91
+ if err : = cond (t , u ); err != nil {
92
+ return nil , err
94
93
}
95
94
}
96
95
97
96
if u == nil {
98
- return bad ("no specific type" )
97
+ return nil , typeErrorf ("no specific type" )
99
98
}
100
99
101
100
// If this is the first type we're seeing, we're done.
102
101
if cu == nil {
103
102
ct , cu = t , u
104
- return true
103
+ continue
105
104
}
106
105
107
106
// If we've seen a channel before, and we have a channel now, they must be compatible.
108
107
if chu , _ := cu .(* Chan ); chu != nil {
109
108
if ch , _ := u .(* Chan ); ch != nil {
110
109
if ! Identical (chu .elem , ch .elem ) {
111
- return bad ("channels %s and %s have different element types" , ct , t )
110
+ return nil , typeErrorf ("channels %s and %s have different element types" , ct , t )
112
111
}
113
112
// If we have different channel directions, keep the restricted one
114
113
// and complain if they conflict.
@@ -118,22 +117,16 @@ func commonUnder(t Type, cond func(t, u Type) *typeError) (Type, *typeError) {
118
117
case chu .dir == SendRecv :
119
118
ct , cu = t , u // switch to restricted channel
120
119
case ch .dir != SendRecv :
121
- return bad ("channels %s and %s have conflicting directions" , ct , t )
120
+ return nil , typeErrorf ("channels %s and %s have conflicting directions" , ct , t )
122
121
}
123
- return true
122
+ continue
124
123
}
125
124
}
126
125
127
126
// Otherwise, the current type must have the same underlying type as all previous types.
128
127
if ! Identical (cu , u ) {
129
- return bad ("%s and %s have different underlying types" , ct , t )
128
+ return nil , typeErrorf ("%s and %s have different underlying types" , ct , t )
130
129
}
131
-
132
- return true
133
- })
134
-
135
- if err != nil {
136
- return nil , err
137
130
}
138
131
return cu , nil
139
132
}
0 commit comments