Skip to content

Commit 747849c

Browse files
authored
Merge pull request #2309 from FnControlOption/noreturn
Improve type resolution of unlabeled blocks
2 parents b5c2200 + 8567894 commit 747849c

3 files changed

Lines changed: 78 additions & 7 deletions

File tree

src/analysis.zig

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,10 +2193,17 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
21932193
if (std.mem.eql(u8, call_name, "@src")) {
21942194
return analyser.instanceStdBuiltinType("SourceLocation");
21952195
}
2196+
21962197
if (std.mem.eql(u8, call_name, "@compileError")) {
21972198
return .{ .data = .{ .compile_error = node_handle }, .is_type_val = false };
21982199
}
21992200

2201+
if (std.mem.eql(u8, call_name, "@panic") or
2202+
std.mem.eql(u8, call_name, "@trap"))
2203+
{
2204+
return Type.fromIP(analyser, .noreturn_type, null);
2205+
}
2206+
22002207
if (std.mem.eql(u8, call_name, "@Vector")) {
22012208
if (params.len != 2) return null;
22022209

@@ -2414,16 +2421,21 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
24142421
.block_two,
24152422
.block_two_semicolon,
24162423
=> {
2417-
const has_zero_statements = switch (tree.nodeTag(node)) {
2418-
.block_two, .block_two_semicolon => tree.nodeData(node).opt_node_and_opt_node[0] == .none,
2419-
.block, .block_semicolon => false,
2420-
else => unreachable,
2421-
};
2422-
if (has_zero_statements) {
2424+
var buffer: [2]Ast.Node.Index = undefined;
2425+
const statements = tree.blockStatements(&buffer, node).?;
2426+
if (statements.len == 0) {
24232427
return Type.fromIP(analyser, .void_type, .void_value);
24242428
}
24252429

2426-
const label_token = ast.blockLabel(tree, node) orelse return null;
2430+
const label_token = ast.blockLabel(tree, node) orelse {
2431+
const last_statement = statements[statements.len - 1];
2432+
if (try analyser.resolveTypeOfNodeInternal(.of(last_statement, handle))) |ty| {
2433+
if (ty.typeOf(analyser).isNoreturnType()) {
2434+
return Type.fromIP(analyser, .noreturn_type, null);
2435+
}
2436+
}
2437+
return Type.fromIP(analyser, .void_type, .void_value);
2438+
};
24272439
const block_label = offsets.identifierTokenToNameSlice(tree, label_token);
24282440

24292441
// TODO: peer type resolution based on all `break` statements
@@ -3381,6 +3393,15 @@ pub const Type = struct {
33813393
};
33823394
}
33833395

3396+
pub fn isNoreturnType(self: Type) bool {
3397+
if (!self.is_type_val) return false;
3398+
return switch (self.data) {
3399+
.compile_error => true,
3400+
.ip_index => |payload| payload.index == .noreturn_type,
3401+
else => false,
3402+
};
3403+
}
3404+
33843405
pub fn typeDefinitionToken(self: Type) !?TokenWithHandle {
33853406
return switch (self.data) {
33863407
.container => |scope_handle| .{

tests/analysis/block.zig

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const empty_block = {};
2+
// ^^^^^^^^^^^ (void)()
3+
4+
// zig fmt: off
5+
const void_block = { _ = 1; };
6+
// ^^^^^^^^^^ (void)()
7+
8+
const compile_error_block = { @compileError("foo"); };
9+
// ^^^^^^^^^^^^^^^^^^^ (noreturn)()
10+
11+
const panic_block = { @panic("foo"); };
12+
// ^^^^^^^^^^^ (noreturn)()
13+
14+
const labeled_block_0 = blk: { break :blk @as(i32, 1); };
15+
// ^^^^^^^^^^^^^^^ (i32)()
16+
17+
// TODO this should be `i64`
18+
const labeled_block_1 = blk: {
19+
// ^^^^^^^^^^^^^^^ (i32)()
20+
if (false) break :blk @as(i32, 1);
21+
break :blk @as(i64, 2);
22+
};
23+
// zig fmt: on
24+
25+
pub fn main() void {
26+
const return_block = {
27+
return;
28+
};
29+
_ = return_block;
30+
// ^^^^^^^^^^^^ (noreturn)()
31+
32+
for (0..1) |_| {
33+
const break_block = {
34+
break;
35+
};
36+
_ = break_block;
37+
// ^^^^^^^^^^^ (noreturn)()
38+
39+
const continue_block = {
40+
continue;
41+
};
42+
_ = continue_block;
43+
// ^^^^^^^^^^^^^^ (noreturn)()
44+
}
45+
}

tests/analysis/builtins.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ const abs_vector_i8 = @abs(@as(@Vector(4, i8), undefined));
111111
const abs_vector_u8 = @abs(@as(@Vector(4, u8), undefined));
112112
// ^^^^^^^^^^^^^ (@Vector(4,u8))()
113113

114+
const panic = @panic("foo");
115+
// ^^^^^ (noreturn)()
116+
const trap = @trap();
117+
// ^^^^ (noreturn)()
118+
114119
comptime {
115120
// Use @compileLog to verify the expected type with the compiler
116121
// @compileLog(vector_builtin_13);

0 commit comments

Comments
 (0)