From 8bf3e1f8d0902abd4133e2729b3625c25011c3ff Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 26 May 2022 15:30:42 +0300 Subject: [PATCH] AstGen: preserve inferred ptr result loc for breaks --- src/AstGen.zig | 2 +- src/Sema.zig | 22 ++++++++++++++++++++++ test/behavior/basic.zig | 12 ++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index 30ed680226..ba27165cea 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -9915,7 +9915,7 @@ const GenZir = struct { .inferred_ptr => |ptr| { gz.rl_ty_inst = .none; gz.rl_ptr = ptr; - gz.break_result_loc = .{ .block_ptr = gz }; + gz.break_result_loc = parent_rl; }, .block_ptr => |parent_block_scope| { diff --git a/src/Sema.zig b/src/Sema.zig index 170f1e5631..38e5ce0836 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2881,6 +2881,28 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com if (var_is_mut) { try sema.validateVarType(block, ty_src, final_elem_ty, false); + + // The value might have been bitcasted into a comptime only + // pointer type such as `*@Type(.EnumLiteral)` so we must now + // update all the stores to not give backends invalid AIR. + + var air_tags = sema.air_instructions.items(.tag); + var air_data = sema.air_instructions.items(.data); + var peer_inst_index: usize = 0; + var i = ptr_inst; + while (i < air_tags.len and peer_inst_index < peer_inst_list.len) : (i += 1) { + if (air_tags[i] != .store) continue; + if (air_data[i].bin_op.rhs == peer_inst_list[peer_inst_index]) { + peer_inst_index += 1; + _ = (try sema.resolveMaybeUndefVal(block, .unneeded, air_data[i].bin_op.rhs)) orelse continue; + const coerced_val = try sema.coerce(block, final_elem_ty, air_data[i].bin_op.rhs, .unneeded); + air_tags = sema.air_instructions.items(.tag); + air_data = sema.air_instructions.items(.data); + + air_data[i].bin_op.lhs = ptr; + air_data[i].bin_op.rhs = coerced_val; + } + } } else ct: { // Detect if the value is comptime known. In such case, the // last 3 AIR instructions of the block will look like this: diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index d62ba75dee..adcba8721d 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -933,3 +933,15 @@ test "try in labeled block doesn't cast to wrong type" { }; _ = s; } + +test "comptime int in switch in catch is casted to correct inferred type" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + + var a: error{ A, B }!u64 = 0; + var b = a catch |err| switch (err) { + error.A => 0, + else => unreachable, + }; + _ = b; +}