AstGen: fix loop result locations
The main problem was that the loop body was treated as an expression that was one of the peer result values of a loop, when in reality the loop body is noreturn and only the `break` operands are the result values of loops. This was solved by introducing an override that prevents rvalue() from emitting a store to result location instruction for loop bodies. An orthogonal change also included in this commit is switching `elem_val` index expressions to using `coerced_ty` and doing the coercion to `usize` inside `Sema`, resulting in smaller ZIR (since the cast becomes implied). I also changed the break operand expression to use `reachableExpr`, introducing a new compile error for double break. This makes a few more behavior tests pass for `while` and `for` loops.
This commit is contained in:
@@ -236,3 +236,33 @@ test "while on error union with else result follow break prong" {
|
||||
} else |_| @as(i32, 2);
|
||||
try expect(result == 10);
|
||||
}
|
||||
|
||||
test "while bool 2 break statements and an else" {
|
||||
const S = struct {
|
||||
fn entry(t: bool, f: bool) !void {
|
||||
var ok = false;
|
||||
ok = while (t) {
|
||||
if (f) break false;
|
||||
if (t) break true;
|
||||
} else false;
|
||||
try expect(ok);
|
||||
}
|
||||
};
|
||||
try S.entry(true, false);
|
||||
comptime try S.entry(true, false);
|
||||
}
|
||||
|
||||
test "while optional 2 break statements and an else" {
|
||||
const S = struct {
|
||||
fn entry(opt_t: ?bool, f: bool) !void {
|
||||
var ok = false;
|
||||
ok = while (opt_t) |t| {
|
||||
if (f) break false;
|
||||
if (t) break true;
|
||||
} else false;
|
||||
try expect(ok);
|
||||
}
|
||||
};
|
||||
try S.entry(true, false);
|
||||
comptime try S.entry(true, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user