authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-27 06:52:25+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-13 12:54:20+01:00
logec27524da9b4200dc9ea39285e9c4c30cad28a98
treef3335b774c49cd257de873e1cb6aba6e9e0107aa
parent00609e7edbbc949b12e29a8d9911d988b78d7e03
signaturelock-open Commit is signed but in an unrecognized format.

Sema: minor refactor to switch prong analysis


1 files changed, 263 insertions(+), 342 deletions(-)

src/Sema.zig+263-342
......@@ -10077,298 +10077,284 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1007710077 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);
1007810078}
1007910079
10080/// Resolve a switch prong which is determined at comptime to have no peers. Uses
10081/// `resolveBlockBody`. Sets up captures as needed.
10082fn resolveSwitchProngComptime(
10080/// Holds common data used when analyzing or resolving switch prong bodies,
10081/// including setting up captures.
10082const SwitchProngAnalysis = struct {
1008310083 sema: *Sema,
10084 /// The block containing the `switch_block` itself.
1008410085 parent_block: *Block,
10085 child_block: *Block,
10086 src: LazySrcLoc,
10086 /// The raw switch operand value (*not* the condition). Always defined.
1008710087 operand: Air.Inst.Ref,
10088 /// May be `undefined` if no prong has a by-ref capture.
1008810089 operand_ptr: Air.Inst.Ref,
10089 prong_type: enum { normal, special },
10090 prong_body: []const Zir.Inst.Index,
10091 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10092 raw_capture_src: Module.SwitchProngSrc,
10090 /// If this switch is on an error set, this is the type to assign to the
10091 /// `else` prong. If `null`, the prong should be unreachable.
1009310092 else_error_ty: ?Type,
10094 case_vals: []const Air.Inst.Ref,
10093 /// The index of the `switch_block` instruction itself.
1009510094 switch_block_inst: Zir.Inst.Index,
10096 merges: *Block.Merges,
10097) CompileError!Air.Inst.Ref {
10098 switch (capture) {
10099 .none => {
10100 return sema.resolveBlockBody(parent_block, src, child_block, prong_body, switch_block_inst, merges);
10101 },
1010210095
10103 .by_val, .by_ref => {
10104 const zir_datas = sema.code.instructions.items(.data);
10105 const switch_info = zir_datas[switch_block_inst].pl_node;
10106
10107 const capture_ref = try sema.analyzeSwitchCapture(
10108 child_block,
10109 capture == .by_ref,
10110 operand,
10111 operand_ptr,
10112 switch_info.src_node,
10113 prong_type == .special,
10114 raw_capture_src,
10115 else_error_ty,
10116 case_vals,
10117 );
10096 /// Resolve a switch prong which is determined at comptime to have no peers.
10097 /// Uses `resolveBlockBody`. Sets up captures as needed.
10098 fn resolveProngComptime(
10099 spa: SwitchProngAnalysis,
10100 child_block: *Block,
10101 prong_type: enum { normal, special },
10102 prong_body: []const Zir.Inst.Index,
10103 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10104 /// Must use the `scalar`, `special`, or `multi_capture` union field.
10105 raw_capture_src: Module.SwitchProngSrc,
10106 /// The set of all values which can reach this prong. May be undefined
10107 /// if the prong is special or contains ranges.
10108 case_vals: []const Air.Inst.Ref,
10109 merges: *Block.Merges,
10110 ) CompileError!Air.Inst.Ref {
10111 const sema = spa.sema;
10112 const src = sema.code.instructions.items(.data)[spa.switch_block_inst].pl_node.src();
10113 switch (capture) {
10114 .none => {
10115 return sema.resolveBlockBody(spa.parent_block, src, child_block, prong_body, spa.switch_block_inst, merges);
10116 },
10117
10118 .by_val, .by_ref => {
10119 const capture_ref = try spa.analyzeCapture(
10120 child_block,
10121 capture == .by_ref,
10122 prong_type == .special,
10123 raw_capture_src,
10124 case_vals,
10125 );
1011810126
10119 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10120 // This prong should be unreachable!
10121 return Air.Inst.Ref.unreachable_value;
10122 }
10127 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10128 // This prong should be unreachable!
10129 return Air.Inst.Ref.unreachable_value;
10130 }
1012310131
10124 sema.inst_map.putAssumeCapacity(switch_block_inst, capture_ref);
10125 defer assert(sema.inst_map.remove(switch_block_inst));
10132 sema.inst_map.putAssumeCapacity(spa.switch_block_inst, capture_ref);
10133 defer assert(sema.inst_map.remove(spa.switch_block_inst));
1012610134
10127 return sema.resolveBlockBody(parent_block, src, child_block, prong_body, switch_block_inst, merges);
10128 },
10135 return sema.resolveBlockBody(spa.parent_block, src, child_block, prong_body, spa.switch_block_inst, merges);
10136 },
10137 }
1012910138 }
10130}
10131
10132/// Analyze a switch prong which may have peers at runtime. Uses
10133/// `analyzeBodyRuntimeBreak`. Sets up captures as needed.
10134fn analyzeSwitchProngRuntime(
10135 sema: *Sema,
10136 case_block: *Block,
10137 operand: Air.Inst.Ref,
10138 operand_ptr: Air.Inst.Ref,
10139 prong_type: enum { normal, special },
10140 prong_body: []const Zir.Inst.Index,
10141 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10142 raw_capture_src: Module.SwitchProngSrc,
10143 else_error_ty: ?Type,
10144 case_vals: []const Air.Inst.Ref,
10145 switch_block_inst: Zir.Inst.Index,
10146) CompileError!void {
10147 switch (capture) {
10148 .none => {
10149 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10150 },
1015110139
10152 .by_val, .by_ref => {
10153 const zir_datas = sema.code.instructions.items(.data);
10154 const switch_info = zir_datas[switch_block_inst].pl_node;
10155
10156 const capture_ref = try sema.analyzeSwitchCapture(
10157 case_block,
10158 capture == .by_ref,
10159 operand,
10160 operand_ptr,
10161 switch_info.src_node,
10162 prong_type == .special,
10163 raw_capture_src,
10164 else_error_ty,
10165 case_vals,
10166 );
10140 /// Analyze a switch prong which may have peers at runtime.
10141 /// Uses `analyzeBodyRuntimeBreak`. Sets up captures as needed.
10142 fn analyzeProngRuntime(
10143 spa: SwitchProngAnalysis,
10144 case_block: *Block,
10145 prong_type: enum { normal, special },
10146 prong_body: []const Zir.Inst.Index,
10147 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10148 /// Must use the `scalar`, `special`, or `multi_capture` union field.
10149 raw_capture_src: Module.SwitchProngSrc,
10150 /// The set of all values which can reach this prong. May be undefined
10151 /// if the prong is special or contains ranges.
10152 case_vals: []const Air.Inst.Ref,
10153 ) CompileError!void {
10154 const sema = spa.sema;
10155 switch (capture) {
10156 .none => {
10157 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10158 },
10159
10160 .by_val, .by_ref => {
10161 const capture_ref = try spa.analyzeCapture(
10162 case_block,
10163 capture == .by_ref,
10164 prong_type == .special,
10165 raw_capture_src,
10166 case_vals,
10167 );
1016710168
10168 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10169 // No need to analyze any further, the prong is unreachable
10170 return;
10171 }
10169 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10170 // No need to analyze any further, the prong is unreachable
10171 return;
10172 }
1017210173
10173 sema.inst_map.putAssumeCapacity(switch_block_inst, capture_ref);
10174 defer assert(sema.inst_map.remove(switch_block_inst));
10174 sema.inst_map.putAssumeCapacity(spa.switch_block_inst, capture_ref);
10175 defer assert(sema.inst_map.remove(spa.switch_block_inst));
1017510176
10176 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10177 },
10177 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10178 },
10179 }
1017810180 }
10179}
1018010181
10181fn analyzeSwitchCapture(
10182 sema: *Sema,
10183 /// Must be the child block so that `inline_case_capture` is set for inline prongs.
10184 block: *Block,
10185 capture_byref: bool,
10186 /// The raw switch operand value.
10187 operand: Air.Inst.Ref,
10188 /// Pointer to the raw switch operand. May be undefined if `capture_byref` is false.
10189 operand_ptr: Air.Inst.Ref,
10190 switch_node_offset: i32,
10191 /// `true` if this is the `else` or `_` prong of a switch.
10192 is_special_prong: bool,
10193 /// Must use the `scalar`, `special`, or `multi_capture` union field.
10194 raw_capture_src: Module.SwitchProngSrc,
10195 /// If this is the `else` prong of a switch on an error set, this is the
10196 /// type that should be assigned to the capture. If `null`, the prong should
10197 /// be unreachable.
10198 else_error_ty: ?Type,
10199 /// The set of all values which can reach this prong. May be undefined if
10200 /// the prong has `is_special_prong` or contains ranges.
10201 case_vals: []const Air.Inst.Ref,
10202) CompileError!Air.Inst.Ref {
10203 const mod = sema.mod;
10204 const gpa = sema.gpa;
10205 const operand_ty = sema.typeOf(operand);
10206 const operand_ptr_ty = if (capture_byref) sema.typeOf(operand_ptr) else undefined;
10207 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset };
10208
10209 if (block.inline_case_capture != .none) {
10210 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, "") catch unreachable;
10211 if (operand_ty.zigTypeTag(mod) == .Union) {
10212 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, mod).?);
10213 const union_obj = mod.typeToUnion(operand_ty).?;
10214 const field_ty = union_obj.fields.values()[field_index].ty;
10215 if (capture_byref) {
10216 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_ptr| {
10182 fn analyzeCapture(
10183 spa: SwitchProngAnalysis,
10184 block: *Block,
10185 capture_byref: bool,
10186 is_special_prong: bool,
10187 raw_capture_src: Module.SwitchProngSrc,
10188 case_vals: []const Air.Inst.Ref,
10189 ) CompileError!Air.Inst.Ref {
10190 const sema = spa.sema;
10191 const mod = sema.mod;
10192
10193 const zir_datas = sema.code.instructions.items(.data);
10194 const switch_node_offset = zir_datas[spa.switch_block_inst].pl_node.src_node;
10195
10196 const operand_ty = sema.typeOf(spa.operand);
10197 const operand_ptr_ty = if (capture_byref) sema.typeOf(spa.operand_ptr) else undefined;
10198 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset };
10199
10200 if (block.inline_case_capture != .none) {
10201 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, "") catch unreachable;
10202 if (operand_ty.zigTypeTag(mod) == .Union) {
10203 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, mod).?);
10204 const union_obj = mod.typeToUnion(operand_ty).?;
10205 const field_ty = union_obj.fields.values()[field_index].ty;
10206 if (capture_byref) {
1021710207 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
1021810208 .pointee_type = field_ty,
1021910209 .mutable = operand_ptr_ty.ptrIsMutable(mod),
1022010210 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
1022110211 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
1022210212 });
10223 return sema.addConstant(
10224 ptr_field_ty,
10225 (try mod.intern(.{ .ptr = .{
10226 .ty = ptr_field_ty.toIntern(),
10227 .addr = .{ .field = .{
10228 .base = union_ptr.toIntern(),
10229 .index = field_index,
10230 } },
10231 } })).toValue(),
10232 );
10213 if (try sema.resolveDefinedValue(block, sema.src, spa.operand_ptr)) |union_ptr| {
10214 return sema.addConstant(
10215 ptr_field_ty,
10216 (try mod.intern(.{ .ptr = .{
10217 .ty = ptr_field_ty.toIntern(),
10218 .addr = .{ .field = .{
10219 .base = union_ptr.toIntern(),
10220 .index = field_index,
10221 } },
10222 } })).toValue(),
10223 );
10224 }
10225 return block.addStructFieldPtr(spa.operand_ptr, field_index, ptr_field_ty);
10226 } else {
10227 if (try sema.resolveDefinedValue(block, sema.src, spa.operand)) |union_val| {
10228 const tag_and_val = mod.intern_pool.indexToKey(union_val.toIntern()).un;
10229 return sema.addConstant(field_ty, tag_and_val.val.toValue());
10230 }
10231 return block.addStructFieldVal(spa.operand, field_index, field_ty);
1023310232 }
10234 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
10235 .pointee_type = field_ty,
10236 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10237 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10238 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
10239 });
10240 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);
10233 } else if (capture_byref) {
10234 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
1024110235 } else {
10242 if (try sema.resolveDefinedValue(block, sema.src, operand)) |union_val| {
10243 const tag_and_val = mod.intern_pool.indexToKey(union_val.toIntern()).un;
10244 return sema.addConstant(field_ty, tag_and_val.val.toValue());
10245 }
10246 return block.addStructFieldVal(operand, field_index, field_ty);
10236 return block.inline_case_capture;
1024710237 }
10248 } else if (capture_byref) {
10249 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
10250 } else {
10251 return block.inline_case_capture;
1025210238 }
10253 }
1025410239
10255 if (is_special_prong) {
10256 if (capture_byref) {
10257 return operand_ptr;
10258 }
10240 if (is_special_prong) {
10241 if (capture_byref) {
10242 return spa.operand_ptr;
10243 }
1025910244
10260 switch (operand_ty.zigTypeTag(mod)) {
10261 .ErrorSet => if (else_error_ty) |ty| {
10262 return sema.bitCast(block, ty, operand, operand_src, null);
10263 } else {
10264 try block.addUnreachable(false);
10265 return Air.Inst.Ref.unreachable_value;
10266 },
10267 else => return operand,
10245 switch (operand_ty.zigTypeTag(mod)) {
10246 .ErrorSet => if (spa.else_error_ty) |ty| {
10247 return sema.bitCast(block, ty, spa.operand, operand_src, null);
10248 } else {
10249 try block.addUnreachable(false);
10250 return Air.Inst.Ref.unreachable_value;
10251 },
10252 else => return spa.operand,
10253 }
1026810254 }
10269 }
1027010255
10271 switch (operand_ty.zigTypeTag(mod)) {
10272 .Union => {
10273 const union_obj = mod.typeToUnion(operand_ty).?;
10274 const first_item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10256 switch (operand_ty.zigTypeTag(mod)) {
10257 .Union => {
10258 const union_obj = mod.typeToUnion(operand_ty).?;
10259 const first_item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
1027510260
10276 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);
10277 const first_field = union_obj.fields.values()[first_field_index];
10261 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);
10262 const first_field = union_obj.fields.values()[first_field_index];
1027810263
10279 for (case_vals[1..], 0..) |item, i| {
10280 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
10264 for (case_vals[1..], 0..) |item, i| {
10265 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
1028110266
10282 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;
10283 const field = union_obj.fields.values()[field_index];
10284 if (!field.ty.eql(first_field.ty, mod)) {
10285 const msg = msg: {
10286 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10267 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;
10268 const field = union_obj.fields.values()[field_index];
10269 if (!field.ty.eql(first_field.ty, mod)) {
10270 const msg = msg: {
10271 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
1028710272
10288 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
10289 errdefer msg.destroy(gpa);
10273 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
10274 errdefer msg.destroy(sema.gpa);
1029010275
10291 // This must be a multi-prong so this must be a `multi_capture` src
10292 const multi_idx = raw_capture_src.multi_capture;
10276 // This must be a multi-prong so this must be a `multi_capture` src
10277 const multi_idx = raw_capture_src.multi_capture;
1029310278
10294 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 0 } };
10295 const first_item_src = raw_first_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .first);
10296 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 1 + @intCast(u32, i) } };
10297 const item_src = raw_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .first);
10298 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});
10299 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
10300 break :msg msg;
10301 };
10302 return sema.failWithOwnedErrorMsg(msg);
10279 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 0 } };
10280 const first_item_src = raw_first_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .first);
10281 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 1 + @intCast(u32, i) } };
10282 const item_src = raw_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .first);
10283 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});
10284 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
10285 break :msg msg;
10286 };
10287 return sema.failWithOwnedErrorMsg(msg);
10288 }
1030310289 }
10304 }
1030510290
10306 if (capture_byref) {
10307 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{
10308 .pointee_type = first_field.ty,
10309 .@"addrspace" = .generic,
10310 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10311 });
10291 if (capture_byref) {
10292 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{
10293 .pointee_type = first_field.ty,
10294 .@"addrspace" = .generic,
10295 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10296 });
1031210297
10313 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {
10314 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10315 .ty = field_ty_ptr.toIntern(),
10316 .addr = .{ .field = .{
10317 .base = op_ptr_val.toIntern(),
10318 .index = first_field_index,
10319 } },
10320 } })).toValue());
10298 if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |op_ptr_val| {
10299 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10300 .ty = field_ty_ptr.toIntern(),
10301 .addr = .{ .field = .{
10302 .base = op_ptr_val.toIntern(),
10303 .index = first_field_index,
10304 } },
10305 } })).toValue());
10306 }
10307 try sema.requireRuntimeBlock(block, operand_src, null);
10308 return block.addStructFieldPtr(spa.operand_ptr, first_field_index, field_ty_ptr);
1032110309 }
10322 try sema.requireRuntimeBlock(block, operand_src, null);
10323 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
10324 }
1032510310
10326 if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| {
10327 return sema.addConstant(
10328 first_field.ty,
10329 mod.intern_pool.indexToKey(operand_val.toIntern()).un.val.toValue(),
10330 );
10331 }
10332 try sema.requireRuntimeBlock(block, operand_src, null);
10333 return block.addStructFieldVal(operand, first_field_index, first_field.ty);
10334 },
10335 .ErrorSet => {
10336 if (capture_byref) {
10337 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10338 return sema.fail(
10339 block,
10340 capture_src,
10341 "error set cannot be captured by reference",
10342 .{},
10343 );
10344 }
10311 if (try sema.resolveDefinedValue(block, operand_src, spa.operand)) |operand_val| {
10312 return sema.addConstant(
10313 first_field.ty,
10314 mod.intern_pool.indexToKey(operand_val.toIntern()).un.val.toValue(),
10315 );
10316 }
10317 try sema.requireRuntimeBlock(block, operand_src, null);
10318 return block.addStructFieldVal(spa.operand, first_field_index, first_field.ty);
10319 },
10320 .ErrorSet => {
10321 if (capture_byref) {
10322 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10323 return sema.fail(
10324 block,
10325 capture_src,
10326 "error set cannot be captured by reference",
10327 .{},
10328 );
10329 }
1034510330
10346 if (case_vals.len == 1) {
10347 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10348 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
10349 return sema.bitCast(block, item_ty, operand, operand_src, null);
10350 }
10331 if (case_vals.len == 1) {
10332 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10333 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
10334 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
10335 }
1035110336
10352 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10353 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
10354 for (case_vals) |err| {
10355 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
10356 names.putAssumeCapacityNoClobber(err_val.getErrorName(mod).unwrap().?, {});
10357 }
10358 const error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10359 return sema.bitCast(block, error_ty, operand, operand_src, null);
10360 },
10361 else => {
10362 // In this case the capture value is just the passed-through value
10363 // of the switch condition.
10364 if (capture_byref) {
10365 return operand_ptr;
10366 } else {
10367 return operand;
10368 }
10369 },
10337 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10338 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
10339 for (case_vals) |err| {
10340 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
10341 names.putAssumeCapacityNoClobber(err_val.getErrorName(mod).unwrap().?, {});
10342 }
10343 const error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10344 return sema.bitCast(block, error_ty, spa.operand, operand_src, null);
10345 },
10346 else => {
10347 // In this case the capture value is just the passed-through value
10348 // of the switch condition.
10349 if (capture_byref) {
10350 return spa.operand_ptr;
10351 } else {
10352 return spa.operand;
10353 }
10354 },
10355 }
1037010356 }
10371}
10357};
1037210358
1037310359fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1037410360 const mod = sema.mod;
......@@ -11075,6 +11061,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1107511061 }),
1107611062 }
1107711063
11064 const spa: SwitchProngAnalysis = .{
11065 .sema = sema,
11066 .parent_block = block,
11067 .operand = raw_operand.val,
11068 .operand_ptr = raw_operand.ptr,
11069 .else_error_ty = else_error_ty,
11070 .switch_block_inst = inst,
11071 };
11072
1107811073 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
1107911074 try sema.air_instructions.append(gpa, .{
1108011075 .tag = .block,
......@@ -11129,19 +11124,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1112911124 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
1113011125 if (info.is_inline) child_block.inline_case_capture = operand;
1113111126 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11132 return sema.resolveSwitchProngComptime(
11133 block,
11127 return spa.resolveProngComptime(
1113411128 &child_block,
11135 src,
11136 raw_operand.val,
11137 raw_operand.ptr,
1113811129 .normal,
1113911130 body,
1114011131 info.capture,
1114111132 .{ .scalar = @intCast(u32, scalar_i) },
11142 else_error_ty,
1114311133 &.{item},
11144 inst,
1114511134 merges,
1114611135 );
1114711136 }
......@@ -11168,19 +11157,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1116811157 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
1116911158 if (info.is_inline) child_block.inline_case_capture = operand;
1117011159 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11171 return sema.resolveSwitchProngComptime(
11172 block,
11160 return spa.resolveProngComptime(
1117311161 &child_block,
11174 src,
11175 raw_operand.val,
11176 raw_operand.ptr,
1117711162 .normal,
1117811163 body,
1117911164 info.capture,
1118011165 .{ .multi_capture = @intCast(u32, multi_i) },
11181 else_error_ty,
1118211166 items,
11183 inst,
1118411167 merges,
1118511168 );
1118611169 }
......@@ -11200,19 +11183,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1120011183 {
1120111184 if (info.is_inline) child_block.inline_case_capture = operand;
1120211185 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11203 return sema.resolveSwitchProngComptime(
11204 block,
11186 return spa.resolveProngComptime(
1120511187 &child_block,
11206 src,
11207 raw_operand.val,
11208 raw_operand.ptr,
1120911188 .normal,
1121011189 body,
1121111190 info.capture,
1121211191 .{ .multi_capture = @intCast(u32, multi_i) },
11213 else_error_ty,
11214 undefined,
11215 inst,
11192 undefined, // case_vals may be undefined for ranges
1121611193 merges,
1121711194 );
1121811195 }
......@@ -11227,19 +11204,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1122711204 return Air.Inst.Ref.void_value;
1122811205 }
1122911206
11230 return sema.resolveSwitchProngComptime(
11231 block,
11207 return spa.resolveProngComptime(
1123211208 &child_block,
11233 src,
11234 raw_operand.val,
11235 raw_operand.ptr,
1123611209 .special,
1123711210 special.body,
1123811211 special.capture,
1123911212 .special,
11240 else_error_ty,
11241 undefined,
11242 inst,
11213 undefined, // case_vals may be undefined for special prongs
1124311214 merges,
1124411215 );
1124511216 }
......@@ -11262,19 +11233,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1126211233 try sema.addSafetyCheck(block, ok, .corrupt_switch);
1126311234 }
1126411235
11265 return sema.resolveSwitchProngComptime(
11266 block,
11236 return spa.resolveProngComptime(
1126711237 &child_block,
11268 src,
11269 raw_operand.val,
11270 raw_operand.ptr,
1127111238 .special,
1127211239 special.body,
1127311240 special.capture,
1127411241 .special,
11275 else_error_ty,
11276 undefined,
11277 inst,
11242 undefined, // case_vals may be undefined for special prongs
1127811243 merges,
1127911244 );
1128011245 }
......@@ -11328,17 +11293,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1132811293 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
1132911294 // nothing to do here
1133011295 } else if (analyze_body) {
11331 try sema.analyzeSwitchProngRuntime(
11296 try spa.analyzeProngRuntime(
1133211297 &case_block,
11333 raw_operand.val,
11334 raw_operand.ptr,
1133511298 .normal,
1133611299 body,
1133711300 info.capture,
1133811301 .{ .scalar = @intCast(u32, scalar_i) },
11339 else_error_ty,
1134011302 &.{item},
11341 inst,
1134211303 );
1134311304 } else {
1134411305 _ = try case_block.addNoOp(.unreach);
......@@ -11422,17 +11383,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1142211383 };
1142311384 emit_bb = true;
1142411385
11425 try sema.analyzeSwitchProngRuntime(
11386 try spa.analyzeProngRuntime(
1142611387 &case_block,
11427 raw_operand.val,
11428 raw_operand.ptr,
1142911388 .normal,
1143011389 body,
1143111390 info.capture,
1143211391 .{ .multi_capture = multi_i },
11433 else_error_ty,
11434 undefined,
11435 inst,
11392 undefined, // case_vals may be undefined for ranges
1143611393 );
1143711394
1143811395 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
......@@ -11469,17 +11426,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1146911426 emit_bb = true;
1147011427
1147111428 if (analyze_body) {
11472 try sema.analyzeSwitchProngRuntime(
11429 try spa.analyzeProngRuntime(
1147311430 &case_block,
11474 raw_operand.val,
11475 raw_operand.ptr,
1147611431 .normal,
1147711432 body,
1147811433 info.capture,
1147911434 .{ .multi_capture = multi_i },
11480 else_error_ty,
1148111435 &.{item},
11482 inst,
1148311436 );
1148411437 } else {
1148511438 _ = try case_block.addNoOp(.unreach);
......@@ -11518,17 +11471,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1151811471 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
1151911472 // nothing to do here
1152011473 } else if (analyze_body) {
11521 try sema.analyzeSwitchProngRuntime(
11474 try spa.analyzeProngRuntime(
1152211475 &case_block,
11523 raw_operand.val,
11524 raw_operand.ptr,
1152511476 .normal,
1152611477 body,
1152711478 info.capture,
1152811479 .{ .multi_capture = multi_i },
11529 else_error_ty,
1153011480 items,
11531 inst,
1153211481 );
1153311482 } else {
1153411483 _ = try case_block.addNoOp(.unreach);
......@@ -11607,17 +11556,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1160711556 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
1160811557 // nothing to do here
1160911558 } else {
11610 try sema.analyzeSwitchProngRuntime(
11559 try spa.analyzeProngRuntime(
1161111560 &case_block,
11612 raw_operand.val,
11613 raw_operand.ptr,
1161411561 .normal,
1161511562 body,
1161611563 info.capture,
1161711564 .{ .multi_capture = multi_i },
11618 else_error_ty,
1161911565 items,
11620 inst,
1162111566 );
1162211567 }
1162311568
......@@ -11677,17 +11622,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1167711622 emit_bb = true;
1167811623
1167911624 if (analyze_body) {
11680 try sema.analyzeSwitchProngRuntime(
11625 try spa.analyzeProngRuntime(
1168111626 &case_block,
11682 raw_operand.val,
11683 raw_operand.ptr,
1168411627 .special,
1168511628 special.body,
1168611629 special.capture,
1168711630 .special,
11688 else_error_ty,
1168911631 &.{item_ref},
11690 inst,
1169111632 );
1169211633 } else {
1169311634 _ = try case_block.addNoOp(.unreach);
......@@ -11724,17 +11665,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1172411665 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1172511666 emit_bb = true;
1172611667
11727 try sema.analyzeSwitchProngRuntime(
11668 try spa.analyzeProngRuntime(
1172811669 &case_block,
11729 raw_operand.val,
11730 raw_operand.ptr,
1173111670 .special,
1173211671 special.body,
1173311672 special.capture,
1173411673 .special,
11735 else_error_ty,
1173611674 &.{item_ref},
11737 inst,
1173811675 );
1173911676
1174011677 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
......@@ -11758,17 +11695,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1175811695 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1175911696 emit_bb = true;
1176011697
11761 try sema.analyzeSwitchProngRuntime(
11698 try spa.analyzeProngRuntime(
1176211699 &case_block,
11763 raw_operand.val,
11764 raw_operand.ptr,
1176511700 .special,
1176611701 special.body,
1176711702 special.capture,
1176811703 .special,
11769 else_error_ty,
1177011704 &.{item_ref},
11771 inst,
1177211705 );
1177311706
1177411707 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
......@@ -11789,17 +11722,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1178911722 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1179011723 emit_bb = true;
1179111724
11792 try sema.analyzeSwitchProngRuntime(
11725 try spa.analyzeProngRuntime(
1179311726 &case_block,
11794 raw_operand.val,
11795 raw_operand.ptr,
1179611727 .special,
1179711728 special.body,
1179811729 special.capture,
1179911730 .special,
11800 else_error_ty,
1180111731 &.{Air.Inst.Ref.bool_true},
11802 inst,
1180311732 );
1180411733
1180511734 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
......@@ -11818,17 +11747,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1181811747 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
1181911748 emit_bb = true;
1182011749
11821 try sema.analyzeSwitchProngRuntime(
11750 try spa.analyzeProngRuntime(
1182211751 &case_block,
11823 raw_operand.val,
11824 raw_operand.ptr,
1182511752 .special,
1182611753 special.body,
1182711754 special.capture,
1182811755 .special,
11829 else_error_ty,
1183011756 &.{Air.Inst.Ref.bool_false},
11831 inst,
1183211757 );
1183311758
1183411759 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);
......@@ -11872,17 +11797,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1187211797 {
1187311798 // nothing to do here
1187411799 } else if (special.body.len != 0 and analyze_body and !special.is_inline) {
11875 try sema.analyzeSwitchProngRuntime(
11800 try spa.analyzeProngRuntime(
1187611801 &case_block,
11877 raw_operand.val,
11878 raw_operand.ptr,
1187911802 .special,
1188011803 special.body,
1188111804 special.capture,
1188211805 .special,
11883 else_error_ty,
11884 undefined,
11885 inst,
11806 undefined, // case_vals may be undefined for special prongs
1188611807 );
1188711808 } else {
1188811809 // We still need a terminator in this block, but we have proven