authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-02-06 22:11:41+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-06 21:26:26-05:00
logfd1284ebd07ded1c67bbaff4c14f093051e56f59
tree3ceb66a3288aae5aa8495ff00e7af89c9561f134
parentadc9a282d8b3cbe58e07c965fe40fb1dd8666bd7

stage2: apply type coercion in if expressions

When setting the break value in an if expression we must explicitly check if a result location type coercion that needs to happen. This was already done for switch expression, so let's just imitate that check and fix for if expressions. To make this possible, we now also propagate `rl_ty_inst` to sub scopes.

2 files changed, 40 insertions(+), 8 deletions(-)

src/AstGen.zig+34-8
......@@ -5118,8 +5118,10 @@ fn setCondBrPayloadElideBlockStorePtr(
51185118 const astgen = then_scope.astgen;
51195119 const then_body = then_scope.instructionsSliceUpto(else_scope);
51205120 const else_body = else_scope.instructionsSlice();
5121 const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0));
5122 const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0));
5121 const has_then_break = then_break != 0;
5122 const has_else_break = else_break != 0;
5123 const then_body_len = @intCast(u32, then_body.len + @boolToInt(has_then_break));
5124 const else_body_len = @intCast(u32, else_body.len + @boolToInt(has_else_break));
51235125 try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
51245126 then_body_len + else_body_len);
51255127
......@@ -5135,26 +5137,49 @@ fn setCondBrPayloadElideBlockStorePtr(
51355137 const then_body_len_index = condbr_pl + 1;
51365138 const else_body_len_index = condbr_pl + 2;
51375139
5140 // The break instructions need to have their operands coerced if the
5141 // switch's result location is a `ty`. In this case we overwrite the
5142 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
5143 // it as the break operand.
51385144 for (then_body) |src_inst| {
5139 if (zir_tags[src_inst] == .store_to_block_ptr) {
5140 if (zir_datas[src_inst].bin.lhs == block_ptr) {
5145 if (zir_tags[src_inst] == .store_to_block_ptr and
5146 zir_datas[src_inst].bin.lhs == block_ptr)
5147 {
5148 if (then_scope.rl_ty_inst != .none and has_then_break) {
5149 zir_tags[src_inst] = .as;
5150 zir_datas[src_inst].bin = .{
5151 .lhs = then_scope.rl_ty_inst,
5152 .rhs = zir_datas[then_break].@"break".operand,
5153 };
5154 zir_datas[then_break].@"break".operand = indexToRef(src_inst);
5155 } else {
51415156 astgen.extra.items[then_body_len_index] -= 1;
51425157 continue;
51435158 }
51445159 }
51455160 astgen.extra.appendAssumeCapacity(src_inst);
51465161 }
5147 if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break);
5162 if (has_then_break) astgen.extra.appendAssumeCapacity(then_break);
5163
51485164 for (else_body) |src_inst| {
5149 if (zir_tags[src_inst] == .store_to_block_ptr) {
5150 if (zir_datas[src_inst].bin.lhs == block_ptr) {
5165 if (zir_tags[src_inst] == .store_to_block_ptr and
5166 zir_datas[src_inst].bin.lhs == block_ptr)
5167 {
5168 if (else_scope.rl_ty_inst != .none and has_else_break) {
5169 zir_tags[src_inst] = .as;
5170 zir_datas[src_inst].bin = .{
5171 .lhs = else_scope.rl_ty_inst,
5172 .rhs = zir_datas[else_break].@"break".operand,
5173 };
5174 zir_datas[else_break].@"break".operand = indexToRef(src_inst);
5175 } else {
51515176 astgen.extra.items[else_body_len_index] -= 1;
51525177 continue;
51535178 }
51545179 }
51555180 astgen.extra.appendAssumeCapacity(src_inst);
51565181 }
5157 if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break);
5182 if (has_else_break) astgen.extra.appendAssumeCapacity(else_break);
51585183}
51595184
51605185fn whileExpr(
......@@ -9460,6 +9485,7 @@ const GenZir = struct {
94609485 .decl_node_index = gz.decl_node_index,
94619486 .decl_line = gz.decl_line,
94629487 .parent = scope,
9488 .rl_ty_inst = gz.rl_ty_inst,
94639489 .astgen = gz.astgen,
94649490 .suspend_node = gz.suspend_node,
94659491 .nosuspend_node = gz.nosuspend_node,
test/behavior/basic.zig+6
......@@ -693,3 +693,9 @@ test "variable name containing underscores does not shadow int primitive" {
693693 _ = u6__4;
694694 _ = i2_04_8;
695695}
696
697test "if expression type coercion" {
698 var cond: bool = true;
699 const x: u16 = if (cond) 1 else 0;
700 try expect(@as(u16, x) == 1);
701}