diff --git a/src/ir.cpp b/src/ir.cpp index f506fa093b..53c3d1e241 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7053,12 +7053,20 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) return ira->codegen->invalid_instruction; - if (val->data.x_bignum.is_negative && wanted_type->id == TypeTableEntryIdInt && - !wanted_type->data.integral.is_signed) - { - ir_add_error(ira, source_instr, - buf_sprintf("attempt to cast negative value to unsigned integer")); - return ira->codegen->invalid_instruction; + if (wanted_type->id == TypeTableEntryIdInt) { + if (val->data.x_bignum.is_negative && !wanted_type->data.integral.is_signed) { + ir_add_error(ira, source_instr, + buf_sprintf("attempt to cast negative value to unsigned integer")); + return ira->codegen->invalid_instruction; + } + if (!bignum_fits_in_bits(&val->data.x_bignum, wanted_type->data.integral.bit_count, + wanted_type->data.integral.is_signed)) + { + ir_add_error(ira, source_instr, + buf_sprintf("cast from '%s' to '%s' truncates bits", + buf_ptr(&target->value.type->name), buf_ptr(&wanted_type->name))); + return ira->codegen->invalid_instruction; + } } IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type); diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 87c8101ed0..d5d3d4958a 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -314,3 +314,11 @@ const global_array = { } result }; + +test "compile-time downcast when the bits fit" { + comptime { + const spartan_count: u16 = 255; + const byte = u8(spartan_count); + assert(byte == 255); + } +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 2ee7954209..1f1f215791 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1827,4 +1827,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} , ".tmp_source.zig:4:17: error: division by zero is undefined"); + + cases.add("compile-time integer cast truncates bits", + \\comptime { + \\ const spartan_count: u16 = 300; + \\ const byte = u8(spartan_count); + \\} + , + ".tmp_source.zig:3:20: error: cast from 'u16' to 'u8' truncates bits"); }