go_types/check/
conversion.rs1#![allow(dead_code)]
13use crate::SourceRead;
14
15use super::super::constant::Value;
16use super::super::objects::TypeKey;
17use super::super::operand::{Operand, OperandMode};
18use super::super::typ::{self, BasicType, Type};
19use super::check::{Checker, FilesContext};
20use std::char;
21
22impl<'a, S: SourceRead> Checker<'a, S> {
23 pub fn conversion(&mut self, x: &mut Operand, t: TypeKey, fctx: &mut FilesContext<S>) {
24 let constv = match &mut x.mode {
25 OperandMode::Constant(v) => Some(v),
26 _ => None,
27 };
28 let const_arg = constv.is_some();
29
30 let o = &self.tc_objs;
31 let xtype = x.typ.unwrap();
32 let ok = if const_arg && typ::is_const_type(t, o) {
33 let v = constv.unwrap();
35 let tval = self.otype(t).underlying_val(o);
36 let basic = tval.try_as_basic().unwrap();
37 let clone = v.clone();
38 if clone.representable(basic, Some(v)) {
39 true
40 } else if typ::is_integer(xtype, o) && tval.is_string(o) {
41 let mut s = "\u{FFFD}".to_owned();
42 let (i, exact) = v.int_as_i64();
43 if exact {
44 if let Some(c) = char::from_u32(i as u32) {
45 s = c.to_string()
46 }
47 }
48 *v = Value::with_str(s);
49 true
50 } else {
51 false
52 }
53 } else if self.convertable_to(x, t, fctx) {
54 x.mode = OperandMode::Value;
56 true
57 } else {
58 false
59 };
60
61 if !ok {
62 let xd = self.new_dis(x);
63 let td = self.new_dis(&t);
64 self.error(xd.pos(), format!("cannot convert {} to {}", xd, td));
65 x.mode = OperandMode::Invalid;
66 return;
67 }
68
69 if typ::is_untyped(xtype, self.tc_objs) {
73 let o = &self.tc_objs;
80 let final_t = if typ::is_interface(t, o) || const_arg && !typ::is_const_type(t, o) {
81 typ::untyped_default_type(xtype, o)
82 } else if typ::is_integer(xtype, o) && typ::is_string(t, o) {
83 xtype
84 } else {
85 t
86 };
87 self.update_expr_type(x.expr.as_ref().unwrap(), final_t, true, fctx);
88 }
89
90 x.typ = Some(t);
91 }
92
93 pub fn convertable_to(&mut self, x: &Operand, t: TypeKey, fctx: &mut FilesContext<S>) -> bool {
97 if x.assignable_to(t, None, self, fctx) {
99 return true;
100 }
101
102 let o = &self.tc_objs;
103 let v = x.typ.unwrap();
105 let vu = typ::underlying_type(v, o);
106 let tu = typ::underlying_type(t, o);
107 if typ::identical_ignore_tags_o(Some(vu), Some(tu), o) {
108 return true;
109 }
110
111 let vval = self.otype(v);
112 let tval = self.otype(t);
113 let vuval = self.otype(vu);
114 let tuval = self.otype(tu);
115 if let Some(vdetail) = vval.try_as_pointer() {
118 if let Some(tdetail) = tval.try_as_pointer() {
119 let vu = typ::underlying_type(vdetail.base(), o);
120 let tu = typ::underlying_type(tdetail.base(), o);
121 if typ::identical_ignore_tags_o(Some(vu), Some(tu), o) {
122 return true;
123 }
124 }
125 }
126
127 if (vval.is_integer(o) || vval.is_float(o)) && (tval.is_integer(o) || tval.is_float(o)) {
129 return true;
130 }
131
132 if vval.is_complex(o) || tval.is_complex(o) {
134 return true;
135 }
136
137 if (vval.is_integer(o) || self.is_bytes_or_runes(vuval)) && tval.is_string(o) {
139 return true;
140 }
141
142 if vval.is_string(o) && self.is_bytes_or_runes(tuval) {
144 return true;
145 }
146
147 if (self.is_pointer(vuval) || self.is_uintptr(vuval)) && self.is_unsafe_pointer(tval) {
150 return true;
151 }
152
153 if (self.is_pointer(tuval) || self.is_uintptr(tuval)) && self.is_unsafe_pointer(vval) {
155 return true;
156 }
157
158 false
159 }
160
161 fn is_uintptr(&self, t: &Type) -> bool {
162 if let Some(detail) = t.underlying_val(self.tc_objs).try_as_basic() {
163 return detail.typ() == BasicType::Uintptr;
164 }
165 false
166 }
167
168 fn is_unsafe_pointer(&self, t: &Type) -> bool {
169 if let Some(detail) = t.underlying_val(self.tc_objs).try_as_basic() {
170 return detail.typ() == BasicType::UnsafePointer;
171 }
172 false
173 }
174
175 fn is_pointer(&self, t: &Type) -> bool {
176 t.underlying_val(self.tc_objs).try_as_pointer().is_some()
177 }
178
179 fn is_bytes_or_runes(&self, t: &Type) -> bool {
180 if let Some(detail) = t.try_as_slice() {
181 if let Some(b) = self
182 .otype(detail.elem())
183 .underlying_val(self.tc_objs)
184 .try_as_basic()
185 {
186 return b.typ() == BasicType::Byte || b.typ() == BasicType::Rune;
187 }
188 }
189 false
190 }
191}