1 // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
2 // Source: ../../cmd/compile/internal/types2/conversions.go
3 4 // Copyright 2012 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 // This file implements typechecking of conversions.
9 10 package types
11 12 import (
13 "go/constant"
14 . "internal/types/errors"
15 "unicode"
16 )
17 18 // conversion type-checks the conversion T(x).
19 // The result is in x.
20 func (check *Checker) conversion(x *operand, T Type) {
21 constArg := x.mode == constant_
22 23 constConvertibleTo := func(T Type, val *constant.Value) bool {
24 switch t, _ := under(T).(*Basic); {
25 case t == nil:
26 // nothing to do
27 case representableConst(x.val, check, t, val):
28 return true
29 case isInteger(x.typ) && isString(t):
30 codepoint := unicode.ReplacementChar
31 if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune {
32 codepoint = rune(i)
33 }
34 if val != nil {
35 *val = constant.MakeString(string(codepoint))
36 }
37 return true
38 }
39 return false
40 }
41 42 var ok bool
43 var cause string
44 switch {
45 case constArg && isConstType(T):
46 // constant conversion
47 ok = constConvertibleTo(T, &x.val)
48 // A conversion from an integer constant to an integer type
49 // can only fail if there's overflow. Give a concise error.
50 // (go.dev/issue/63563)
51 if !ok && isInteger(x.typ) && isInteger(T) {
52 check.errorf(x, InvalidConversion, "constant %s overflows %s", x.val, T)
53 x.mode = invalid
54 return
55 }
56 case constArg && isTypeParam(T):
57 // x is convertible to T if it is convertible
58 // to each specific type in the type set of T.
59 // If T's type set is empty, or if it doesn't
60 // have specific types, constant x cannot be
61 // converted.
62 ok = underIs(T, func(u Type) bool {
63 // u is nil if there are no specific type terms
64 if u == nil {
65 cause = check.sprintf("%s does not contain specific types", T)
66 return false
67 }
68 if isString(x.typ) && isBytesOrRunes(u) {
69 return true
70 }
71 if !constConvertibleTo(u, nil) {
72 if isInteger(x.typ) && isInteger(u) {
73 // see comment above on constant conversion
74 cause = check.sprintf("constant %s overflows %s (in %s)", x.val, u, T)
75 } else {
76 cause = check.sprintf("cannot convert %s to type %s (in %s)", x, u, T)
77 }
78 return false
79 }
80 return true
81 })
82 x.mode = value // type parameters are not constants
83 case x.convertibleTo(check, T, &cause):
84 // non-constant conversion
85 ok = true
86 x.mode = value
87 }
88 89 if !ok {
90 if cause != "" {
91 check.errorf(x, InvalidConversion, "cannot convert %s to type %s: %s", x, T, cause)
92 } else {
93 check.errorf(x, InvalidConversion, "cannot convert %s to type %s", x, T)
94 }
95 x.mode = invalid
96 return
97 }
98 99 // The conversion argument types are final. For untyped values the
100 // conversion provides the type, per the spec: "A constant may be
101 // given a type explicitly by a constant declaration or conversion,...".
102 if isUntyped(x.typ) {
103 final := T
104 // - For conversions to interfaces, except for untyped nil arguments
105 // and isTypes2, use the argument's default type.
106 // - For conversions of untyped constants to non-constant types, also
107 // use the default type (e.g., []byte("foo") should report string
108 // not []byte as type for the constant "foo").
109 // - If !isTypes2, keep untyped nil for untyped nil arguments.
110 // - For constant integer to string conversions, keep the argument type.
111 // (See also the TODO below.)
112 if isTypes2 && x.typ == Typ[UntypedNil] {
113 // ok
114 } else if isNonTypeParamInterface(T) || constArg && !isConstType(T) || !isTypes2 && x.isNil() {
115 final = Default(x.typ) // default type of untyped nil is untyped nil
116 } else if x.mode == constant_ && isInteger(x.typ) && allString(T) {
117 final = x.typ
118 }
119 check.updateExprType(x.expr, final, true)
120 }
121 122 x.typ = T
123 }
124 125 // TODO(gri) convertibleTo checks if T(x) is valid. It assumes that the type
126 // of x is fully known, but that's not the case for say string(1<<s + 1.0):
127 // Here, the type of 1<<s + 1.0 will be UntypedFloat which will lead to the
128 // (correct!) refusal of the conversion. But the reported error is essentially
129 // "cannot convert untyped float value to string", yet the correct error (per
130 // the spec) is that we cannot shift a floating-point value: 1 in 1<<s should
131 // be converted to UntypedFloat because of the addition of 1.0. Fixing this
132 // is tricky because we'd have to run updateExprType on the argument first.
133 // (go.dev/issue/21982.)
134 135 // convertibleTo reports whether T(x) is valid. In the failure case, *cause
136 // may be set to the cause for the failure.
137 // The check parameter may be nil if convertibleTo is invoked through an
138 // exported API call, i.e., when all methods have been type-checked.
139 func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
140 // "x is assignable to T"
141 if ok, _ := x.assignableTo(check, T, cause); ok {
142 return true
143 }
144 145 origT := T
146 V := Unalias(x.typ)
147 T = Unalias(T)
148 Vu := under(V)
149 Tu := under(T)
150 Vp, _ := V.(*TypeParam)
151 Tp, _ := T.(*TypeParam)
152 153 // "V and T have identical underlying types if tags are ignored
154 // and V and T are not type parameters"
155 if IdenticalIgnoreTags(Vu, Tu) && Vp == nil && Tp == nil {
156 return true
157 }
158 159 // "V and T are unnamed pointer types and their pointer base types
160 // have identical underlying types if tags are ignored
161 // and their pointer base types are not type parameters"
162 if V, ok := V.(*Pointer); ok {
163 if T, ok := T.(*Pointer); ok {
164 if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) {
165 return true
166 }
167 }
168 }
169 170 // "V and T are both integer or floating point types"
171 if isIntegerOrFloat(Vu) && isIntegerOrFloat(Tu) {
172 return true
173 }
174 175 // "V and T are both complex types"
176 if isComplex(Vu) && isComplex(Tu) {
177 return true
178 }
179 180 // "V is an integer or a slice of bytes or runes and T is a string type"
181 if (isInteger(Vu) || isBytesOrRunes(Vu)) && isString(Tu) {
182 return true
183 }
184 185 // "V is a string and T is a slice of bytes or runes"
186 if isString(Vu) && isBytesOrRunes(Tu) {
187 return true
188 }
189 190 // package unsafe:
191 // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
192 if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(Tu) {
193 return true
194 }
195 // "and vice versa"
196 if isUnsafePointer(Vu) && (isPointer(Tu) || isUintptr(Tu)) {
197 return true
198 }
199 200 // "V is a slice, T is an array or pointer-to-array type,
201 // and the slice and array types have identical element types."
202 if s, _ := Vu.(*Slice); s != nil {
203 switch a := Tu.(type) {
204 case *Array:
205 if Identical(s.Elem(), a.Elem()) {
206 if check == nil || check.allowVersion(go1_20) {
207 return true
208 }
209 // check != nil
210 if cause != nil {
211 // TODO(gri) consider restructuring versionErrorf so we can use it here and below
212 *cause = "conversion of slice to array requires go1.20 or later"
213 }
214 return false
215 }
216 case *Pointer:
217 if a, _ := under(a.Elem()).(*Array); a != nil {
218 if Identical(s.Elem(), a.Elem()) {
219 if check == nil || check.allowVersion(go1_17) {
220 return true
221 }
222 // check != nil
223 if cause != nil {
224 *cause = "conversion of slice to array pointer requires go1.17 or later"
225 }
226 return false
227 }
228 }
229 }
230 }
231 232 // optimization: if we don't have type parameters, we're done
233 if Vp == nil && Tp == nil {
234 return false
235 }
236 237 errorf := func(format string, args ...any) {
238 if check != nil && cause != nil {
239 msg := check.sprintf(format, args...)
240 if *cause != "" {
241 msg += "\n\t" + *cause
242 }
243 *cause = msg
244 }
245 }
246 247 // generic cases with specific type terms
248 // (generic operands cannot be constants, so we can ignore x.val)
249 switch {
250 case Vp != nil && Tp != nil:
251 x := *x // don't clobber outer x
252 return Vp.is(func(V *term) bool {
253 if V == nil {
254 return false // no specific types
255 }
256 x.typ = V.typ
257 return Tp.is(func(T *term) bool {
258 if T == nil {
259 return false // no specific types
260 }
261 if !x.convertibleTo(check, T.typ, cause) {
262 errorf("cannot convert %s (in %s) to type %s (in %s)", V.typ, Vp, T.typ, Tp)
263 return false
264 }
265 return true
266 })
267 })
268 case Vp != nil:
269 x := *x // don't clobber outer x
270 return Vp.is(func(V *term) bool {
271 if V == nil {
272 return false // no specific types
273 }
274 x.typ = V.typ
275 if !x.convertibleTo(check, T, cause) {
276 errorf("cannot convert %s (in %s) to type %s", V.typ, Vp, origT)
277 return false
278 }
279 return true
280 })
281 case Tp != nil:
282 return Tp.is(func(T *term) bool {
283 if T == nil {
284 return false // no specific types
285 }
286 if !x.convertibleTo(check, T.typ, cause) {
287 errorf("cannot convert %s to type %s (in %s)", x.typ, T.typ, Tp)
288 return false
289 }
290 return true
291 })
292 }
293 294 return false
295 }
296 297 func isUintptr(typ Type) bool {
298 t, _ := under(typ).(*Basic)
299 return t != nil && t.kind == Uintptr
300 }
301 302 func isUnsafePointer(typ Type) bool {
303 t, _ := under(typ).(*Basic)
304 return t != nil && t.kind == UnsafePointer
305 }
306 307 func isPointer(typ Type) bool {
308 _, ok := under(typ).(*Pointer)
309 return ok
310 }
311 312 func isBytesOrRunes(typ Type) bool {
313 if s, _ := under(typ).(*Slice); s != nil {
314 t, _ := under(s.elem).(*Basic)
315 return t != nil && (t.kind == Byte || t.kind == Rune)
316 }
317 return false
318 }
319