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...@@ -10077,298 +10077,284 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10077 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);10077 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true);
10078}10078}
1007910079
10080/// Resolve a switch prong which is determined at comptime to have no peers. Uses10080/// Holds common data used when analyzing or resolving switch prong bodies,
10081/// `resolveBlockBody`. Sets up captures as needed.10081/// including setting up captures.
10082fn resolveSwitchProngComptime(10082const SwitchProngAnalysis = struct {
10083 sema: *Sema,10083 sema: *Sema,
10084 /// The block containing the `switch_block` itself.
10084 parent_block: *Block,10085 parent_block: *Block,
10085 child_block: *Block,10086 /// The raw switch operand value (*not* the condition). Always defined.
10086 src: LazySrcLoc,
10087 operand: Air.Inst.Ref,10087 operand: Air.Inst.Ref,
10088 /// May be `undefined` if no prong has a by-ref capture.
10088 operand_ptr: Air.Inst.Ref,10089 operand_ptr: Air.Inst.Ref,
10089 prong_type: enum { normal, special },10090 /// If this switch is on an error set, this is the type to assign to the
10090 prong_body: []const Zir.Inst.Index,10091 /// `else` prong. If `null`, the prong should be unreachable.
10091 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10092 raw_capture_src: Module.SwitchProngSrc,
10093 else_error_ty: ?Type,10092 else_error_ty: ?Type,
10094 case_vals: []const Air.Inst.Ref,10093 /// The index of the `switch_block` instruction itself.
10095 switch_block_inst: Zir.Inst.Index,10094 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 => {10096 /// Resolve a switch prong which is determined at comptime to have no peers.
10104 const zir_datas = sema.code.instructions.items(.data);10097 /// Uses `resolveBlockBody`. Sets up captures as needed.
10105 const switch_info = zir_datas[switch_block_inst].pl_node;10098 fn resolveProngComptime(
1010610099 spa: SwitchProngAnalysis,
10107 const capture_ref = try sema.analyzeSwitchCapture(10100 child_block: *Block,
10108 child_block,10101 prong_type: enum { normal, special },
10109 capture == .by_ref,10102 prong_body: []const Zir.Inst.Index,
10110 operand,10103 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10111 operand_ptr,10104 /// Must use the `scalar`, `special`, or `multi_capture` union field.
10112 switch_info.src_node,10105 raw_capture_src: Module.SwitchProngSrc,
10113 prong_type == .special,10106 /// The set of all values which can reach this prong. May be undefined
10114 raw_capture_src,10107 /// if the prong is special or contains ranges.
10115 else_error_ty,10108 case_vals: []const Air.Inst.Ref,
10116 case_vals,10109 merges: *Block.Merges,
10117 );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)) {10127 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10120 // This prong should be unreachable!10128 // This prong should be unreachable!
10121 return Air.Inst.Ref.unreachable_value;10129 return Air.Inst.Ref.unreachable_value;
10122 }10130 }
1012310131
10124 sema.inst_map.putAssumeCapacity(switch_block_inst, capture_ref);10132 sema.inst_map.putAssumeCapacity(spa.switch_block_inst, capture_ref);
10125 defer assert(sema.inst_map.remove(switch_block_inst));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);10135 return sema.resolveBlockBody(spa.parent_block, src, child_block, prong_body, spa.switch_block_inst, merges);
10128 },10136 },
10137 }
10129 }10138 }
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 => {10140 /// Analyze a switch prong which may have peers at runtime.
10153 const zir_datas = sema.code.instructions.items(.data);10141 /// Uses `analyzeBodyRuntimeBreak`. Sets up captures as needed.
10154 const switch_info = zir_datas[switch_block_inst].pl_node;10142 fn analyzeProngRuntime(
1015510143 spa: SwitchProngAnalysis,
10156 const capture_ref = try sema.analyzeSwitchCapture(10144 case_block: *Block,
10157 case_block,10145 prong_type: enum { normal, special },
10158 capture == .by_ref,10146 prong_body: []const Zir.Inst.Index,
10159 operand,10147 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
10160 operand_ptr,10148 /// Must use the `scalar`, `special`, or `multi_capture` union field.
10161 switch_info.src_node,10149 raw_capture_src: Module.SwitchProngSrc,
10162 prong_type == .special,10150 /// The set of all values which can reach this prong. May be undefined
10163 raw_capture_src,10151 /// if the prong is special or contains ranges.
10164 else_error_ty,10152 case_vals: []const Air.Inst.Ref,
10165 case_vals,10153 ) CompileError!void {
10166 );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 if (sema.typeOf(capture_ref).isNoReturn(sema.mod)) {
10169 // No need to analyze any further, the prong is unreachable10170 // No need to analyze any further, the prong is unreachable
10170 return;10171 return;
10171 }10172 }
1017210173
10173 sema.inst_map.putAssumeCapacity(switch_block_inst, capture_ref);10174 sema.inst_map.putAssumeCapacity(spa.switch_block_inst, capture_ref);
10174 defer assert(sema.inst_map.remove(switch_block_inst));10175 defer assert(sema.inst_map.remove(spa.switch_block_inst));
1017510176
10176 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);10177 return sema.analyzeBodyRuntimeBreak(case_block, prong_body);
10177 },10178 },
10179 }
10178 }10180 }
10179}
1018010181
10181fn analyzeSwitchCapture(10182 fn analyzeCapture(
10182 sema: *Sema,10183 spa: SwitchProngAnalysis,
10183 /// Must be the child block so that `inline_case_capture` is set for inline prongs.10184 block: *Block,
10184 block: *Block,10185 capture_byref: bool,
10185 capture_byref: bool,10186 is_special_prong: bool,
10186 /// The raw switch operand value.10187 raw_capture_src: Module.SwitchProngSrc,
10187 operand: Air.Inst.Ref,10188 case_vals: []const Air.Inst.Ref,
10188 /// Pointer to the raw switch operand. May be undefined if `capture_byref` is false.10189 ) CompileError!Air.Inst.Ref {
10189 operand_ptr: Air.Inst.Ref,10190 const sema = spa.sema;
10190 switch_node_offset: i32,10191 const mod = sema.mod;
10191 /// `true` if this is the `else` or `_` prong of a switch.10192
10192 is_special_prong: bool,10193 const zir_datas = sema.code.instructions.items(.data);
10193 /// Must use the `scalar`, `special`, or `multi_capture` union field.10194 const switch_node_offset = zir_datas[spa.switch_block_inst].pl_node.src_node;
10194 raw_capture_src: Module.SwitchProngSrc,10195
10195 /// If this is the `else` prong of a switch on an error set, this is the10196 const operand_ty = sema.typeOf(spa.operand);
10196 /// type that should be assigned to the capture. If `null`, the prong should10197 const operand_ptr_ty = if (capture_byref) sema.typeOf(spa.operand_ptr) else undefined;
10197 /// be unreachable.10198 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset };
10198 else_error_ty: ?Type,10199
10199 /// The set of all values which can reach this prong. May be undefined if10200 if (block.inline_case_capture != .none) {
10200 /// the prong has `is_special_prong` or contains ranges.10201 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, "") catch unreachable;
10201 case_vals: []const Air.Inst.Ref,10202 if (operand_ty.zigTypeTag(mod) == .Union) {
10202) CompileError!Air.Inst.Ref {10203 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, mod).?);
10203 const mod = sema.mod;10204 const union_obj = mod.typeToUnion(operand_ty).?;
10204 const gpa = sema.gpa;10205 const field_ty = union_obj.fields.values()[field_index].ty;
10205 const operand_ty = sema.typeOf(operand);10206 if (capture_byref) {
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| {
10217 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{10207 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
10218 .pointee_type = field_ty,10208 .pointee_type = field_ty,
10219 .mutable = operand_ptr_ty.ptrIsMutable(mod),10209 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10220 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),10210 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10221 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),10211 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
10222 });10212 });
10223 return sema.addConstant(10213 if (try sema.resolveDefinedValue(block, sema.src, spa.operand_ptr)) |union_ptr| {
10224 ptr_field_ty,10214 return sema.addConstant(
10225 (try mod.intern(.{ .ptr = .{10215 ptr_field_ty,
10226 .ty = ptr_field_ty.toIntern(),10216 (try mod.intern(.{ .ptr = .{
10227 .addr = .{ .field = .{10217 .ty = ptr_field_ty.toIntern(),
10228 .base = union_ptr.toIntern(),10218 .addr = .{ .field = .{
10229 .index = field_index,10219 .base = union_ptr.toIntern(),
10230 } },10220 .index = field_index,
10231 } })).toValue(),10221 } },
10232 );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);
10233 }10232 }
10234 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{10233 } else if (capture_byref) {
10235 .pointee_type = field_ty,10234 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
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);
10241 } else {10235 } else {
10242 if (try sema.resolveDefinedValue(block, sema.src, operand)) |union_val| {10236 return block.inline_case_capture;
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);
10247 }10237 }
10248 } else if (capture_byref) {
10249 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
10250 } else {
10251 return block.inline_case_capture;
10252 }10238 }
10253 }
1025410239
10255 if (is_special_prong) {10240 if (is_special_prong) {
10256 if (capture_byref) {10241 if (capture_byref) {
10257 return operand_ptr;10242 return spa.operand_ptr;
10258 }10243 }
1025910244
10260 switch (operand_ty.zigTypeTag(mod)) {10245 switch (operand_ty.zigTypeTag(mod)) {
10261 .ErrorSet => if (else_error_ty) |ty| {10246 .ErrorSet => if (spa.else_error_ty) |ty| {
10262 return sema.bitCast(block, ty, operand, operand_src, null);10247 return sema.bitCast(block, ty, spa.operand, operand_src, null);
10263 } else {10248 } else {
10264 try block.addUnreachable(false);10249 try block.addUnreachable(false);
10265 return Air.Inst.Ref.unreachable_value;10250 return Air.Inst.Ref.unreachable_value;
10266 },10251 },
10267 else => return operand,10252 else => return spa.operand,
10253 }
10268 }10254 }
10269 }
1027010255
10271 switch (operand_ty.zigTypeTag(mod)) {10256 switch (operand_ty.zigTypeTag(mod)) {
10272 .Union => {10257 .Union => {
10273 const union_obj = mod.typeToUnion(operand_ty).?;10258 const union_obj = mod.typeToUnion(operand_ty).?;
10274 const first_item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;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).?);10261 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);
10277 const first_field = union_obj.fields.values()[first_field_index];10262 const first_field = union_obj.fields.values()[first_field_index];
1027810263
10279 for (case_vals[1..], 0..) |item, i| {10264 for (case_vals[1..], 0..) |item, i| {
10280 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;10265 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
1028110266
10282 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;10267 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;
10283 const field = union_obj.fields.values()[field_index];10268 const field = union_obj.fields.values()[field_index];
10284 if (!field.ty.eql(first_field.ty, mod)) {10269 if (!field.ty.eql(first_field.ty, mod)) {
10285 const msg = msg: {10270 const msg = msg: {
10286 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);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", .{});10273 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
10289 errdefer msg.destroy(gpa);10274 errdefer msg.destroy(sema.gpa);
1029010275
10291 // This must be a multi-prong so this must be a `multi_capture` src10276 // This must be a multi-prong so this must be a `multi_capture` src
10292 const multi_idx = raw_capture_src.multi_capture;10277 const multi_idx = raw_capture_src.multi_capture;
1029310278
10294 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_idx, .item = 0 } };10279 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);10280 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) } };10281 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);10282 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)});10283 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)});10284 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
10300 break :msg msg;10285 break :msg msg;
10301 };10286 };
10302 return sema.failWithOwnedErrorMsg(msg);10287 return sema.failWithOwnedErrorMsg(msg);
10288 }
10303 }10289 }
10304 }
1030510290
10306 if (capture_byref) {10291 if (capture_byref) {
10307 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{10292 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{
10308 .pointee_type = first_field.ty,10293 .pointee_type = first_field.ty,
10309 .@"addrspace" = .generic,10294 .@"addrspace" = .generic,
10310 .mutable = operand_ptr_ty.ptrIsMutable(mod),10295 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10311 });10296 });
1031210297
10313 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {10298 if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |op_ptr_val| {
10314 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{10299 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10315 .ty = field_ty_ptr.toIntern(),10300 .ty = field_ty_ptr.toIntern(),
10316 .addr = .{ .field = .{10301 .addr = .{ .field = .{
10317 .base = op_ptr_val.toIntern(),10302 .base = op_ptr_val.toIntern(),
10318 .index = first_field_index,10303 .index = first_field_index,
10319 } },10304 } },
10320 } })).toValue());10305 } })).toValue());
10306 }
10307 try sema.requireRuntimeBlock(block, operand_src, null);
10308 return block.addStructFieldPtr(spa.operand_ptr, first_field_index, field_ty_ptr);
10321 }10309 }
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| {10311 if (try sema.resolveDefinedValue(block, operand_src, spa.operand)) |operand_val| {
10327 return sema.addConstant(10312 return sema.addConstant(
10328 first_field.ty,10313 first_field.ty,
10329 mod.intern_pool.indexToKey(operand_val.toIntern()).un.val.toValue(),10314 mod.intern_pool.indexToKey(operand_val.toIntern()).un.val.toValue(),
10330 );10315 );
10331 }10316 }
10332 try sema.requireRuntimeBlock(block, operand_src, null);10317 try sema.requireRuntimeBlock(block, operand_src, null);
10333 return block.addStructFieldVal(operand, first_field_index, first_field.ty);10318 return block.addStructFieldVal(spa.operand, first_field_index, first_field.ty);
10334 },10319 },
10335 .ErrorSet => {10320 .ErrorSet => {
10336 if (capture_byref) {10321 if (capture_byref) {
10337 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);10322 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none);
10338 return sema.fail(10323 return sema.fail(
10339 block,10324 block,
10340 capture_src,10325 capture_src,
10341 "error set cannot be captured by reference",10326 "error set cannot be captured by reference",
10342 .{},10327 .{},
10343 );10328 );
10344 }10329 }
1034510330
10346 if (case_vals.len == 1) {10331 if (case_vals.len == 1) {
10347 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;10332 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10348 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);10333 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
10349 return sema.bitCast(block, item_ty, operand, operand_src, null);10334 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
10350 }10335 }
1035110336
10352 var names: Module.Fn.InferredErrorSet.NameMap = .{};10337 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10353 try names.ensureUnusedCapacity(sema.arena, case_vals.len);10338 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
10354 for (case_vals) |err| {10339 for (case_vals) |err| {
10355 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;10340 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
10356 names.putAssumeCapacityNoClobber(err_val.getErrorName(mod).unwrap().?, {});10341 names.putAssumeCapacityNoClobber(err_val.getErrorName(mod).unwrap().?, {});
10357 }10342 }
10358 const error_ty = try mod.errorSetFromUnsortedNames(names.keys());10343 const error_ty = try mod.errorSetFromUnsortedNames(names.keys());
10359 return sema.bitCast(block, error_ty, operand, operand_src, null);10344 return sema.bitCast(block, error_ty, spa.operand, operand_src, null);
10360 },10345 },
10361 else => {10346 else => {
10362 // In this case the capture value is just the passed-through value10347 // In this case the capture value is just the passed-through value
10363 // of the switch condition.10348 // of the switch condition.
10364 if (capture_byref) {10349 if (capture_byref) {
10365 return operand_ptr;10350 return spa.operand_ptr;
10366 } else {10351 } else {
10367 return operand;10352 return spa.operand;
10368 }10353 }
10369 },10354 },
10355 }
10370 }10356 }
10371}10357};
1037210358
10373fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10359fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10374 const mod = sema.mod;10360 const mod = sema.mod;
...@@ -11075,6 +11061,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11075,6 +11061,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11075 }),11061 }),
11076 }11062 }
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
11078 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);11073 const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
11079 try sema.air_instructions.append(gpa, .{11074 try sema.air_instructions.append(gpa, .{
11080 .tag = .block,11075 .tag = .block,
...@@ -11129,19 +11124,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11129,19 +11124,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11129 if (operand_val.eql(item_val, operand_ty, sema.mod)) {11124 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11130 if (info.is_inline) child_block.inline_case_capture = operand;11125 if (info.is_inline) child_block.inline_case_capture = operand;
11131 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11126 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11132 return sema.resolveSwitchProngComptime(11127 return spa.resolveProngComptime(
11133 block,
11134 &child_block,11128 &child_block,
11135 src,
11136 raw_operand.val,
11137 raw_operand.ptr,
11138 .normal,11129 .normal,
11139 body,11130 body,
11140 info.capture,11131 info.capture,
11141 .{ .scalar = @intCast(u32, scalar_i) },11132 .{ .scalar = @intCast(u32, scalar_i) },
11142 else_error_ty,
11143 &.{item},11133 &.{item},
11144 inst,
11145 merges,11134 merges,
11146 );11135 );
11147 }11136 }
...@@ -11168,19 +11157,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11168,19 +11157,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11168 if (operand_val.eql(item_val, operand_ty, sema.mod)) {11157 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11169 if (info.is_inline) child_block.inline_case_capture = operand;11158 if (info.is_inline) child_block.inline_case_capture = operand;
11170 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11159 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11171 return sema.resolveSwitchProngComptime(11160 return spa.resolveProngComptime(
11172 block,
11173 &child_block,11161 &child_block,
11174 src,
11175 raw_operand.val,
11176 raw_operand.ptr,
11177 .normal,11162 .normal,
11178 body,11163 body,
11179 info.capture,11164 info.capture,
11180 .{ .multi_capture = @intCast(u32, multi_i) },11165 .{ .multi_capture = @intCast(u32, multi_i) },
11181 else_error_ty,
11182 items,11166 items,
11183 inst,
11184 merges,11167 merges,
11185 );11168 );
11186 }11169 }
...@@ -11200,19 +11183,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11200,19 +11183,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11200 {11183 {
11201 if (info.is_inline) child_block.inline_case_capture = operand;11184 if (info.is_inline) child_block.inline_case_capture = operand;
11202 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);11185 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
11203 return sema.resolveSwitchProngComptime(11186 return spa.resolveProngComptime(
11204 block,
11205 &child_block,11187 &child_block,
11206 src,
11207 raw_operand.val,
11208 raw_operand.ptr,
11209 .normal,11188 .normal,
11210 body,11189 body,
11211 info.capture,11190 info.capture,
11212 .{ .multi_capture = @intCast(u32, multi_i) },11191 .{ .multi_capture = @intCast(u32, multi_i) },
11213 else_error_ty,11192 undefined, // case_vals may be undefined for ranges
11214 undefined,
11215 inst,
11216 merges,11193 merges,
11217 );11194 );
11218 }11195 }
...@@ -11227,19 +11204,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11227,19 +11204,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11227 return Air.Inst.Ref.void_value;11204 return Air.Inst.Ref.void_value;
11228 }11205 }
1122911206
11230 return sema.resolveSwitchProngComptime(11207 return spa.resolveProngComptime(
11231 block,
11232 &child_block,11208 &child_block,
11233 src,
11234 raw_operand.val,
11235 raw_operand.ptr,
11236 .special,11209 .special,
11237 special.body,11210 special.body,
11238 special.capture,11211 special.capture,
11239 .special,11212 .special,
11240 else_error_ty,11213 undefined, // case_vals may be undefined for special prongs
11241 undefined,
11242 inst,
11243 merges,11214 merges,
11244 );11215 );
11245 }11216 }
...@@ -11262,19 +11233,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11262,19 +11233,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11262 try sema.addSafetyCheck(block, ok, .corrupt_switch);11233 try sema.addSafetyCheck(block, ok, .corrupt_switch);
11263 }11234 }
1126411235
11265 return sema.resolveSwitchProngComptime(11236 return spa.resolveProngComptime(
11266 block,
11267 &child_block,11237 &child_block,
11268 src,
11269 raw_operand.val,
11270 raw_operand.ptr,
11271 .special,11238 .special,
11272 special.body,11239 special.body,
11273 special.capture,11240 special.capture,
11274 .special,11241 .special,
11275 else_error_ty,11242 undefined, // case_vals may be undefined for special prongs
11276 undefined,
11277 inst,
11278 merges,11243 merges,
11279 );11244 );
11280 }11245 }
...@@ -11328,17 +11293,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11328,17 +11293,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11328 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11293 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
11329 // nothing to do here11294 // nothing to do here
11330 } else if (analyze_body) {11295 } else if (analyze_body) {
11331 try sema.analyzeSwitchProngRuntime(11296 try spa.analyzeProngRuntime(
11332 &case_block,11297 &case_block,
11333 raw_operand.val,
11334 raw_operand.ptr,
11335 .normal,11298 .normal,
11336 body,11299 body,
11337 info.capture,11300 info.capture,
11338 .{ .scalar = @intCast(u32, scalar_i) },11301 .{ .scalar = @intCast(u32, scalar_i) },
11339 else_error_ty,
11340 &.{item},11302 &.{item},
11341 inst,
11342 );11303 );
11343 } else {11304 } else {
11344 _ = try case_block.addNoOp(.unreach);11305 _ = try case_block.addNoOp(.unreach);
...@@ -11422,17 +11383,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11422,17 +11383,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11422 };11383 };
11423 emit_bb = true;11384 emit_bb = true;
1142411385
11425 try sema.analyzeSwitchProngRuntime(11386 try spa.analyzeProngRuntime(
11426 &case_block,11387 &case_block,
11427 raw_operand.val,
11428 raw_operand.ptr,
11429 .normal,11388 .normal,
11430 body,11389 body,
11431 info.capture,11390 info.capture,
11432 .{ .multi_capture = multi_i },11391 .{ .multi_capture = multi_i },
11433 else_error_ty,11392 undefined, // case_vals may be undefined for ranges
11434 undefined,
11435 inst,
11436 );11393 );
1143711394
11438 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11395 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...@@ -11469,17 +11426,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11469 emit_bb = true;11426 emit_bb = true;
1147011427
11471 if (analyze_body) {11428 if (analyze_body) {
11472 try sema.analyzeSwitchProngRuntime(11429 try spa.analyzeProngRuntime(
11473 &case_block,11430 &case_block,
11474 raw_operand.val,
11475 raw_operand.ptr,
11476 .normal,11431 .normal,
11477 body,11432 body,
11478 info.capture,11433 info.capture,
11479 .{ .multi_capture = multi_i },11434 .{ .multi_capture = multi_i },
11480 else_error_ty,
11481 &.{item},11435 &.{item},
11482 inst,
11483 );11436 );
11484 } else {11437 } else {
11485 _ = try case_block.addNoOp(.unreach);11438 _ = try case_block.addNoOp(.unreach);
...@@ -11518,17 +11471,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11518,17 +11471,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11518 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11471 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
11519 // nothing to do here11472 // nothing to do here
11520 } else if (analyze_body) {11473 } else if (analyze_body) {
11521 try sema.analyzeSwitchProngRuntime(11474 try spa.analyzeProngRuntime(
11522 &case_block,11475 &case_block,
11523 raw_operand.val,
11524 raw_operand.ptr,
11525 .normal,11476 .normal,
11526 body,11477 body,
11527 info.capture,11478 info.capture,
11528 .{ .multi_capture = multi_i },11479 .{ .multi_capture = multi_i },
11529 else_error_ty,
11530 items,11480 items,
11531 inst,
11532 );11481 );
11533 } else {11482 } else {
11534 _ = try case_block.addNoOp(.unreach);11483 _ = try case_block.addNoOp(.unreach);
...@@ -11607,17 +11556,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11607,17 +11556,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11607 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {11556 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
11608 // nothing to do here11557 // nothing to do here
11609 } else {11558 } else {
11610 try sema.analyzeSwitchProngRuntime(11559 try spa.analyzeProngRuntime(
11611 &case_block,11560 &case_block,
11612 raw_operand.val,
11613 raw_operand.ptr,
11614 .normal,11561 .normal,
11615 body,11562 body,
11616 info.capture,11563 info.capture,
11617 .{ .multi_capture = multi_i },11564 .{ .multi_capture = multi_i },
11618 else_error_ty,
11619 items,11565 items,
11620 inst,
11621 );11566 );
11622 }11567 }
1162311568
...@@ -11677,17 +11622,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11677,17 +11622,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11677 emit_bb = true;11622 emit_bb = true;
1167811623
11679 if (analyze_body) {11624 if (analyze_body) {
11680 try sema.analyzeSwitchProngRuntime(11625 try spa.analyzeProngRuntime(
11681 &case_block,11626 &case_block,
11682 raw_operand.val,
11683 raw_operand.ptr,
11684 .special,11627 .special,
11685 special.body,11628 special.body,
11686 special.capture,11629 special.capture,
11687 .special,11630 .special,
11688 else_error_ty,
11689 &.{item_ref},11631 &.{item_ref},
11690 inst,
11691 );11632 );
11692 } else {11633 } else {
11693 _ = try case_block.addNoOp(.unreach);11634 _ = try case_block.addNoOp(.unreach);
...@@ -11724,17 +11665,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -11724,17 +11665,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11724 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11665 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11725 emit_bb = true;11666 emit_bb = true;
1172611667
11727 try sema.analyzeSwitchProngRuntime(11668 try spa.analyzeProngRuntime(
11728 &case_block,11669 &case_block,
11729 raw_operand.val,
11730 raw_operand.ptr,
11731 .special,11670 .special,
11732 special.body,11671 special.body,
11733 special.capture,11672 special.capture,
11734 .special,11673 .special,
11735 else_error_ty,
11736 &.{item_ref},11674 &.{item_ref},
11737 inst,
11738 );11675 );
1173911676
11740 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11677 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...@@ -11758,17 +11695,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11758 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11695 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11759 emit_bb = true;11696 emit_bb = true;
1176011697
11761 try sema.analyzeSwitchProngRuntime(11698 try spa.analyzeProngRuntime(
11762 &case_block,11699 &case_block,
11763 raw_operand.val,
11764 raw_operand.ptr,
11765 .special,11700 .special,
11766 special.body,11701 special.body,
11767 special.capture,11702 special.capture,
11768 .special,11703 .special,
11769 else_error_ty,
11770 &.{item_ref},11704 &.{item_ref},
11771 inst,
11772 );11705 );
1177311706
11774 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11707 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...@@ -11789,17 +11722,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11789 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11722 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11790 emit_bb = true;11723 emit_bb = true;
1179111724
11792 try sema.analyzeSwitchProngRuntime(11725 try spa.analyzeProngRuntime(
11793 &case_block,11726 &case_block,
11794 raw_operand.val,
11795 raw_operand.ptr,
11796 .special,11727 .special,
11797 special.body,11728 special.body,
11798 special.capture,11729 special.capture,
11799 .special,11730 .special,
11800 else_error_ty,
11801 &.{Air.Inst.Ref.bool_true},11731 &.{Air.Inst.Ref.bool_true},
11802 inst,
11803 );11732 );
1180411733
11805 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11734 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...@@ -11818,17 +11747,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11818 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);11747 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
11819 emit_bb = true;11748 emit_bb = true;
1182011749
11821 try sema.analyzeSwitchProngRuntime(11750 try spa.analyzeProngRuntime(
11822 &case_block,11751 &case_block,
11823 raw_operand.val,
11824 raw_operand.ptr,
11825 .special,11752 .special,
11826 special.body,11753 special.body,
11827 special.capture,11754 special.capture,
11828 .special,11755 .special,
11829 else_error_ty,
11830 &.{Air.Inst.Ref.bool_false},11756 &.{Air.Inst.Ref.bool_false},
11831 inst,
11832 );11757 );
1183311758
11834 try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len);11759 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...@@ -11872,17 +11797,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
11872 {11797 {
11873 // nothing to do here11798 // nothing to do here
11874 } else if (special.body.len != 0 and analyze_body and !special.is_inline) {11799 } else if (special.body.len != 0 and analyze_body and !special.is_inline) {
11875 try sema.analyzeSwitchProngRuntime(11800 try spa.analyzeProngRuntime(
11876 &case_block,11801 &case_block,
11877 raw_operand.val,
11878 raw_operand.ptr,
11879 .special,11802 .special,
11880 special.body,11803 special.body,
11881 special.capture,11804 special.capture,
11882 .special,11805 .special,
11883 else_error_ty,11806 undefined, // case_vals may be undefined for special prongs
11884 undefined,
11885 inst,
11886 );11807 );
11887 } else {11808 } else {
11888 // We still need a terminator in this block, but we have proven11809 // We still need a terminator in this block, but we have proven