diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-07-14 18:10:54 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-07-14 18:11:46 -0700 |
| commit | 04572f6e341e6ff19877d1ae3b79e3baa653e652 (patch) | |
| tree | 07b91717329efb36bd8c8bd266b047fff60692ff | |
| parent | d7711ec9532d4c38bf1911f5c0ed2c813705ae15 (diff) | |
| download | zig-04572f6e341e6ff19877d1ae3b79e3baa653e652.tar.gz zig-04572f6e341e6ff19877d1ae3b79e3baa653e652.zip | |
Sema: fix coerceResultPtr
It did not handle properly when the dummy operand was a comptime_int; it
was crashing in coerce because comptime_int is supposed to be
comptime-known. So when calling coerceResultPtr, we pass the actual
operand, not a dummy operand, which means it will have the proper
comptime value when necessary.
| -rw-r--r-- | src/Sema.zig | 42 | ||||
| -rw-r--r-- | test/behavior/array.zig | 5 | ||||
| -rw-r--r-- | test/behavior/if.zig | 16 |
3 files changed, 39 insertions, 24 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index d4de78e5d1..92df7a6b1f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2030,7 +2030,8 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE defer trash_block.instructions.deinit(sema.gpa); const dummy_ptr = try trash_block.addTy(.alloc, sema.typeOf(ptr)); - return coerceResultPtr(sema, block, src, ptr, dummy_ptr, pointee_ty, &trash_block); + const dummy_operand = try trash_block.addBitCast(pointee_ty, .void_value); + return coerceResultPtr(sema, block, src, ptr, dummy_ptr, dummy_operand, &trash_block); } fn coerceResultPtr( @@ -2039,13 +2040,14 @@ fn coerceResultPtr( src: LazySrcLoc, ptr: Air.Inst.Ref, dummy_ptr: Air.Inst.Ref, - pointee_ty: Type, + dummy_operand: Air.Inst.Ref, trash_block: *Block, ) CompileError!Air.Inst.Ref { const target = sema.mod.getTarget(); const addr_space = target_util.defaultAddressSpace(target, .local); + const pointee_ty = sema.typeOf(dummy_operand); + const prev_trash_len = trash_block.instructions.items.len; - const dummy_operand = try trash_block.addBitCast(pointee_ty, .void_value); try sema.storePtr2(trash_block, src, dummy_ptr, src, dummy_operand, src, .bitcast); { @@ -2078,21 +2080,24 @@ fn coerceResultPtr( while (true) { const air_tags = sema.air_instructions.items(.tag); const air_datas = sema.air_instructions.items(.data); + + if (trash_block.instructions.items.len == prev_trash_len) { + if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| { + return sema.addConstant(ptr_ty, ptr_val); + } + if (pointee_ty.eql(Type.@"null", sema.mod)) { + const opt_ty = sema.typeOf(new_ptr).childType(); + const null_inst = try sema.addConstant(opt_ty, Value.@"null"); + _ = try block.addBinOp(.store, new_ptr, null_inst); + return Air.Inst.Ref.void_value; + } + return sema.bitCast(block, ptr_ty, new_ptr, src); + } + const trash_inst = trash_block.instructions.pop(); + switch (air_tags[trash_inst]) { .bitcast => { - if (Air.indexToRef(trash_inst) == dummy_operand) { - if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| { - return sema.addConstant(ptr_ty, ptr_val); - } - if (pointee_ty.eql(Type.@"null", sema.mod)) { - const opt_ty = sema.typeOf(new_ptr).childType(); - const null_inst = try sema.addConstant(opt_ty, Value.@"null"); - _ = try block.addBinOp(.store, new_ptr, null_inst); - return Air.Inst.Ref.void_value; - } - return sema.bitCast(block, ptr_ty, new_ptr, src); - } const ty_op = air_datas[trash_inst].ty_op; const operand_ty = sema.typeOf(ty_op.operand); const ptr_operand_ty = try Type.ptr(sema.arena, sema.mod, .{ @@ -3309,8 +3314,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com defer bitcast_block.instructions.deinit(gpa); trash_block.instructions.shrinkRetainingCapacity(empty_trash_count); - const pointee_ty = sema.typeOf(peer_inst_list[i]); - const sub_ptr = try coerceResultPtr(sema, &bitcast_block, src, ptr, dummy_ptr, pointee_ty, &trash_block); + const sub_ptr = try coerceResultPtr(sema, &bitcast_block, src, ptr, dummy_ptr, peer_inst_list[i], &trash_block); assert(bitcast_block.instructions.items.len > 0); // If only one instruction is produced then we can replace the bitcast @@ -4190,7 +4194,7 @@ fn storeToInferredAlloc( .stored_inst = operand, .placeholder = Air.refToIndex(bitcasted_ptr).?, }); - return sema.storePtr(block, src, bitcasted_ptr, operand); + return sema.storePtr2(block, src, bitcasted_ptr, src, operand, src, .bitcast); } fn storeToInferredAllocComptime( @@ -21707,8 +21711,6 @@ fn storePtr2( if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null) return; - // TODO handle if the element type requires comptime - if (air_tag == .bitcast) { // `air_tag == .bitcast` is used as a special case for `zirCoerceResultPtr` // to avoid calling `requireRuntimeBlock` for the dummy block. diff --git a/test/behavior/array.zig b/test/behavior/array.zig index aea4dd357b..b99ac27651 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -570,10 +570,7 @@ test "type coercion of pointer to anon struct literal to pointer to array" { } test "array with comptime only element type" { - const a = [_]type{ - u32, - i32, - }; + const a = [_]type{ u32, i32 }; try testing.expect(a[0] == u32); try testing.expect(a[1] == i32); } diff --git a/test/behavior/if.zig b/test/behavior/if.zig index 7618363474..8117c1db3f 100644 --- a/test/behavior/if.zig +++ b/test/behavior/if.zig @@ -140,3 +140,19 @@ test "if-else expression with runtime condition result location is inferred opti const e = if (d) A{ .b = 15, .c = 30 } else null; try expect(e != null); } + +test "result location with inferred type ends up being pointer to comptime_int" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + + var a: ?u32 = 1234; + var b: u32 = 2000; + var c = if (a) |d| blk: { + if (d < b) break :blk @as(u32, 1); + break :blk 0; + } else @as(u32, 0); + try expect(c == 1); +} |
