...
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.conf, 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.conf, 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 func (x *operand) convertibleTo(conf *Config, T Type) bool {
80
81 if x.assignableTo(conf, T, nil) {
82 return true
83 }
84
85
86 V := x.typ
87 Vu := V.Underlying()
88 Tu := T.Underlying()
89 if IdenticalIgnoreTags(Vu, Tu) {
90 return true
91 }
92
93
94
95 if V, ok := V.(*Pointer); ok {
96 if T, ok := T.(*Pointer); ok {
97 if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) {
98 return true
99 }
100 }
101 }
102
103
104 if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
105 return true
106 }
107
108
109 if isComplex(V) && isComplex(T) {
110 return true
111 }
112
113
114 if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
115 return true
116 }
117
118
119 if isString(V) && isBytesOrRunes(Tu) {
120 return true
121 }
122
123
124
125 if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
126 return true
127 }
128
129 if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
130 return true
131 }
132
133 return false
134 }
135
136 func isUintptr(typ Type) bool {
137 t, ok := typ.Underlying().(*Basic)
138 return ok && t.kind == Uintptr
139 }
140
141 func isUnsafePointer(typ Type) bool {
142
143
144
145 t, ok := typ.Underlying().(*Basic)
146 return ok && t.kind == UnsafePointer
147 }
148
149 func isPointer(typ Type) bool {
150 _, ok := typ.Underlying().(*Pointer)
151 return ok
152 }
153
154 func isBytesOrRunes(typ Type) bool {
155 if s, ok := typ.(*Slice); ok {
156 t, ok := s.elem.Underlying().(*Basic)
157 return ok && (t.kind == Byte || t.kind == Rune)
158 }
159 return false
160 }
161
View as plain text