Commit 8bf3e1f8d0

Veikka Tuominen <git@vexu.eu>
2022-05-26 14:30:42
AstGen: preserve inferred ptr result loc for breaks
1 parent e08cdad
Changed files (3)
src
test
behavior
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| {
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:
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;
+}