Skip to content

Commit fbe03d5

Browse files
Resolve type of labeled switch from break statements
1 parent b95b65a commit fbe03d5

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

src/analysis.zig

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,7 @@ const FindBreaks = struct {
18271827
try context.break_operands.append(context.allocator, operand.unwrap() orelse return);
18281828
} else if (context.label) |label| {
18291829
if (opt_label_token.unwrap()) |label_token| {
1830-
if (std.mem.eql(u8, label, tree.tokenSlice(label_token))) {
1830+
if (std.mem.eql(u8, label, offsets.identifierTokenToNameSlice(tree, label_token))) {
18311831
try context.break_operands.append(context.allocator, operand.unwrap() orelse return);
18321832
}
18331833
}
@@ -2496,6 +2496,21 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
24962496
=> {
24972497
const switch_node = tree.switchFull(node);
24982498

2499+
// TODO: peer type resolution based on all `break` statements and `switch` cases
2500+
if (switch_node.label_token) |label_token| {
2501+
var context: FindBreaks = .{
2502+
.label = offsets.identifierTokenToNameSlice(tree, label_token),
2503+
.allow_unlabeled = false,
2504+
.allocator = analyser.gpa,
2505+
};
2506+
defer context.deinit();
2507+
try context.findBreakOperands(tree, node);
2508+
for (context.break_operands.items) |operand| {
2509+
if (try analyser.resolveTypeOfNodeInternal(.of(operand, handle))) |operand_type|
2510+
return operand_type;
2511+
}
2512+
}
2513+
24992514
var either: std.ArrayList(Type.TypeWithDescriptor) = .empty;
25002515
for (switch_node.ast.cases) |case| {
25012516
const switch_case = tree.fullSwitchCase(case).?;
@@ -2547,7 +2562,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
25472562
return else_type;
25482563

25492564
var context: FindBreaks = .{
2550-
.label = if (loop.label_token) |token| tree.tokenSlice(token) else null,
2565+
.label = if (loop.label_token) |token| offsets.identifierTokenToNameSlice(tree, token) else null,
25512566
.allow_unlabeled = true,
25522567
.allocator = analyser.gpa,
25532568
};

tests/analysis/switch.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,12 @@ const switch_null_inline = switch (null) {
115115
// ^ (@TypeOf(null))() TODO this should be `unknown`
116116
// ^ (unknown)()
117117
};
118+
119+
// zig fmt: off
120+
const labeled_switch = blk: switch (some_u8) {
121+
// ^^^^^^^^^^^^^^ (u8)()
122+
'x' => |a| break :blk a,
123+
'y' => |a| break :blk a,
124+
else => |a| break :blk a,
125+
};
126+
// zig fmt: on

0 commit comments

Comments
 (0)