authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-11-18 19:36:27-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-11-18 19:37:59-05:00
logf8a782fb2ec63b89fadb409f7378066a26945d3b
tree363d3428b7b38777b1f328fe0196987b7d986f9f
parente9b47d960b81dfc1fd70c5ae663b4b692ab0b19d
signaturelock-open Commit is signed but in an unrecognized format.

all numbers with comptime known values implicitly cast

to all number types. If the value does not fit, a compile error is emitted. closes #422 closes #1712

4 files changed, 346 insertions(+), 161 deletions(-)

doc/langref.html.in+2-2
...@@ -6659,7 +6659,7 @@ fn foo(x: []const u8) u8 {...@@ -6659,7 +6659,7 @@ fn foo(x: []const u8) u8 {
6659 {#header_close#}6659 {#header_close#}
6660 {#header_open|Cast Negative Number to Unsigned Integer#}6660 {#header_open|Cast Negative Number to Unsigned Integer#}
6661 <p>At compile-time:</p>6661 <p>At compile-time:</p>
6662 {#code_begin|test_err|attempt to cast negative value to unsigned integer#}6662 {#code_begin|test_err|cannot cast negative value -1 to unsigned integer type 'u32'#}
6663comptime {6663comptime {
6664 const value: i32 = -1;6664 const value: i32 = -1;
6665 const unsigned = @intCast(u32, value);6665 const unsigned = @intCast(u32, value);
...@@ -6681,7 +6681,7 @@ pub fn main() void {...@@ -6681,7 +6681,7 @@ pub fn main() void {
6681 {#header_close#}6681 {#header_close#}
6682 {#header_open|Cast Truncates Data#}6682 {#header_open|Cast Truncates Data#}
6683 <p>At compile-time:</p>6683 <p>At compile-time:</p>
6684 {#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#}6684 {#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#}
6685comptime {6685comptime {
6686 const spartan_count: u16 = 300;6686 const spartan_count: u16 = 300;
6687 const byte = @intCast(u8, spartan_count);6687 const byte = @intCast(u8, spartan_count);
src/ir.cpp+278-128
...@@ -138,6 +138,11 @@ struct ConstCastErrSetMismatch {...@@ -138,6 +138,11 @@ struct ConstCastErrSetMismatch {
138 ZigList<ErrorTableEntry *> missing_errors;138 ZigList<ErrorTableEntry *> missing_errors;
139};139};
140140
141enum UndefAllowed {
142 UndefOk,
143 UndefBad,
144};
145
141static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);146static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
142static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);147static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);
143static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);148static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
...@@ -157,6 +162,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,...@@ -157,6 +162,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
157 ConstExprValue *out_val, ConstExprValue *ptr_val);162 ConstExprValue *out_val, ConstExprValue *ptr_val);
158static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,163static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
159 ZigType *dest_type, IrInstruction *dest_type_src);164 ZigType *dest_type, IrInstruction *dest_type_src);
165static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
160166
161static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {167static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
162 assert(get_src_ptr_type(const_val->type) != nullptr);168 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -8063,15 +8069,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -8063,15 +8069,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
8063 return false;8069 return false;
8064 }8070 }
80658071
8066 ConstExprValue *const_val = &instruction->value;8072 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);
8067 assert(const_val->special != ConstValSpecialRuntime);8073 assert(const_val != nullptr);
8074
8075 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
8076 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
80688077
8069 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt ||
8070 const_val->type->id == ZigTypeIdComptimeInt);
8071 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat ||
8072 const_val->type->id == ZigTypeIdComptimeFloat);
8073 if (other_type->id == ZigTypeIdFloat) {8078 if (other_type->id == ZigTypeIdFloat) {
8074 return true;8079 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
8080 return true;
8081 }
8082 if (const_val->type->id == ZigTypeIdInt) {
8083 BigFloat tmp_bf;
8084 bigfloat_init_bigint(&tmp_bf, &const_val->data.x_bigint);
8085 BigFloat orig_bf;
8086 switch (other_type->data.floating.bit_count) {
8087 case 16: {
8088 float16_t tmp = bigfloat_to_f16(&tmp_bf);
8089 bigfloat_init_16(&orig_bf, tmp);
8090 break;
8091 }
8092 case 32: {
8093 float tmp = bigfloat_to_f32(&tmp_bf);
8094 bigfloat_init_32(&orig_bf, tmp);
8095 break;
8096 }
8097 case 64: {
8098 double tmp = bigfloat_to_f64(&tmp_bf);
8099 bigfloat_init_64(&orig_bf, tmp);
8100 break;
8101 }
8102 case 80:
8103 zig_panic("TODO");
8104 case 128: {
8105 float128_t tmp = bigfloat_to_f128(&tmp_bf);
8106 bigfloat_init_128(&orig_bf, tmp);
8107 break;
8108 }
8109 default:
8110 zig_unreachable();
8111 }
8112 BigInt orig_bi;
8113 bigint_init_bigfloat(&orig_bi, &orig_bf);
8114 if (bigint_cmp(&orig_bi, &const_val->data.x_bigint) == CmpEQ) {
8115 return true;
8116 }
8117 Buf *val_buf = buf_alloc();
8118 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
8119 ir_add_error(ira, instruction,
8120 buf_sprintf("integer value %s has no representation in type '%s'",
8121 buf_ptr(val_buf),
8122 buf_ptr(&other_type->name)));
8123 return false;
8124 }
8125 if (other_type->data.floating.bit_count >= const_val->type->data.floating.bit_count) {
8126 return true;
8127 }
8128 switch (other_type->data.floating.bit_count) {
8129 case 16:
8130 switch (const_val->type->data.floating.bit_count) {
8131 case 32: {
8132 float16_t tmp = zig_double_to_f16(const_val->data.x_f32);
8133 float orig = zig_f16_to_double(tmp);
8134 if (const_val->data.x_f32 == orig) {
8135 return true;
8136 }
8137 break;
8138 }
8139 case 64: {
8140 float16_t tmp = zig_double_to_f16(const_val->data.x_f64);
8141 double orig = zig_f16_to_double(tmp);
8142 if (const_val->data.x_f64 == orig) {
8143 return true;
8144 }
8145 break;
8146 }
8147 case 80:
8148 zig_panic("TODO");
8149 case 128: {
8150 float16_t tmp = f128M_to_f16(&const_val->data.x_f128);
8151 float128_t orig;
8152 f16_to_f128M(tmp, &orig);
8153 if (f128M_eq(&orig, &const_val->data.x_f128)) {
8154 return true;
8155 }
8156 break;
8157 }
8158 default:
8159 zig_unreachable();
8160 }
8161 break;
8162 case 32:
8163 switch (const_val->type->data.floating.bit_count) {
8164 case 64: {
8165 float tmp = const_val->data.x_f64;
8166 double orig = tmp;
8167 if (const_val->data.x_f64 == orig) {
8168 return true;
8169 }
8170 break;
8171 }
8172 case 80:
8173 zig_panic("TODO");
8174 case 128: {
8175 float32_t tmp = f128M_to_f32(&const_val->data.x_f128);
8176 float128_t orig;
8177 f32_to_f128M(tmp, &orig);
8178 if (f128M_eq(&orig, &const_val->data.x_f128)) {
8179 return true;
8180 }
8181 break;
8182 }
8183 default:
8184 zig_unreachable();
8185 }
8186 break;
8187 case 64:
8188 switch (const_val->type->data.floating.bit_count) {
8189 case 80:
8190 zig_panic("TODO");
8191 case 128: {
8192 float64_t tmp = f128M_to_f64(&const_val->data.x_f128);
8193 float128_t orig;
8194 f64_to_f128M(tmp, &orig);
8195 if (f128M_eq(&orig, &const_val->data.x_f128)) {
8196 return true;
8197 }
8198 break;
8199 }
8200 default:
8201 zig_unreachable();
8202 }
8203 break;
8204 case 80:
8205 assert(const_val->type->data.floating.bit_count == 128);
8206 zig_panic("TODO");
8207 case 128:
8208 return true;
8209 default:
8210 zig_unreachable();
8211 }
8212 Buf *val_buf = buf_alloc();
8213 float_append_buf(val_buf, const_val);
8214 ir_add_error(ira, instruction,
8215 buf_sprintf("cast of value %s to type '%s' loses information",
8216 buf_ptr(val_buf),
8217 buf_ptr(&other_type->name)));
8218 return false;
8075 } else if (other_type->id == ZigTypeIdInt && const_val_is_int) {8219 } else if (other_type->id == ZigTypeIdInt && const_val_is_int) {
8076 if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {8220 if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
8077 Buf *val_buf = buf_alloc();8221 Buf *val_buf = buf_alloc();
...@@ -9453,11 +9597,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio...@@ -9453,11 +9597,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
9453 return const_instr;9597 return const_instr;
9454}9598}
94559599
9456enum UndefAllowed {
9457 UndefOk,
9458 UndefBad,
9459};
9460
9461static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {9600static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
9462 switch (value->value.special) {9601 switch (value->value.special) {
9463 case ConstValSpecialStatic:9602 case ConstValSpecialStatic:
...@@ -10370,6 +10509,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10370,6 +10509,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10370 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);10509 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
10371 }10510 }
1037210511
10512 // cast from T to ?T
10513 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
10514 if (wanted_type->id == ZigTypeIdOptional) {
10515 ZigType *wanted_child_type = wanted_type->data.maybe.child_type;
10516 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10517 false).id == ConstCastResultIdOk)
10518 {
10519 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10520 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10521 actual_type->id == ZigTypeIdComptimeFloat)
10522 {
10523 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10524 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10525 } else {
10526 return ira->codegen->invalid_instruction;
10527 }
10528 } else if (
10529 wanted_child_type->id == ZigTypeIdPointer &&
10530 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
10531 actual_type->id == ZigTypeIdPointer &&
10532 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10533 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
10534 {
10535 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10536 return ira->codegen->invalid_instruction;
10537 if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10538 return ira->codegen->invalid_instruction;
10539 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
10540 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
10541 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10542 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
10543 {
10544 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value,
10545 wanted_child_type);
10546 if (type_is_invalid(cast1->value.type))
10547 return ira->codegen->invalid_instruction;
10548 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
10549 }
10550 }
10551 }
10552
10553 // T to E!T
10554 if (wanted_type->id == ZigTypeIdErrorUnion) {
10555 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
10556 source_node, false).id == ConstCastResultIdOk)
10557 {
10558 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10559 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10560 actual_type->id == ZigTypeIdComptimeFloat)
10561 {
10562 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
10563 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10564 } else {
10565 return ira->codegen->invalid_instruction;
10566 }
10567 }
10568 }
10569
10570 // cast from T to E!?T
10571 if (wanted_type->id == ZigTypeIdErrorUnion &&
10572 wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional &&
10573 actual_type->id != ZigTypeIdOptional)
10574 {
10575 ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
10576 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk ||
10577 actual_type->id == ZigTypeIdNull ||
10578 actual_type->id == ZigTypeIdComptimeInt ||
10579 actual_type->id == ZigTypeIdComptimeFloat)
10580 {
10581 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
10582 if (type_is_invalid(cast1->value.type))
10583 return ira->codegen->invalid_instruction;
10584
10585 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
10586 if (type_is_invalid(cast2->value.type))
10587 return ira->codegen->invalid_instruction;
10588
10589 return cast2;
10590 }
10591 }
10592
10593
10594 // cast from comptime-known number to another number type
10595 if (instr_is_comptime(value) &&
10596 (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt ||
10597 actual_type->id == ZigTypeIdFloat || actual_type->id == ZigTypeIdComptimeFloat) &&
10598 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
10599 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
10600 {
10601 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10602 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
10603 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10604 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
10605 bigint_init_bigint(&result->value.data.x_bigint, &value->value.data.x_bigint);
10606 } else {
10607 float_init_bigint(&result->value.data.x_bigint, &value->value);
10608 }
10609 return result;
10610 } else if (wanted_type->id == ZigTypeIdComptimeFloat || wanted_type->id == ZigTypeIdFloat) {
10611 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10612 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
10613 BigFloat bf;
10614 bigfloat_init_bigint(&bf, &value->value.data.x_bigint);
10615 float_init_bigfloat(&result->value, &bf);
10616 } else {
10617 float_init_float(&result->value, &value->value);
10618 }
10619 return result;
10620 }
10621 zig_unreachable();
10622 } else {
10623 return ira->codegen->invalid_instruction;
10624 }
10625 }
10626
10373 // widening conversion10627 // widening conversion
10374 if (wanted_type->id == ZigTypeIdInt &&10628 if (wanted_type->id == ZigTypeIdInt &&
10375 actual_type->id == ZigTypeIdInt &&10629 actual_type->id == ZigTypeIdInt &&
...@@ -10472,47 +10726,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10472,47 +10726,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10472 }10726 }
1047310727
1047410728
10475 // cast from T to ?T
10476 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
10477 if (wanted_type->id == ZigTypeIdOptional) {
10478 ZigType *wanted_child_type = wanted_type->data.maybe.child_type;
10479 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10480 false).id == ConstCastResultIdOk)
10481 {
10482 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10483 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10484 actual_type->id == ZigTypeIdComptimeFloat)
10485 {
10486 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10487 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10488 } else {
10489 return ira->codegen->invalid_instruction;
10490 }
10491 } else if (
10492 wanted_child_type->id == ZigTypeIdPointer &&
10493 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
10494 actual_type->id == ZigTypeIdPointer &&
10495 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10496 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
10497 {
10498 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10499 return ira->codegen->invalid_instruction;
10500 if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10501 return ira->codegen->invalid_instruction;
10502 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
10503 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
10504 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10505 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
10506 {
10507 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value,
10508 wanted_child_type);
10509 if (type_is_invalid(cast1->value.type))
10510 return ira->codegen->invalid_instruction;
10511 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
10512 }
10513 }
10514 }
10515
10516 // cast from null literal to maybe type10729 // cast from null literal to maybe type
10517 if (wanted_type->id == ZigTypeIdOptional &&10730 if (wanted_type->id == ZigTypeIdOptional &&
10518 actual_type->id == ZigTypeIdNull)10731 actual_type->id == ZigTypeIdNull)
...@@ -10520,23 +10733,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10520,23 +10733,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10520 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);10733 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
10521 }10734 }
1052210735
10523 // cast from child type of error type to error type
10524 if (wanted_type->id == ZigTypeIdErrorUnion) {
10525 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
10526 source_node, false).id == ConstCastResultIdOk)
10527 {
10528 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10529 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10530 actual_type->id == ZigTypeIdComptimeFloat)
10531 {
10532 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
10533 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10534 } else {
10535 return ira->codegen->invalid_instruction;
10536 }
10537 }
10538 }
10539
10540 // cast from [N]T to E![]const T10736 // cast from [N]T to E![]const T
10541 if (wanted_type->id == ZigTypeIdErrorUnion &&10737 if (wanted_type->id == ZigTypeIdErrorUnion &&
10542 is_slice(wanted_type->data.error_union.payload_type) &&10738 is_slice(wanted_type->data.error_union.payload_type) &&
...@@ -10568,54 +10764,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10568,54 +10764,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10568 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);10764 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
10569 }10765 }
1057010766
10571 // cast from T to E!?T
10572 if (wanted_type->id == ZigTypeIdErrorUnion &&
10573 wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional &&
10574 actual_type->id != ZigTypeIdOptional)
10575 {
10576 ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
10577 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk ||
10578 actual_type->id == ZigTypeIdNull ||
10579 actual_type->id == ZigTypeIdComptimeInt ||
10580 actual_type->id == ZigTypeIdComptimeFloat)
10581 {
10582 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
10583 if (type_is_invalid(cast1->value.type))
10584 return ira->codegen->invalid_instruction;
10585
10586 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
10587 if (type_is_invalid(cast2->value.type))
10588 return ira->codegen->invalid_instruction;
10589
10590 return cast2;
10591 }
10592 }
10593
10594 // cast from number literal to another type
10595 if (actual_type->id == ZigTypeIdComptimeFloat ||
10596 actual_type->id == ZigTypeIdComptimeInt)
10597 {
10598 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10599 CastOp op;
10600 if ((actual_type->id == ZigTypeIdComptimeFloat &&
10601 wanted_type->id == ZigTypeIdFloat) ||
10602 (actual_type->id == ZigTypeIdComptimeInt &&
10603 wanted_type->id == ZigTypeIdInt))
10604 {
10605 op = CastOpNumLitToConcrete;
10606 } else if (wanted_type->id == ZigTypeIdInt) {
10607 op = CastOpFloatToInt;
10608 } else if (wanted_type->id == ZigTypeIdFloat) {
10609 op = CastOpIntToFloat;
10610 } else {
10611 zig_unreachable();
10612 }
10613 return ir_resolve_cast(ira, source_instr, value, wanted_type, op, false);
10614 } else {
10615 return ira->codegen->invalid_instruction;
10616 }
10617 }
10618
10619 // cast from typed number to integer or float literal.10767 // cast from typed number to integer or float literal.
10620 // works when the number is known at compile time10768 // works when the number is known at compile time
10621 if (instr_is_comptime(value) &&10769 if (instr_is_comptime(value) &&
...@@ -17878,7 +18026,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct...@@ -17878,7 +18026,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct
17878 if (type_is_invalid(dest_type))18026 if (type_is_invalid(dest_type))
17879 return ira->codegen->invalid_instruction;18027 return ira->codegen->invalid_instruction;
1788018028
17881 if (dest_type->id != ZigTypeIdInt) {18029 if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) {
17882 ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));18030 ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
17883 return ira->codegen->invalid_instruction;18031 return ira->codegen->invalid_instruction;
17884 }18032 }
...@@ -17887,20 +18035,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct...@@ -17887,20 +18035,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct
17887 if (type_is_invalid(target->value.type))18035 if (type_is_invalid(target->value.type))
17888 return ira->codegen->invalid_instruction;18036 return ira->codegen->invalid_instruction;
1788918037
17890 if (target->value.type->id == ZigTypeIdComptimeInt) {18038 if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) {
17891 if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) {
17892 return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpNumLitToConcrete, false);
17893 } else {
17894 return ira->codegen->invalid_instruction;
17895 }
17896 }
17897
17898 if (target->value.type->id != ZigTypeIdInt) {
17899 ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",18039 ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",
17900 buf_ptr(&target->value.type->name)));18040 buf_ptr(&target->value.type->name)));
17901 return ira->codegen->invalid_instruction;18041 return ira->codegen->invalid_instruction;
17902 }18042 }
1790318043
18044 if (instr_is_comptime(target)) {
18045 return ir_implicit_cast(ira, target, dest_type);
18046 }
18047
18048 if (dest_type->id == ZigTypeIdComptimeInt) {
18049 ir_add_error(ira, instruction->target, buf_sprintf("attempt to cast runtime value to '%s'",
18050 buf_ptr(&dest_type->name)));
18051 return ira->codegen->invalid_instruction;
18052 }
18053
17904 return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);18054 return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
17905}18055}
1790618056
test/cases/cast.zig+10
...@@ -452,3 +452,13 @@ test "implicit ptr to *c_void" {...@@ -452,3 +452,13 @@ test "implicit ptr to *c_void" {
452 var c: *u32 = @ptrCast(*u32, ptr2.?);452 var c: *u32 = @ptrCast(*u32, ptr2.?);
453 assert(c.* == 1);453 assert(c.* == 1);
454}454}
455
456test "@intCast to comptime_int" {
457 assert(@intCast(comptime_int, 0) == 0);
458}
459
460test "implicit cast comptime numbers to any type when the value fits" {
461 const a: u64 = 255;
462 var b: u8 = a;
463 assert(b == 255);
464}
test/compile_errors.zig+56-31
...@@ -1,6 +1,61 @@...@@ -1,6 +1,61 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.add(
5 "cast negative value to unsigned integer",
6 \\comptime {
7 \\ const value: i32 = -1;
8 \\ const unsigned = @intCast(u32, value);
9 \\}
10 \\export fn entry1() void {
11 \\ const value: i32 = -1;
12 \\ const unsigned: u32 = value;
13 \\}
14 ,
15 ".tmp_source.zig:3:36: error: cannot cast negative value -1 to unsigned integer type 'u32'",
16 ".tmp_source.zig:7:27: error: cannot cast negative value -1 to unsigned integer type 'u32'",
17 );
18
19 cases.add(
20 "integer cast truncates bits",
21 \\export fn entry1() void {
22 \\ const spartan_count: u16 = 300;
23 \\ const byte = @intCast(u8, spartan_count);
24 \\}
25 \\export fn entry2() void {
26 \\ const spartan_count: u16 = 300;
27 \\ const byte: u8 = spartan_count;
28 \\}
29 \\export fn entry3() void {
30 \\ var spartan_count: u16 = 300;
31 \\ var byte: u8 = spartan_count;
32 \\}
33 ,
34 ".tmp_source.zig:3:31: error: integer value 300 cannot be implicitly casted to type 'u8'",
35 ".tmp_source.zig:7:22: error: integer value 300 cannot be implicitly casted to type 'u8'",
36 ".tmp_source.zig:11:20: error: expected type 'u8', found 'u16'",
37 );
38
39 cases.add(
40 "comptime implicit cast f64 to f32",
41 \\export fn entry() void {
42 \\ const x: f64 = 16777217;
43 \\ const y: f32 = x;
44 \\}
45 ,
46 ".tmp_source.zig:3:20: error: cast of value 16777217.000000 to type 'f32' loses information",
47 );
48
49 cases.add(
50 "implicit cast from f64 to f32",
51 \\var x: f64 = 1.0;
52 \\var y: f32 = x;
53 \\
54 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
55 ,
56 ".tmp_source.zig:2:14: error: expected type 'f32', found 'f64'",
57 );
58
4 cases.add(59 cases.add(
5 "exceeded maximum bit width of integer",60 "exceeded maximum bit width of integer",
6 \\export fn entry1() void {61 \\export fn entry1() void {
...@@ -1819,7 +1874,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1819,7 +1874,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1819 \\ if (0) {}1874 \\ if (0) {}
1820 \\}1875 \\}
1821 ,1876 ,
1822 ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'",1877 ".tmp_source.zig:2:9: error: expected type 'bool', found 'comptime_int'",
1823 );1878 );
18241879
1825 cases.add(1880 cases.add(
...@@ -2422,16 +2477,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2422,16 +2477,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2422 ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'",2477 ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'",
2423 );2478 );
24242479
2425 cases.add(
2426 "implicit cast from f64 to f32",
2427 \\const x : f64 = 1.0;
2428 \\const y : f32 = x;
2429 \\
2430 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
2431 ,
2432 ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'",
2433 );
2434
2435 cases.add(2480 cases.add(
2436 "colliding invalid top level functions",2481 "colliding invalid top level functions",
2437 \\fn func() bogus {}2482 \\fn func() bogus {}
...@@ -4049,16 +4094,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4049,16 +4094,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4049 ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod",4094 ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod",
4050 );4095 );
40514096
4052 cases.add(
4053 "cast negative value to unsigned integer",
4054 \\comptime {
4055 \\ const value: i32 = -1;
4056 \\ const unsigned = @intCast(u32, value);
4057 \\}
4058 ,
4059 ".tmp_source.zig:3:22: error: attempt to cast negative value to unsigned integer",
4060 );
4061
4062 cases.add(4097 cases.add(
4063 "compile-time division by zero",4098 "compile-time division by zero",
4064 \\comptime {4099 \\comptime {
...@@ -4081,16 +4116,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4081,16 +4116,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4081 ".tmp_source.zig:4:17: error: division by zero",4116 ".tmp_source.zig:4:17: error: division by zero",
4082 );4117 );
40834118
4084 cases.add(
4085 "compile-time integer cast truncates bits",
4086 \\comptime {
4087 \\ const spartan_count: u16 = 300;
4088 \\ const byte = @intCast(u8, spartan_count);
4089 \\}
4090 ,
4091 ".tmp_source.zig:3:18: error: cast from 'u16' to 'u8' truncates bits",
4092 );
4093
4094 cases.add(4119 cases.add(
4095 "@setRuntimeSafety twice for same scope",4120 "@setRuntimeSafety twice for same scope",
4096 \\export fn foo() void {4121 \\export fn foo() void {