mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 00:44:32 +01:00
Sema: fix single-range switch prong capture
This kind of capture cannot always be comptime-known, assuming so caused access of undefined memory during payload capture analysis!
This commit is contained in:
parent
76dd39d531
commit
e2338edb47
2 changed files with 32 additions and 20 deletions
37
src/Sema.zig
37
src/Sema.zig
|
|
@ -10970,8 +10970,7 @@ fn analyzeSwitchBlock(
|
|||
.case_idx = index,
|
||||
} }),
|
||||
capture == .by_ref,
|
||||
is_special,
|
||||
if (!is_special) case_vals else undefined,
|
||||
if (is_special) .special else .{ .item_refs = &.{.fromValue(item_opv)} },
|
||||
if (is_inline) .fromValue(item_opv) else .none,
|
||||
validated_switch.else_err_ty,
|
||||
);
|
||||
|
|
@ -12569,11 +12568,7 @@ fn resolveSwitchProng(
|
|||
operand_src,
|
||||
capture_src,
|
||||
capture == .by_ref,
|
||||
kind == .special,
|
||||
switch (kind) {
|
||||
.item_refs => |item_refs| item_refs,
|
||||
.has_ranges, .special => undefined,
|
||||
},
|
||||
kind,
|
||||
inline_case_capture,
|
||||
else_err_ty,
|
||||
);
|
||||
|
|
@ -12702,11 +12697,7 @@ fn analyzeSwitchProng(
|
|||
operand_src,
|
||||
capture_src,
|
||||
capture == .by_ref,
|
||||
kind == .special,
|
||||
switch (kind) {
|
||||
.item_refs => |item_refs| item_refs,
|
||||
.has_ranges, .special => undefined,
|
||||
},
|
||||
kind,
|
||||
inline_case_capture,
|
||||
else_err_ty,
|
||||
);
|
||||
|
|
@ -12783,9 +12774,7 @@ fn analyzeSwitchPayloadCapture(
|
|||
operand_src: LazySrcLoc,
|
||||
capture_src: LazySrcLoc,
|
||||
capture_by_ref: bool,
|
||||
is_special_prong: bool,
|
||||
/// May be `undefined` if `is_special_prong` is `true`.
|
||||
case_vals: []const Air.Inst.Ref,
|
||||
kind: SwitchProngKind,
|
||||
/// If this is not `.none`, this is an inline capture.
|
||||
inline_case_capture: Air.Inst.Ref,
|
||||
else_err_ty: ?Type,
|
||||
|
|
@ -12829,7 +12818,7 @@ fn analyzeSwitchPayloadCapture(
|
|||
|
||||
const operand_ptr_ty = if (capture_by_ref) sema.typeOf(operand_ptr) else undefined;
|
||||
|
||||
if (is_special_prong) {
|
||||
if (kind == .special) {
|
||||
if (capture_by_ref) return operand_ptr;
|
||||
return switch (operand_ty.zigTypeTag(zcu)) {
|
||||
.error_set => e: {
|
||||
|
|
@ -12846,6 +12835,8 @@ fn analyzeSwitchPayloadCapture(
|
|||
|
||||
switch (operand_ty.zigTypeTag(zcu)) {
|
||||
.@"union" => {
|
||||
const case_vals = kind.item_refs;
|
||||
|
||||
const union_obj = zcu.typeToUnion(operand_ty).?;
|
||||
const first_item_val = sema.resolveConstDefinedValue(case_block, .unneeded, case_vals[0], undefined) catch unreachable;
|
||||
|
||||
|
|
@ -13141,6 +13132,7 @@ fn analyzeSwitchPayloadCapture(
|
|||
);
|
||||
}
|
||||
|
||||
const case_vals = kind.item_refs;
|
||||
if (case_vals.len == 1) {
|
||||
const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, case_vals[0], undefined) catch unreachable;
|
||||
const item_ty = try pt.singleErrorSetType(item_val.getErrorName(zcu).unwrap().?);
|
||||
|
|
@ -13161,11 +13153,16 @@ fn analyzeSwitchPayloadCapture(
|
|||
// switch condition. It is comptime-known if there is only one item.
|
||||
if (capture_by_ref) {
|
||||
return operand_ptr;
|
||||
} else if (case_vals.len == 1) {
|
||||
return case_vals[0];
|
||||
} else {
|
||||
return operand_val;
|
||||
}
|
||||
switch (kind) {
|
||||
.special => unreachable,
|
||||
.item_refs => |case_vals| {
|
||||
// If there's only a single item, the capture is comptime-known!
|
||||
if (case_vals.len == 1) return case_vals[0];
|
||||
},
|
||||
.has_ranges => {},
|
||||
}
|
||||
return operand_val;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1307,3 +1307,18 @@ test "single-item prong in switch on enum has comptime-known capture" {
|
|||
try E.doTheTest(.a);
|
||||
try comptime E.doTheTest(.a);
|
||||
}
|
||||
|
||||
test "single-range switch prong capture" {
|
||||
const S = struct {
|
||||
fn doTheTest(x: u8) !void {
|
||||
switch (x) {
|
||||
1...5 => |val| {
|
||||
try expect(val == 2);
|
||||
},
|
||||
else => return error.TestFailed,
|
||||
}
|
||||
}
|
||||
};
|
||||
try S.doTheTest(2);
|
||||
try comptime S.doTheTest(2);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue