diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 19242a5c42..fd44e11721 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -19563,6 +19563,18 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); } + if (src_type->id != ZigTypeIdComptimeInt) { + if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { + const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; + ir_add_error(ira, &target->base, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); + return ira->codegen->invalid_inst_gen; + } else if (src_type->data.integral.bit_count > 0 && src_type->data.integral.bit_count < dest_type->data.integral.bit_count) { + ir_add_error(ira, &target->base, buf_sprintf("type '%s' has fewer bits than destination type '%s'", + buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); + return ira->codegen->invalid_inst_gen; + } + } + if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (val == nullptr) @@ -19580,16 +19592,6 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc return result; } - if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { - const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; - ir_add_error(ira, &target->base, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); - return ira->codegen->invalid_inst_gen; - } else if (src_type->data.integral.bit_count < dest_type->data.integral.bit_count) { - ir_add_error(ira, &target->base, buf_sprintf("type '%s' has fewer bits than destination type '%s'", - buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); - return ira->codegen->invalid_inst_gen; - } - return ir_build_truncate_gen(ira, &instruction->base.base, dest_type, target); } diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig index 0d67c5d6dd..4adee38800 100644 --- a/test/behavior/truncate.zig +++ b/test/behavior/truncate.zig @@ -24,13 +24,34 @@ test "truncate.u0.var" { try expect(z == 0); } -test "truncate sign mismatch but comptime known so it works anyway" { - const x: u32 = 10; - var result = @truncate(i8, x); - try expect(result == 10); +test "truncate i0 to larger integer allowed and has comptime known result" { + var x: i0 = 0; + const y = @truncate(i8, x); + comptime try expect(y == 0); +} + +test "truncate.i0.literal" { + var z = @truncate(i0, 0); + try expect(z == 0); +} + +test "truncate.i0.const" { + const c0: isize = 0; + var z = @truncate(i0, c0); + try expect(z == 0); +} + +test "truncate.i0.var" { + var d: i8 = 2; + var z = @truncate(i0, d); + try expect(z == 0); } test "truncate on comptime integer" { var x = @truncate(u16, 9999); try expect(x == 9999); + var y = @truncate(u16, -21555); + try expect(y == 0xabcd); + var z = @truncate(i16, -65537); + try expect(z == -1); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index b2545d31f5..fd1255c5b8 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6031,14 +6031,27 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }); cases.add("truncate sign mismatch", - \\fn f() i8 { + \\export fn entry1() i8 { \\ var x: u32 = 10; \\ return @truncate(i8, x); \\} - \\ - \\export fn entry() usize { return @sizeOf(@TypeOf(f)); } + \\export fn entry2() u8 { + \\ var x: i32 = -10; + \\ return @truncate(u8, x); + \\} + \\export fn entry3() i8 { + \\ comptime var x: u32 = 10; + \\ return @truncate(i8, x); + \\} + \\export fn entry4() u8 { + \\ comptime var x: i32 = -10; + \\ return @truncate(u8, x); + \\} , &[_][]const u8{ "tmp.zig:3:26: error: expected signed integer type, found 'u32'", + "tmp.zig:7:26: error: expected unsigned integer type, found 'i32'", + "tmp.zig:11:26: error: expected signed integer type, found 'u32'", + "tmp.zig:15:26: error: expected unsigned integer type, found 'i32'", }); cases.add("try in function with non error return type",