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 {
66596659 {#header_close#}
66606660 {#header_open|Cast Negative Number to Unsigned Integer#}
66616661 <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'#}
66636663comptime {
66646664 const value: i32 = -1;
66656665 const unsigned = @intCast(u32, value);
......@@ -6681,7 +6681,7 @@ pub fn main() void {
66816681 {#header_close#}
66826682 {#header_open|Cast Truncates Data#}
66836683 <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'#}
66856685comptime {
66866686 const spartan_count: u16 = 300;
66876687 const byte = @intCast(u8, spartan_count);
src/ir.cpp+278-128
......@@ -138,6 +138,11 @@ struct ConstCastErrSetMismatch {
138138 ZigList<ErrorTableEntry *> missing_errors;
139139};
140140
141enum UndefAllowed {
142 UndefOk,
143 UndefBad,
144};
145
141146static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
142147static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);
143148static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
......@@ -157,6 +162,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
157162 ConstExprValue *out_val, ConstExprValue *ptr_val);
158163static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
159164 ZigType *dest_type, IrInstruction *dest_type_src);
165static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
160166
161167static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
162168 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
80638069 return false;
80648070 }
80658071
8066 ConstExprValue *const_val = &instruction->value;
8067 assert(const_val->special != ConstValSpecialRuntime);
8072 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);
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);
80738078 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;
80758219 } else if (other_type->id == ZigTypeIdInt && const_val_is_int) {
80768220 if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
80778221 Buf *val_buf = buf_alloc();
......@@ -9453,11 +9597,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
94539597 return const_instr;
94549598}
94559599
9456enum UndefAllowed {
9457 UndefOk,
9458 UndefBad,
9459};
9460
94619600static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
94629601 switch (value->value.special) {
94639602 case ConstValSpecialStatic:
......@@ -10370,6 +10509,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1037010509 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
1037110510 }
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
1037310627 // widening conversion
1037410628 if (wanted_type->id == ZigTypeIdInt &&
1037510629 actual_type->id == ZigTypeIdInt &&
......@@ -10472,47 +10726,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1047210726 }
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
1051610729 // cast from null literal to maybe type
1051710730 if (wanted_type->id == ZigTypeIdOptional &&
1051810731 actual_type->id == ZigTypeIdNull)
......@@ -10520,23 +10733,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1052010733 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
1052110734 }
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
1054010736 // cast from [N]T to E![]const T
1054110737 if (wanted_type->id == ZigTypeIdErrorUnion &&
1054210738 is_slice(wanted_type->data.error_union.payload_type) &&
......@@ -10568,54 +10764,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1056810764 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
1056910765 }
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
1061910767 // cast from typed number to integer or float literal.
1062010768 // works when the number is known at compile time
1062110769 if (instr_is_comptime(value) &&
......@@ -17878,7 +18026,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct
1787818026 if (type_is_invalid(dest_type))
1787918027 return ira->codegen->invalid_instruction;
1788018028
17881 if (dest_type->id != ZigTypeIdInt) {
18029 if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) {
1788218030 ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
1788318031 return ira->codegen->invalid_instruction;
1788418032 }
......@@ -17887,20 +18035,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct
1788718035 if (type_is_invalid(target->value.type))
1788818036 return ira->codegen->invalid_instruction;
1788918037
17890 if (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) {
18038 if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) {
1789918039 ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",
1790018040 buf_ptr(&target->value.type->name)));
1790118041 return ira->codegen->invalid_instruction;
1790218042 }
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
1790418054 return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
1790518055}
1790618056
test/cases/cast.zig+10
......@@ -452,3 +452,13 @@ test "implicit ptr to *c_void" {
452452 var c: *u32 = @ptrCast(*u32, ptr2.?);
453453 assert(c.* == 1);
454454}
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 @@
11const tests = @import("tests.zig");
22
33pub 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
459 cases.add(
560 "exceeded maximum bit width of integer",
661 \\export fn entry1() void {
......@@ -1819,7 +1874,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
18191874 \\ if (0) {}
18201875 \\}
18211876 ,
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'",
18231878 );
18241879
18251880 cases.add(
......@@ -2422,16 +2477,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
24222477 ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'",
24232478 );
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
24352480 cases.add(
24362481 "colliding invalid top level functions",
24372482 \\fn func() bogus {}
......@@ -4049,16 +4094,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
40494094 ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod",
40504095 );
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
40624097 cases.add(
40634098 "compile-time division by zero",
40644099 \\comptime {
......@@ -4081,16 +4116,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
40814116 ".tmp_source.zig:4:17: error: division by zero",
40824117 );
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
40944119 cases.add(
40954120 "@setRuntimeSafety twice for same scope",
40964121 \\export fn foo() void {