@@ -122,64 +122,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
122
122
return true
123
123
}
124
124
125
- // determine type parameter operands with specific type terms
126
- Vp , _ := under (x .typ ).(* TypeParam )
127
- Tp , _ := under (T ).(* TypeParam )
128
- if Vp != nil && ! Vp .hasTerms () {
129
- Vp = nil
130
- }
131
- if Tp != nil && ! Tp .hasTerms () {
132
- Tp = nil
133
- }
134
-
135
- errorf := func (format string , args ... interface {}) {
136
- if check != nil && cause != nil {
137
- msg := check .sprintf (format , args ... )
138
- if * cause != "" {
139
- msg += "\n \t " + * cause
140
- }
141
- * cause = msg
142
- }
143
- }
144
-
145
- // generic cases with specific type terms
146
- // (generic operands cannot be constants, so we can ignore x.val)
147
- switch {
148
- case Vp != nil && Tp != nil :
149
- return Vp .is (func (V * term ) bool {
150
- return Tp .is (func (T * term ) bool {
151
- if ! convertibleToImpl (check , V .typ , T .typ , cause ) {
152
- errorf ("cannot convert %s (in %s) to %s (in %s)" , V .typ , Vp , T .typ , Tp )
153
- return false
154
- }
155
- return true
156
- })
157
- })
158
- case Vp != nil :
159
- return Vp .is (func (V * term ) bool {
160
- if ! convertibleToImpl (check , V .typ , T , cause ) {
161
- errorf ("cannot convert %s (in %s) to %s" , V .typ , Vp , T )
162
- return false
163
- }
164
- return true
165
- })
166
- case Tp != nil :
167
- return Tp .is (func (T * term ) bool {
168
- if ! convertibleToImpl (check , x .typ , T .typ , cause ) {
169
- errorf ("cannot convert %s to %s (in %s)" , x .typ , T .typ , Tp )
170
- return false
171
- }
172
- return true
173
- })
174
- }
175
-
176
- // non-generic case
177
- return convertibleToImpl (check , x .typ , T , cause )
178
- }
179
-
180
- // convertibleToImpl should only be called by convertibleTo
181
- func convertibleToImpl (check * Checker , V , T Type , cause * string ) bool {
182
125
// "V and T have identical underlying types if tags are ignored"
126
+ V := x .typ
183
127
Vu := under (V )
184
128
Tu := under (T )
185
129
if IdenticalIgnoreTags (Vu , Tu ) {
@@ -250,6 +194,67 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool {
250
194
}
251
195
}
252
196
197
+ // optimization: if we don't have type parameters, we're done
198
+ Vp , _ := Vu .(* TypeParam )
199
+ Tp , _ := Tu .(* TypeParam )
200
+ if Vp == nil && Tp == nil {
201
+ return false
202
+ }
203
+
204
+ errorf := func (format string , args ... interface {}) {
205
+ if check != nil && cause != nil {
206
+ msg := check .sprintf (format , args ... )
207
+ if * cause != "" {
208
+ msg += "\n \t " + * cause
209
+ }
210
+ * cause = msg
211
+ }
212
+ }
213
+
214
+ // generic cases with specific type terms
215
+ // (generic operands cannot be constants, so we can ignore x.val)
216
+ switch {
217
+ case Vp != nil && Tp != nil :
218
+ x := * x // don't clobber outer x
219
+ return Vp .is (func (V * term ) bool {
220
+ if V == nil {
221
+ return false // no specific types
222
+ }
223
+ x .typ = V .typ
224
+ return Tp .is (func (T * term ) bool {
225
+ if ! x .convertibleTo (check , T .typ , cause ) {
226
+ errorf ("cannot convert %s (in %s) to %s (in %s)" , V .typ , Vp , T .typ , Tp )
227
+ return false
228
+ }
229
+ return true
230
+ })
231
+ })
232
+ case Vp != nil :
233
+ x := * x // don't clobber outer x
234
+ return Vp .is (func (V * term ) bool {
235
+ if V == nil {
236
+ return false // no specific types
237
+ }
238
+ x .typ = V .typ
239
+ if ! x .convertibleTo (check , T , cause ) {
240
+ errorf ("cannot convert %s (in %s) to %s" , V .typ , Vp , T )
241
+ return false
242
+ }
243
+ return true
244
+ })
245
+ case Tp != nil :
246
+ return Tp .is (func (T * term ) bool {
247
+ if T == nil {
248
+ return false // no specific types
249
+ }
250
+ if ! x .convertibleTo (check , T .typ , cause ) {
251
+ errorf ("cannot convert %s to %s (in %s)" , x .typ , T .typ , Tp )
252
+ return false
253
+ }
254
+ return true
255
+ })
256
+ }
257
+
253
258
return false
254
259
}
255
260
0 commit comments