Skip to content

Commit f934b83

Browse files
committed
cmd/compile/internal/types2: check non-generic conversions first
This enables the elimination of convertibleToImpl again, with the code structure close to the original non-generic version, and closely matching the structure of assignableTo. We also don't need the hasTerm tests; instead we can rely directly on the mechanism of TypeParam.is which is feeding a nil term if there are no specific types. Change-Id: I0385acca779d75c3c961d06afb464714fe51705d Reviewed-on: https://go-review.googlesource.com/c/go/+/361269 Trust: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 6ba68a0 commit f934b83

File tree

1 file changed

+62
-57
lines changed

1 file changed

+62
-57
lines changed

src/cmd/compile/internal/types2/conversions.go

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -122,64 +122,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
122122
return true
123123
}
124124

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 {
182125
// "V and T have identical underlying types if tags are ignored"
126+
V := x.typ
183127
Vu := under(V)
184128
Tu := under(T)
185129
if IdenticalIgnoreTags(Vu, Tu) {
@@ -250,6 +194,67 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool {
250194
}
251195
}
252196

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+
253258
return false
254259
}
255260

0 commit comments

Comments
 (0)