...
Source file src/go/types/conversions.go
1
2
3
4
5
6
7 package types
8
9 import "go/constant"
10
11
12
13 func (check *Checker) conversion(x *operand, T Type) {
14 constArg := x.mode == constant_
15
16 var ok bool
17 switch {
18 case constArg && isConstType(T):
19
20 switch t := T.Underlying().(*Basic); {
21 case representableConst(x.val, check, t, &x.val):
22 ok = true
23 case isInteger(x.typ) && isString(t):
24 codepoint := int64(-1)
25 if i, ok := constant.Int64Val(x.val); ok {
26 codepoint = i
27 }
28
29
30
31 x.val = constant.MakeString(string(codepoint))
32 ok = true
33 }
34 case x.convertibleTo(check, T):
35
36 x.mode = value
37 ok = true
38 }
39
40 if !ok {
41 check.errorf(x.pos(), "cannot convert %s to %s", x, T)
42 x.mode = invalid
43 return
44 }
45
46
47
48
49 if isUntyped(x.typ) {
50 final := T
51
52
53
54
55
56
57
58 if IsInterface(T) || constArg && !isConstType(T) {
59 final = Default(x.typ)
60 } else if isInteger(x.typ) && isString(T) {
61 final = x.typ
62 }
63 check.updateExprType(x.expr, final, true)
64 }
65
66 x.typ = T
67 }
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 func (x *operand) convertibleTo(check *Checker, T Type) bool {
83
84 if x.assignableTo(check, T, nil) {
85 return true
86 }
87
88
89 V := x.typ
90 Vu := V.Underlying()
91 Tu := T.Underlying()
92 if IdenticalIgnoreTags(Vu, Tu) {
93 return true
94 }
95
96
97
98 if V, ok := V.(*Pointer); ok {
99 if T, ok := T.(*Pointer); ok {
100 if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) {
101 return true
102 }
103 }
104 }
105
106
107 if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
108 return true
109 }
110
111
112 if isComplex(V) && isComplex(T) {
113 return true
114 }
115
116
117 if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
118 return true
119 }
120
121
122 if isString(V) && isBytesOrRunes(Tu) {
123 return true
124 }
125
126
127
128 if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
129 return true
130 }
131
132 if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
133 return true
134 }
135
136 return false
137 }
138
139 func isUintptr(typ Type) bool {
140 t, ok := typ.Underlying().(*Basic)
141 return ok && t.kind == Uintptr
142 }
143
144 func isUnsafePointer(typ Type) bool {
145
146
147
148 t, ok := typ.Underlying().(*Basic)
149 return ok && t.kind == UnsafePointer
150 }
151
152 func isPointer(typ Type) bool {
153 _, ok := typ.Underlying().(*Pointer)
154 return ok
155 }
156
157 func isBytesOrRunes(typ Type) bool {
158 if s, ok := typ.(*Slice); ok {
159 t, ok := s.elem.Underlying().(*Basic)
160 return ok && (t.kind == Byte || t.kind == Rune)
161 }
162 return false
163 }
164
View as plain text