Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 27 additions & 91 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ fn analyzeBodyInner(
}, inst });
}

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

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

var label: Block.Label = .{
.zir_block = inst,
.merges = undefined,
};
child_block.label = &label;

// Write these instructions directly into the parent block
child_block.instructions = block.instructions;
defer block.instructions = child_block.instructions;

const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
break :blk result;
},
.block, .block_comptime => blk: {
if (!block.is_comptime) {
break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
}
// Same as `block_inline`. TODO https://github.com/ziglang/zig/issues/8220
const inst_data = datas[@intFromEnum(inst)].pl_node;
const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
.block => if (block.is_comptime) {
continue :inst .block_inline;
} else try sema.zirBlock(block, inst, false),

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

var label: Block.Label = .{
.zir_block = inst,
.merges = undefined,
};
child_block.label = &label;

// Write these instructions directly into the parent block
child_block.instructions = block.instructions;
defer block.instructions = child_block.instructions;

const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
break :blk result;
},
.block_inline => blk: {
// Directly analyze the block body without introducing a new block.
// However, in the case of a corresponding break_inline which reaches
Expand Down Expand Up @@ -1749,32 +1712,13 @@ fn analyzeBodyInner(
return error.ComptimeBreak;
}
},
.condbr => blk: {
if (!block.is_comptime) {
try sema.zirCondbr(block, inst);
break;
}
// Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220
const inst_data = datas[@intFromEnum(inst)].pl_node;
const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node });
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len);
const else_body = sema.code.bodySlice(
extra.end + then_body.len,
extra.data.else_body_len,
);
const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, .{
.needed_comptime_reason = "condition in comptime branch must be comptime-known",
.block_comptime_reason = block.comptime_reason,
});
const inline_body = if (cond.toBool()) then_body else else_body;

try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);

const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
break :blk result;
.condbr => if (block.is_comptime) {
continue :inst .condbr_inline;
} else {
try sema.zirCondbr(block, inst);
break;
},
.condbr_inline => blk: {
.condbr_inline => {
const inst_data = datas[@intFromEnum(inst)].pl_node;
const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node });
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
Expand All @@ -1783,18 +1727,20 @@ fn analyzeBodyInner(
extra.end + then_body.len,
extra.data.else_body_len,
);
const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, .{
const uncasted_cond = try sema.resolveInst(extra.data.condition);
const cond = try sema.coerce(block, Type.bool, uncasted_cond, cond_src);
const cond_val = try sema.resolveConstDefinedValue(block, cond_src, cond, .{
.needed_comptime_reason = "condition in comptime branch must be comptime-known",
.block_comptime_reason = block.comptime_reason,
});
const inline_body = if (cond.toBool()) then_body else else_body;
const inline_body = if (cond_val.toBool()) then_body else else_body;

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

const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
break :blk result;
break :inst result;
},
.@"try" => blk: {
if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
Expand Down Expand Up @@ -2251,18 +2197,6 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val
return val;
}

/// Returns a compile error if the value has tag `variable`.
fn resolveInstConst(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
zir_ref: Zir.Inst.Ref,
reason: NeededComptimeReason,
) CompileError!Value {
const air_ref = try sema.resolveInst(zir_ref);
return sema.resolveConstDefinedValue(block, src, air_ref, reason);
}

/// Value Tag may be `undef` or `variable`.
pub fn resolveFinalDeclValue(
sema: *Sema,
Expand Down Expand Up @@ -26824,12 +26758,14 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_ret_ty_ref) blk: {
const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
const ret_ty_val = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{
const ret_ty_air_ref = sema.resolveInst(ret_ty_ref) catch |err| switch (err) {
error.GenericPoison => break :blk Type.generic_poison,
else => |e| return e,
};
const ret_ty_val = sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{
.needed_comptime_reason = "return type must be comptime-known",
}) catch |err| switch (err) {
error.GenericPoison => {
break :blk Type.generic_poison;
},
error.GenericPoison => break :blk Type.generic_poison,
else => |e| return e,
};
break :blk ret_ty_val.toType();
Expand Down
7 changes: 6 additions & 1 deletion test/cases/compile_errors/if_condition_is_bool_not_int.zig
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
export fn f() void {
export fn foo() void {
if (0) {}
}

export fn bar() void {
comptime if (0) {};
}

// error
// backend=stage2
// target=native
//
// :2:9: error: expected type 'bool', found 'comptime_int'
// :6:18: error: expected type 'bool', found 'comptime_int'
Loading