Skip to content

Commit 05b445a

Browse files
committed
Sema: add missing coercion to bool for condbr_inline
Also, start using labeled switch statements when dispatching maybe-runtime instructions like condbr to comptime-only variants like condbr_inline. This can't be merged until we get a zig1.wasm update due to #21385. Resolves: #21405
1 parent e9f3d18 commit 05b445a

File tree

2 files changed

+33
-92
lines changed

2 files changed

+33
-92
lines changed

src/Sema.zig

Lines changed: 27 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ fn analyzeBodyInner(
10431043
}, inst });
10441044
}
10451045

1046-
const air_inst: Air.Inst.Ref = switch (tags[@intFromEnum(inst)]) {
1046+
const air_inst: Air.Inst.Ref = inst: switch (tags[@intFromEnum(inst)]) {
10471047
// zig fmt: off
10481048
.alloc => try sema.zirAlloc(block, inst),
10491049
.alloc_inferred => try sema.zirAllocInferred(block, true),
@@ -1591,56 +1591,19 @@ fn analyzeBodyInner(
15911591
try sema.zirSwitchContinue(block, inst);
15921592
break;
15931593
},
1594-
.loop => blk: {
1595-
if (!block.is_comptime) break :blk try sema.zirLoop(block, inst);
1596-
// Same as `block_inline`. TODO https://github.com/ziglang/zig/issues/8220
1597-
const inst_data = datas[@intFromEnum(inst)].pl_node;
1598-
const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1599-
const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
16001594

1601-
// Create a temporary child block so that this loop is properly
1602-
// labeled for any .restore_err_ret_index instructions
1603-
var child_block = block.makeSubBlock();
1595+
.loop => if (block.is_comptime) {
1596+
continue :inst .block_inline;
1597+
} else try sema.zirLoop(block, inst),
16041598

1605-
var label: Block.Label = .{
1606-
.zir_block = inst,
1607-
.merges = undefined,
1608-
};
1609-
child_block.label = &label;
1610-
1611-
// Write these instructions directly into the parent block
1612-
child_block.instructions = block.instructions;
1613-
defer block.instructions = child_block.instructions;
1614-
1615-
const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
1616-
break :blk result;
1617-
},
1618-
.block, .block_comptime => blk: {
1619-
if (!block.is_comptime) {
1620-
break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
1621-
}
1622-
// Same as `block_inline`. TODO https://github.com/ziglang/zig/issues/8220
1623-
const inst_data = datas[@intFromEnum(inst)].pl_node;
1624-
const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1625-
const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
1599+
.block => if (block.is_comptime) {
1600+
continue :inst .block_inline;
1601+
} else try sema.zirBlock(block, inst, false),
16261602

1627-
// Create a temporary child block so that this block is properly
1628-
// labeled for any .restore_err_ret_index instructions
1629-
var child_block = block.makeSubBlock();
1603+
.block_comptime => if (block.is_comptime) {
1604+
continue :inst .block_inline;
1605+
} else try sema.zirBlock(block, inst, true),
16301606

1631-
var label: Block.Label = .{
1632-
.zir_block = inst,
1633-
.merges = undefined,
1634-
};
1635-
child_block.label = &label;
1636-
1637-
// Write these instructions directly into the parent block
1638-
child_block.instructions = block.instructions;
1639-
defer block.instructions = child_block.instructions;
1640-
1641-
const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
1642-
break :blk result;
1643-
},
16441607
.block_inline => blk: {
16451608
// Directly analyze the block body without introducing a new block.
16461609
// However, in the case of a corresponding break_inline which reaches
@@ -1749,32 +1712,13 @@ fn analyzeBodyInner(
17491712
return error.ComptimeBreak;
17501713
}
17511714
},
1752-
.condbr => blk: {
1753-
if (!block.is_comptime) {
1754-
try sema.zirCondbr(block, inst);
1755-
break;
1756-
}
1757-
// Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220
1758-
const inst_data = datas[@intFromEnum(inst)].pl_node;
1759-
const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node });
1760-
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
1761-
const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len);
1762-
const else_body = sema.code.bodySlice(
1763-
extra.end + then_body.len,
1764-
extra.data.else_body_len,
1765-
);
1766-
const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, .{
1767-
.needed_comptime_reason = "condition in comptime branch must be comptime-known",
1768-
.block_comptime_reason = block.comptime_reason,
1769-
});
1770-
const inline_body = if (cond.toBool()) then_body else else_body;
1771-
1772-
try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1773-
1774-
const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1775-
break :blk result;
1715+
.condbr => if (block.is_comptime) {
1716+
continue :inst .condbr_inline;
1717+
} else {
1718+
try sema.zirCondbr(block, inst);
1719+
break;
17761720
},
1777-
.condbr_inline => blk: {
1721+
.condbr_inline => {
17781722
const inst_data = datas[@intFromEnum(inst)].pl_node;
17791723
const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node });
17801724
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
@@ -1783,18 +1727,20 @@ fn analyzeBodyInner(
17831727
extra.end + then_body.len,
17841728
extra.data.else_body_len,
17851729
);
1786-
const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, .{
1730+
const uncasted_cond = try sema.resolveInst(extra.data.condition);
1731+
const cond = try sema.coerce(block, Type.bool, uncasted_cond, cond_src);
1732+
const cond_val = try sema.resolveConstDefinedValue(block, cond_src, cond, .{
17871733
.needed_comptime_reason = "condition in comptime branch must be comptime-known",
17881734
.block_comptime_reason = block.comptime_reason,
17891735
});
1790-
const inline_body = if (cond.toBool()) then_body else else_body;
1736+
const inline_body = if (cond_val.toBool()) then_body else else_body;
17911737

17921738
try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
17931739
const old_runtime_index = block.runtime_index;
17941740
defer block.runtime_index = old_runtime_index;
17951741

17961742
const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1797-
break :blk result;
1743+
break :inst result;
17981744
},
17991745
.@"try" => blk: {
18001746
if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
@@ -2251,18 +2197,6 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val
22512197
return val;
22522198
}
22532199

