Treat blocks with "return" as "noreturn"

Block statements that end with "break" should not be considered
"noreturn" for the enclosing scope, but other "noreturn" instructions
(return, panic, compile error, etc.) should be. This differentiation
necessitates handling "break" differently from the other "noreturn"
instructions when inside a block statement.
This commit is contained in:
Gregory Anders 2022-06-06 04:13:52 -06:00 committed by GitHub
parent 33826a6a2e
commit 135b91aecd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 0 deletions

View File

@ -1967,6 +1967,9 @@ fn blockExpr(
}
try blockExprStmts(gz, scope, statements);
if (gz.endsWithNoReturn() and !gz.endsWithBreak()) {
return Zir.Inst.Ref.unreachable_value;
}
return rvalue(gz, rl, .void_value, block_node);
}
@ -9930,6 +9933,13 @@ const GenZir = struct {
return tags[last_inst].isNoReturn();
}
fn endsWithBreak(gz: GenZir) bool {
if (gz.isEmpty()) return false;
const tags = gz.astgen.instructions.items(.tag);
const last_inst = gz.instructions.items[gz.instructions.items.len - 1];
return tags[last_inst].isBreak();
}
/// TODO all uses of this should be replaced with uses of `endsWithNoReturn`.
fn refIsNoReturn(gz: GenZir, inst_ref: Zir.Inst.Ref) bool {
if (inst_ref == .unreachable_value) return true;

View File

@ -1250,6 +1250,19 @@ pub const Inst = struct {
};
}
/// Returns whether the instruction is a "break". This differs from
/// isNoReturn because a "break" in a block statement is not a
/// "noreturn" for the outer scope, whereas the other "noreturn"
/// instructions are.
pub fn isBreak(tag: Tag) bool {
return switch (tag) {
.@"break",
.break_inline,
=> true,
else => false,
};
}
/// AstGen uses this to find out if `Ref.void_value` should be used in place
/// of the result of a given instruction. This allows Sema to forego adding
/// the instruction to the map after analysis.

View File

@ -0,0 +1,14 @@
export fn entry() void {
{
return;
}
return;
}
// error
// target=native
//
// :6:5: error: unreachable code
// :2:5: note: control flow is diverted here