2254-
/// Returns a compile error if the value has tag `variable`.
2255-
fn resolveInstConst(
2256-
sema: *Sema,
2257-
block: *Block,
2258-
src: LazySrcLoc,
2259-
zir_ref: Zir.Inst.Ref,
2260-
reason: NeededComptimeReason,
2261-
) CompileError!Value {
2262-
const air_ref = try sema.resolveInst(zir_ref);
2263-
return sema.resolveConstDefinedValue(block, src, air_ref, reason);
2264-
}
2265-
22662200
/// Value Tag may be `undef` or `variable`.
22672201
pub fn resolveFinalDeclValue(
22682202
sema: *Sema,
@@ -26824,12 +26758,14 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2682426758
} else if (extra.data.bits.has_ret_ty_ref) blk: {
2682526759
const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
2682626760
extra_index += 1;
26827-
const ret_ty_val = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{
26761+
const ret_ty_air_ref = sema.resolveInst(ret_ty_ref) catch |err| switch (err) {
26762+
error.GenericPoison => break :blk Type.generic_poison,
26763+
else => |e| return e,
26764+
};
26765+
const ret_ty_val = sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{
2682826766
.needed_comptime_reason = "return type must be comptime-known",
2682926767
}) catch |err| switch (err) {
26830-
error.GenericPoison => {
26831-
break :blk Type.generic_poison;
26832-
},
26768+
error.GenericPoison => break :blk Type.generic_poison,
2683326769
else => |e| return e,
2683426770
};
2683526771
break :blk ret_ty_val.toType();
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
export fn f() void {
1+
export fn foo() void {
22
if (0) {}
33
}
44

5+
export fn bar() void {
6+
comptime if (0) {};
7+
}
8+
59
// error
610
// backend=stage2
711
// target=native
812
//
913
// :2:9: error: expected type 'bool', found 'comptime_int'
14+
// :6:18: error: expected type 'bool', found 'comptime_int'

0 commit comments

Comments
 (0)