| ... | @@ -10928,7 +10928,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -10928,7 +10928,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 10928 | const switch_src = block.nodeOffset(inst_data.src_node); | 10928 | const switch_src = block.nodeOffset(inst_data.src_node); |
| 10929 | const switch_src_node_offset = inst_data.src_node; | 10929 | const switch_src_node_offset = inst_data.src_node; |
| 10930 | const switch_operand_src = block.src(.{ .node_offset_switch_operand = switch_src_node_offset }); | 10930 | const switch_operand_src = block.src(.{ .node_offset_switch_operand = switch_src_node_offset }); |
| 10931 | const else_prong_src = block.src(.{ .node_offset_switch_special_prong = switch_src_node_offset }); | 10931 | const else_prong_src = block.src(.{ .node_offset_switch_else_prong = switch_src_node_offset }); |
| 10932 | const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); | 10932 | const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); |
| 10933 | const main_operand_src = block.src(.{ .node_offset_if_cond = extra.data.main_src_node_offset }); | 10933 | const main_operand_src = block.src(.{ .node_offset_if_cond = extra.data.main_src_node_offset }); |
| 10934 | const main_src = block.src(.{ .node_offset_main_token = extra.data.main_src_node_offset }); | 10934 | const main_src = block.src(.{ .node_offset_main_token = extra.data.main_src_node_offset }); |
| ... | @@ -11122,6 +11122,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11122,6 +11122,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11122 | err_val, | 11122 | err_val, |
| 11123 | operand_err_set_ty, | 11123 | operand_err_set_ty, |
| 11124 | switch_src_node_offset, | 11124 | switch_src_node_offset, |
| | 11125 | null, |
| 11125 | .{ | 11126 | .{ |
| 11126 | .body = else_case.body, | 11127 | .body = else_case.body, |
| 11127 | .end = else_case.end, | 11128 | .end = else_case.end, |
| ... | @@ -11129,6 +11130,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11129,6 +11130,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11129 | .is_inline = else_case.is_inline, | 11130 | .is_inline = else_case.is_inline, |
| 11130 | .has_tag_capture = false, | 11131 | .has_tag_capture = false, |
| 11131 | }, | 11132 | }, |
| | 11133 | false, |
| 11132 | case_vals, | 11134 | case_vals, |
| 11133 | scalar_cases_len, | 11135 | scalar_cases_len, |
| 11134 | multi_cases_len, | 11136 | multi_cases_len, |
| ... | @@ -11200,6 +11202,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11200,6 +11202,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11200 | true, | 11202 | true, |
| 11201 | switch_src_node_offset, | 11203 | switch_src_node_offset, |
| 11202 | else_prong_src, | 11204 | else_prong_src, |
| | 11205 | false, |
| 11203 | undefined, | 11206 | undefined, |
| 11204 | seen_errors, | 11207 | seen_errors, |
| 11205 | undefined, | 11208 | undefined, |
| ... | @@ -11207,6 +11210,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11207,6 +11210,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11207 | undefined, | 11210 | undefined, |
| 11208 | cond_dbg_node_index, | 11211 | cond_dbg_node_index, |
| 11209 | true, | 11212 | true, |
| | 11213 | null, |
| | 11214 | undefined, |
| | 11215 | &.{}, |
| | 11216 | &.{}, |
| 11210 | ); | 11217 | ); |
| 11211 | | 11218 | |
| 11212 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len + | 11219 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len + |
| ... | @@ -11243,12 +11250,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11243,12 +11250,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11243 | | 11250 | |
| 11244 | const pt = sema.pt; | 11251 | const pt = sema.pt; |
| 11245 | const zcu = pt.zcu; | 11252 | const zcu = pt.zcu; |
| | 11253 | const ip = &zcu.intern_pool; |
| 11246 | const gpa = sema.gpa; | 11254 | const gpa = sema.gpa; |
| 11247 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | 11255 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 11248 | const src = block.nodeOffset(inst_data.src_node); | 11256 | const src = block.nodeOffset(inst_data.src_node); |
| 11249 | const src_node_offset = inst_data.src_node; | 11257 | const src_node_offset = inst_data.src_node; |
| 11250 | const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); | 11258 | const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); |
| 11251 | const special_prong_src = block.src(.{ .node_offset_switch_special_prong = src_node_offset }); | 11259 | const else_prong_src = block.src(.{ .node_offset_switch_else_prong = src_node_offset }); |
| | 11260 | const under_prong_src = block.src(.{ .node_offset_switch_under_prong = src_node_offset }); |
| 11252 | const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); | 11261 | const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); |
| 11253 | | 11262 | |
| 11254 | const operand: SwitchProngAnalysis.Operand, const raw_operand_ty: Type = op: { | 11263 | const operand: SwitchProngAnalysis.Operand, const raw_operand_ty: Type = op: { |
| ... | @@ -11335,50 +11344,63 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11335,50 +11344,63 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11335 | var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len); | 11344 | var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len); |
| 11336 | defer case_vals.deinit(gpa); | 11345 | defer case_vals.deinit(gpa); |
| 11337 | | 11346 | |
| | 11347 | var single_absorbed_item: Zir.Inst.Ref = .none; |
| 11338 | var absorbed_items: []const Zir.Inst.Ref = &.{}; | 11348 | var absorbed_items: []const Zir.Inst.Ref = &.{}; |
| 11339 | var absorbed_ranges: []const Zir.Inst.Ref = &.{}; | 11349 | var absorbed_ranges: []const Zir.Inst.Ref = &.{}; |
| 11340 | | 11350 | |
| 11341 | const special_prong = extra.data.bits.special_prong; | 11351 | const special_prongs = extra.data.bits.special_prongs; |
| 11342 | const special: SpecialProng = switch (special_prong) { | 11352 | const has_else = special_prongs.hasElse(); |
| 11343 | .none => .{ | 11353 | const has_under = special_prongs.hasUnder(); |
| 11344 | .body = &.{}, | 11354 | const special_else: SpecialProng = if (has_else) blk: { |
| 11345 | .end = header_extra_index, | 11355 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[header_extra_index]); |
| 11346 | .capture = .none, | 11356 | const extra_body_start = header_extra_index + 1; |
| 11347 | .is_inline = false, | 11357 | break :blk .{ |
| 11348 | .has_tag_capture = false, | 11358 | .body = sema.code.bodySlice(extra_body_start, info.body_len), |
| 11349 | }, | 11359 | .end = extra_body_start + info.body_len, |
| 11350 | .under, .@"else" => blk: { | 11360 | .capture = info.capture, |
| 11351 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[header_extra_index]); | 11361 | .is_inline = info.is_inline, |
| 11352 | const extra_body_start = header_extra_index + 1; | 11362 | .has_tag_capture = info.has_tag_capture, |
| 11353 | break :blk .{ | 11363 | }; |
| 11354 | .body = sema.code.bodySlice(extra_body_start, info.body_len), | 11364 | } else .{ |
| 11355 | .end = extra_body_start + info.body_len, | 11365 | .body = &.{}, |
| 11356 | .capture = info.capture, | 11366 | .end = header_extra_index, |
| 11357 | .is_inline = info.is_inline, | 11367 | .capture = .none, |
| 11358 | .has_tag_capture = info.has_tag_capture, | 11368 | .is_inline = false, |
| 11359 | }; | 11369 | .has_tag_capture = false, |
| 11360 | }, | 11370 | }; |
| 11361 | .absorbing_under => blk: { | 11371 | const special_under: SpecialProng = if (has_under) blk: { |
| 11362 | var extra_index = header_extra_index; | 11372 | var extra_index = special_else.end; |
| | 11373 | var trailing_items_len: usize = 0; |
| | 11374 | if (special_prongs.hasOneAdditionalItem()) { |
| | 11375 | single_absorbed_item = @enumFromInt(sema.code.extra[extra_index]); |
| | 11376 | extra_index += 1; |
| | 11377 | absorbed_items = @ptrCast(&single_absorbed_item); |
| | 11378 | } else if (special_prongs.hasManyAdditionalItems()) { |
| 11363 | const items_len = sema.code.extra[extra_index]; | 11379 | const items_len = sema.code.extra[extra_index]; |
| 11364 | extra_index += 1; | 11380 | extra_index += 1; |
| 11365 | const ranges_len = sema.code.extra[extra_index]; | 11381 | const ranges_len = sema.code.extra[extra_index]; |
| 11366 | extra_index += 1; | 11382 | extra_index += 1; |
| 11367 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); | 11383 | absorbed_items = sema.code.refSlice(extra_index + 1, items_len); |
| 11368 | extra_index += 1; | 11384 | absorbed_ranges = sema.code.refSlice(extra_index + 1 + items_len, ranges_len * 2); |
| 11369 | absorbed_items = sema.code.refSlice(extra_index, items_len); | 11385 | trailing_items_len = items_len + ranges_len * 2; |
| 11370 | extra_index += items_len; | 11386 | } |
| 11371 | absorbed_ranges = sema.code.refSlice(extra_index, ranges_len * 2); | 11387 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); |
| 11372 | extra_index += ranges_len * 2; | 11388 | extra_index += 1 + trailing_items_len; |
| 11373 | break :blk .{ | 11389 | break :blk .{ |
| 11374 | .body = sema.code.bodySlice(extra_index, info.body_len), | 11390 | .body = sema.code.bodySlice(extra_index, info.body_len), |
| 11375 | .end = extra_index + info.body_len, | 11391 | .end = extra_index + info.body_len, |
| 11376 | .capture = info.capture, | 11392 | .capture = info.capture, |
| 11377 | .is_inline = info.is_inline, | 11393 | .is_inline = info.is_inline, |
| 11378 | .has_tag_capture = info.has_tag_capture, | 11394 | .has_tag_capture = info.has_tag_capture, |
| 11379 | }; | 11395 | }; |
| 11380 | }, | 11396 | } else .{ |
| | 11397 | .body = &.{}, |
| | 11398 | .end = special_else.end, |
| | 11399 | .capture = .none, |
| | 11400 | .is_inline = false, |
| | 11401 | .has_tag_capture = false, |
| 11381 | }; | 11402 | }; |
| | 11403 | const special_end = special_under.end; |
| 11382 | | 11404 | |
| 11383 | // Duplicate checking variables later also used for `inline else`. | 11405 | // Duplicate checking variables later also used for `inline else`. |
| 11384 | var seen_enum_fields: []?LazySrcLoc = &.{}; | 11406 | var seen_enum_fields: []?LazySrcLoc = &.{}; |
| ... | @@ -11398,9 +11420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11398,9 +11420,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11398 | var else_error_ty: ?Type = null; | 11420 | var else_error_ty: ?Type = null; |
| 11399 | | 11421 | |
| 11400 | // Validate usage of '_' prongs. | 11422 | // Validate usage of '_' prongs. |
| 11401 | if ((special_prong == .under or special_prong == .absorbing_under) and | 11423 | if (has_under and !raw_operand_ty.isNonexhaustiveEnum(zcu)) { |
| 11402 | !raw_operand_ty.isNonexhaustiveEnum(zcu)) | | |
| 11403 | { | | |
| 11404 | const msg = msg: { | 11424 | const msg = msg: { |
| 11405 | const msg = try sema.errMsg( | 11425 | const msg = try sema.errMsg( |
| 11406 | src, | 11426 | src, |
| ... | @@ -11409,7 +11429,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11409,7 +11429,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11409 | ); | 11429 | ); |
| 11410 | errdefer msg.destroy(gpa); | 11430 | errdefer msg.destroy(gpa); |
| 11411 | try sema.errNote( | 11431 | try sema.errNote( |
| 11412 | special_prong_src, | 11432 | under_prong_src, |
| 11413 | msg, | 11433 | msg, |
| 11414 | "'_' prong here", | 11434 | "'_' prong here", |
| 11415 | .{}, | 11435 | .{}, |
| ... | @@ -11443,14 +11463,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11443,14 +11463,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11443 | cond_ty, | 11463 | cond_ty, |
| 11444 | block.src(.{ .switch_case_item = .{ | 11464 | block.src(.{ .switch_case_item = .{ |
| 11445 | .switch_node_offset = src_node_offset, | 11465 | .switch_node_offset = src_node_offset, |
| 11446 | .case_idx = .special, | 11466 | .case_idx = .special_under, |
| 11447 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, | 11467 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, |
| 11448 | } }), | 11468 | } }), |
| 11449 | ); | 11469 | ); |
| 11450 | } | 11470 | } |
| 11451 | try sema.validateSwitchNoRange(block, @intCast(absorbed_ranges.len), cond_ty, src_node_offset); | 11471 | try sema.validateSwitchNoRange(block, @intCast(absorbed_ranges.len), cond_ty, src_node_offset); |
| 11452 | | 11472 | |
| 11453 | var extra_index: usize = special.end; | 11473 | var extra_index: usize = special_end; |
| 11454 | { | 11474 | { |
| 11455 | var scalar_i: u32 = 0; | 11475 | var scalar_i: u32 = 0; |
| 11456 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11476 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11508,13 +11528,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11508,13 +11528,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11508 | if (seen_src == null) break false; | 11528 | if (seen_src == null) break false; |
| 11509 | } else true; | 11529 | } else true; |
| 11510 | | 11530 | |
| 11511 | if (special_prong == .@"else") { | 11531 | if (has_else) { |
| 11512 | if (all_tags_handled and !cond_ty.isNonexhaustiveEnum(zcu)) return sema.fail( | 11532 | if (all_tags_handled) { |
| 11513 | block, | 11533 | if (cond_ty.isNonexhaustiveEnum(zcu)) { |
| 11514 | special_prong_src, | 11534 | if (has_under) return sema.fail( |
| 11515 | "unreachable else prong; all cases already handled", | 11535 | block, |
| 11516 | .{}, | 11536 | else_prong_src, |
| 11517 | ); | 11537 | "unreachable else prong; all explicit cases already handled", |
| | 11538 | .{}, |
| | 11539 | ); |
| | 11540 | } else return sema.fail( |
| | 11541 | block, |
| | 11542 | else_prong_src, |
| | 11543 | "unreachable else prong; all cases already handled", |
| | 11544 | .{}, |
| | 11545 | ); |
| | 11546 | } |
| 11518 | } else if (!all_tags_handled) { | 11547 | } else if (!all_tags_handled) { |
| 11519 | const msg = msg: { | 11548 | const msg = msg: { |
| 11520 | const msg = try sema.errMsg( | 11549 | const msg = try sema.errMsg( |
| ... | @@ -11532,7 +11561,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11532,7 +11561,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11532 | i, | 11561 | i, |
| 11533 | msg, | 11562 | msg, |
| 11534 | "unhandled enumeration value: '{f}'", | 11563 | "unhandled enumeration value: '{f}'", |
| 11535 | .{field_name.fmt(&zcu.intern_pool)}, | 11564 | .{field_name.fmt(ip)}, |
| 11536 | ); | 11565 | ); |
| 11537 | } | 11566 | } |
| 11538 | try sema.errNote( | 11567 | try sema.errNote( |
| ... | @@ -11544,11 +11573,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11544,11 +11573,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11544 | break :msg msg; | 11573 | break :msg msg; |
| 11545 | }; | 11574 | }; |
| 11546 | return sema.failWithOwnedErrorMsg(block, msg); | 11575 | return sema.failWithOwnedErrorMsg(block, msg); |
| 11547 | } else if (special_prong == .none and cond_ty.isNonexhaustiveEnum(zcu) and !union_originally) { | 11576 | } else if (special_prongs == .none and cond_ty.isNonexhaustiveEnum(zcu) and !union_originally) { |
| 11548 | return sema.fail( | 11577 | return sema.fail( |
| 11549 | block, | 11578 | block, |
| 11550 | src, | 11579 | src, |
| 11551 | "switch on non-exhaustive enum must include 'else' or '_' prong", | 11580 | "switch on non-exhaustive enum must include 'else' or '_' prong or both", |
| 11552 | .{}, | 11581 | .{}, |
| 11553 | ); | 11582 | ); |
| 11554 | } | 11583 | } |
| ... | @@ -11562,11 +11591,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11562,11 +11591,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11562 | inst_data, | 11591 | inst_data, |
| 11563 | scalar_cases_len, | 11592 | scalar_cases_len, |
| 11564 | multi_cases_len, | 11593 | multi_cases_len, |
| 11565 | .{ .body = special.body, .end = special.end, .src = special_prong_src }, | 11594 | .{ .body = special_else.body, .end = special_else.end, .src = else_prong_src }, |
| 11566 | special_prong == .@"else", | 11595 | has_else, |
| 11567 | ), | 11596 | ), |
| 11568 | .int, .comptime_int => { | 11597 | .int, .comptime_int => { |
| 11569 | var extra_index: usize = special.end; | 11598 | var extra_index: usize = special_end; |
| 11570 | { | 11599 | { |
| 11571 | var scalar_i: u32 = 0; | 11600 | var scalar_i: u32 = 0; |
| 11572 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11601 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11648,10 +11677,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11648,10 +11677,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11648 | const min_int = try cond_ty.minInt(pt, cond_ty); | 11677 | const min_int = try cond_ty.minInt(pt, cond_ty); |
| 11649 | const max_int = try cond_ty.maxInt(pt, cond_ty); | 11678 | const max_int = try cond_ty.maxInt(pt, cond_ty); |
| 11650 | if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) { | 11679 | if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) { |
| 11651 | if (special_prong == .@"else") { | 11680 | if (has_else) { |
| 11652 | return sema.fail( | 11681 | return sema.fail( |
| 11653 | block, | 11682 | block, |
| 11654 | special_prong_src, | 11683 | else_prong_src, |
| 11655 | "unreachable else prong; all cases already handled", | 11684 | "unreachable else prong; all cases already handled", |
| 11656 | .{}, | 11685 | .{}, |
| 11657 | ); | 11686 | ); |
| ... | @@ -11659,7 +11688,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11659,7 +11688,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11659 | break :check_range; | 11688 | break :check_range; |
| 11660 | } | 11689 | } |
| 11661 | } | 11690 | } |
| 11662 | if (special_prong != .@"else") { | 11691 | if (special_prongs == .none) { |
| 11663 | return sema.fail( | 11692 | return sema.fail( |
| 11664 | block, | 11693 | block, |
| 11665 | src, | 11694 | src, |
| ... | @@ -11670,7 +11699,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11670,7 +11699,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11670 | } | 11699 | } |
| 11671 | }, | 11700 | }, |
| 11672 | .bool => { | 11701 | .bool => { |
| 11673 | var extra_index: usize = special.end; | 11702 | var extra_index: usize = special_end; |
| 11674 | { | 11703 | { |
| 11675 | var scalar_i: u32 = 0; | 11704 | var scalar_i: u32 = 0; |
| 11676 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11705 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11722,31 +11751,28 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11722,31 +11751,28 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11722 | try sema.validateSwitchNoRange(block, ranges_len, cond_ty, src_node_offset); | 11751 | try sema.validateSwitchNoRange(block, ranges_len, cond_ty, src_node_offset); |
| 11723 | } | 11752 | } |
| 11724 | } | 11753 | } |
| 11725 | switch (special_prong) { | 11754 | if (has_else) { |
| 11726 | .@"else" => { | 11755 | if (true_count + false_count == 2) { |
| 11727 | if (true_count + false_count == 2) { | 11756 | return sema.fail( |
| 11728 | return sema.fail( | 11757 | block, |
| 11729 | block, | 11758 | else_prong_src, |
| 11730 | special_prong_src, | 11759 | "unreachable else prong; all cases already handled", |
| 11731 | "unreachable else prong; all cases already handled", | 11760 | .{}, |
| 11732 | .{}, | 11761 | ); |
| 11733 | ); | 11762 | } |
| 11734 | } | 11763 | } else { |
| 11735 | }, | 11764 | if (true_count + false_count < 2) { |
| 11736 | .under, .absorbing_under, .none => { | 11765 | return sema.fail( |
| 11737 | if (true_count + false_count < 2) { | 11766 | block, |
| 11738 | return sema.fail( | 11767 | src, |
| 11739 | block, | 11768 | "switch must handle all possibilities", |
| 11740 | src, | 11769 | .{}, |
| 11741 | "switch must handle all possibilities", | 11770 | ); |
| 11742 | .{}, | 11771 | } |
| 11743 | ); | | |
| 11744 | } | | |
| 11745 | }, | | |
| 11746 | } | 11772 | } |
| 11747 | }, | 11773 | }, |
| 11748 | .enum_literal, .void, .@"fn", .pointer, .type => { | 11774 | .enum_literal, .void, .@"fn", .pointer, .type => { |
| 11749 | if (special_prong != .@"else") { | 11775 | if (!has_else) { |
| 11750 | return sema.fail( | 11776 | return sema.fail( |
| 11751 | block, | 11777 | block, |
| 11752 | src, | 11778 | src, |
| ... | @@ -11758,7 +11784,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11758,7 +11784,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11758 | var seen_values = ValueSrcMap{}; | 11784 | var seen_values = ValueSrcMap{}; |
| 11759 | defer seen_values.deinit(gpa); | 11785 | defer seen_values.deinit(gpa); |
| 11760 | | 11786 | |
| 11761 | var extra_index: usize = special.end; | 11787 | var extra_index: usize = special_end; |
| 11762 | { | 11788 | { |
| 11763 | var scalar_i: u32 = 0; | 11789 | var scalar_i: u32 = 0; |
| 11764 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11790 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11831,6 +11857,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11831,6 +11857,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11831 | }), | 11857 | }), |
| 11832 | } | 11858 | } |
| 11833 | | 11859 | |
| | 11860 | var special_members_only: ?SpecialProng = null; |
| | 11861 | var special_members_only_src: LazySrcLoc = undefined; |
| | 11862 | const special_generic, const special_generic_src = if (has_under) b: { |
| | 11863 | if (has_else) { |
| | 11864 | special_members_only = special_else; |
| | 11865 | special_members_only_src = else_prong_src; |
| | 11866 | } |
| | 11867 | break :b .{ special_under, under_prong_src }; |
| | 11868 | } else .{ special_else, else_prong_src }; |
| | 11869 | |
| 11834 | const spa: SwitchProngAnalysis = .{ | 11870 | const spa: SwitchProngAnalysis = .{ |
| 11835 | .sema = sema, | 11871 | .sema = sema, |
| 11836 | .parent_block = block, | 11872 | .parent_block = block, |
| ... | @@ -11877,11 +11913,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11877,11 +11913,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11877 | defer child_block.instructions.deinit(gpa); | 11913 | defer child_block.instructions.deinit(gpa); |
| 11878 | defer merges.deinit(gpa); | 11914 | defer merges.deinit(gpa); |
| 11879 | | 11915 | |
| 11880 | if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) { | 11916 | if (scalar_cases_len + multi_cases_len == 0 and |
| | 11917 | special_members_only == null and |
| | 11918 | !special_generic.is_inline) |
| | 11919 | { |
| 11881 | if (empty_enum) { | 11920 | if (empty_enum) { |
| 11882 | return .void_value; | 11921 | return .void_value; |
| 11883 | } | 11922 | } |
| 11884 | if (special_prong == .none) { | 11923 | if (special_prongs == .none) { |
| 11885 | return sema.fail(block, src, "switch must handle all possibilities", .{}); | 11924 | return sema.fail(block, src, "switch must handle all possibilities", .{}); |
| 11886 | } | 11925 | } |
| 11887 | const init_cond = switch (operand) { | 11926 | const init_cond = switch (operand) { |
| ... | @@ -11895,7 +11934,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11895,7 +11934,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11895 | const ok = try block.addUnOp(.is_named_enum_value, init_cond); | 11934 | const ok = try block.addUnOp(.is_named_enum_value, init_cond); |
| 11896 | try sema.addSafetyCheck(block, src, ok, .corrupt_switch); | 11935 | try sema.addSafetyCheck(block, src, ok, .corrupt_switch); |
| 11897 | } | 11936 | } |
| 11898 | if (err_set and try sema.maybeErrorUnwrap(block, special.body, init_cond, operand_src, false)) { | 11937 | if (err_set and try sema.maybeErrorUnwrap(block, special_generic.body, init_cond, operand_src, false)) { |
| 11899 | return .unreachable_value; | 11938 | return .unreachable_value; |
| 11900 | } | 11939 | } |
| 11901 | } | 11940 | } |
| ... | @@ -11915,7 +11954,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11915,7 +11954,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11915 | cond_ty, | 11954 | cond_ty, |
| 11916 | cond_val, | 11955 | cond_val, |
| 11917 | src_node_offset, | 11956 | src_node_offset, |
| 11918 | special, | 11957 | special_members_only, |
| | 11958 | special_generic, |
| | 11959 | has_under, |
| 11919 | case_vals, | 11960 | case_vals, |
| 11920 | scalar_cases_len, | 11961 | scalar_cases_len, |
| 11921 | multi_cases_len, | 11962 | multi_cases_len, |
| ... | @@ -11925,15 +11966,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11925,15 +11966,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11925 | ); | 11966 | ); |
| 11926 | } | 11967 | } |
| 11927 | | 11968 | |
| 11928 | if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline and !extra.data.bits.has_continue) { | 11969 | if (scalar_cases_len + multi_cases_len == 0 and |
| | 11970 | special_members_only == null and |
| | 11971 | !special_generic.is_inline and |
| | 11972 | !extra.data.bits.has_continue) |
| | 11973 | { |
| 11929 | return spa.resolveProngComptime( | 11974 | return spa.resolveProngComptime( |
| 11930 | &child_block, | 11975 | &child_block, |
| 11931 | .special, | 11976 | .special, |
| 11932 | special.body, | 11977 | special_generic.body, |
| 11933 | special.capture, | 11978 | special_generic.capture, |
| 11934 | block.src(.{ .switch_capture = .{ | 11979 | block.src(.{ .switch_capture = .{ |
| 11935 | .switch_node_offset = src_node_offset, | 11980 | .switch_node_offset = src_node_offset, |
| 11936 | .case_idx = .special, | 11981 | .case_idx = if (has_under) .special_under else .special_else, |
| 11937 | } }), | 11982 | } }), |
| 11938 | undefined, // case_vals may be undefined for special prongs | 11983 | undefined, // case_vals may be undefined for special prongs |
| 11939 | .none, | 11984 | .none, |
| ... | @@ -11949,6 +11994,88 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11949,6 +11994,88 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11949 | unreachable; | 11994 | unreachable; |
| 11950 | } | 11995 | } |
| 11951 | | 11996 | |
| | 11997 | var extra_case_vals: struct { |
| | 11998 | items: std.ArrayListUnmanaged(Air.Inst.Ref), |
| | 11999 | ranges: std.ArrayListUnmanaged([2]Air.Inst.Ref), |
| | 12000 | } = .{ .items = .empty, .ranges = .empty }; |
| | 12001 | defer { |
| | 12002 | extra_case_vals.items.deinit(gpa); |
| | 12003 | extra_case_vals.ranges.deinit(gpa); |
| | 12004 | } |
| | 12005 | |
| | 12006 | // Runtime switch, if we have a special_members_only prong we need to unroll |
| | 12007 | // it to a prong with explicit items. |
| | 12008 | // Although this is potentially the same as `inline else` it does not count |
| | 12009 | // towards the backward branch quota because it's an implementation detail. |
| | 12010 | if (special_members_only) |special| gen: { |
| | 12011 | assert(cond_ty.isNonexhaustiveEnum(zcu)); |
| | 12012 | _ = special; |
| | 12013 | |
| | 12014 | var min_i: usize = math.maxInt(usize); |
| | 12015 | var max_i: usize = 0; |
| | 12016 | var seen_field_count: usize = 0; |
| | 12017 | for (seen_enum_fields, 0..) |seen, enum_i| { |
| | 12018 | if (seen != null) { |
| | 12019 | seen_field_count += 1; |
| | 12020 | } else { |
| | 12021 | min_i = @min(min_i, enum_i); |
| | 12022 | max_i = @max(max_i, enum_i); |
| | 12023 | } |
| | 12024 | } |
| | 12025 | if (min_i == max_i) { |
| | 12026 | seen_enum_fields[min_i] = special_members_only_src; |
| | 12027 | const item_val = try pt.enumValueFieldIndex(cond_ty, @intCast(min_i)); |
| | 12028 | const item_ref = Air.internedToRef(item_val.toIntern()); |
| | 12029 | try extra_case_vals.items.append(gpa, item_ref); |
| | 12030 | break :gen; |
| | 12031 | } |
| | 12032 | const missing_field_count = seen_enum_fields.len - seen_field_count; |
| | 12033 | |
| | 12034 | extra_case_vals.items = try .initCapacity(gpa, missing_field_count / 2); |
| | 12035 | extra_case_vals.ranges = try .initCapacity(gpa, missing_field_count / 4); |
| | 12036 | const int_ty = cond_ty.intTagType(zcu); |
| | 12037 | |
| | 12038 | var last_val = try pt.enumValueFieldIndex(cond_ty, @intCast(min_i)); |
| | 12039 | var first_ref = Air.internedToRef(last_val.toIntern()); |
| | 12040 | seen_enum_fields[min_i] = special_members_only_src; |
| | 12041 | for (seen_enum_fields[(min_i + 1)..(max_i + 1)], (min_i + 1)..) |seen, enum_i| { |
| | 12042 | if (seen != null) continue; |
| | 12043 | seen_enum_fields[enum_i] = special_members_only_src; |
| | 12044 | |
| | 12045 | const item_val = try pt.enumValueFieldIndex(cond_ty, @intCast(enum_i)); |
| | 12046 | const item_ref = Air.internedToRef(item_val.toIntern()); |
| | 12047 | |
| | 12048 | const is_next = is_next: { |
| | 12049 | const prev_int = ip.indexToKey(last_val.toIntern()).enum_tag.int; |
| | 12050 | |
| | 12051 | const result = try arith.incrementDefinedInt(sema, int_ty, .fromInterned(prev_int)); |
| | 12052 | if (result.overflow) break :is_next false; |
| | 12053 | |
| | 12054 | const item_int = ip.indexToKey(item_val.toIntern()).enum_tag.int; |
| | 12055 | break :is_next try sema.valuesEqual(.fromInterned(item_int), result.val, int_ty); |
| | 12056 | }; |
| | 12057 | |
| | 12058 | if (is_next) { |
| | 12059 | last_val = item_val; |
| | 12060 | } else { |
| | 12061 | const last_ref = Air.internedToRef(last_val.toIntern()); |
| | 12062 | if (first_ref == last_ref) { |
| | 12063 | try extra_case_vals.items.append(gpa, first_ref); |
| | 12064 | } else { |
| | 12065 | try extra_case_vals.ranges.append(gpa, .{ first_ref, last_ref }); |
| | 12066 | } |
| | 12067 | first_ref = item_ref; |
| | 12068 | last_val = item_val; |
| | 12069 | } |
| | 12070 | } |
| | 12071 | const last_ref = Air.internedToRef(last_val.toIntern()); |
| | 12072 | if (first_ref == last_ref) { |
| | 12073 | try extra_case_vals.items.append(gpa, first_ref); |
| | 12074 | } else { |
| | 12075 | try extra_case_vals.ranges.append(gpa, .{ first_ref, last_ref }); |
| | 12076 | } |
| | 12077 | } |
| | 12078 | |
| 11952 | const air_switch_ref = try sema.analyzeSwitchRuntimeBlock( | 12079 | const air_switch_ref = try sema.analyzeSwitchRuntimeBlock( |
| 11953 | spa, | 12080 | spa, |
| 11954 | &child_block, | 12081 | &child_block, |
| ... | @@ -11960,14 +12087,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11960,14 +12087,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11960 | cond_ty, | 12087 | cond_ty, |
| 11961 | operand_src, | 12088 | operand_src, |
| 11962 | case_vals, | 12089 | case_vals, |
| 11963 | special, | 12090 | special_generic, |
| 11964 | scalar_cases_len, | 12091 | scalar_cases_len, |
| 11965 | multi_cases_len, | 12092 | multi_cases_len, |
| 11966 | union_originally, | 12093 | union_originally, |
| 11967 | raw_operand_ty, | 12094 | raw_operand_ty, |
| 11968 | err_set, | 12095 | err_set, |
| 11969 | src_node_offset, | 12096 | src_node_offset, |
| 11970 | special_prong_src, | 12097 | special_generic_src, |
| | 12098 | has_under, |
| 11971 | seen_enum_fields, | 12099 | seen_enum_fields, |
| 11972 | seen_errors, | 12100 | seen_errors, |
| 11973 | range_set, | 12101 | range_set, |
| ... | @@ -11975,6 +12103,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11975,6 +12103,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11975 | false_count, | 12103 | false_count, |
| 11976 | cond_dbg_node_index, | 12104 | cond_dbg_node_index, |
| 11977 | false, | 12105 | false, |
| | 12106 | special_members_only, |
| | 12107 | special_members_only_src, |
| | 12108 | extra_case_vals.items.items, |
| | 12109 | extra_case_vals.ranges.items, |
| 11978 | ); | 12110 | ); |
| 11979 | | 12111 | |
| 11980 | for (merges.extra_insts.items, merges.extra_src_locs.items) |placeholder_inst, dispatch_src| { | 12112 | for (merges.extra_insts.items, merges.extra_src_locs.items) |placeholder_inst, dispatch_src| { |
| ... | @@ -12058,14 +12190,15 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12058,14 +12190,15 @@ fn analyzeSwitchRuntimeBlock( |
| 12058 | operand_ty: Type, | 12190 | operand_ty: Type, |
| 12059 | operand_src: LazySrcLoc, | 12191 | operand_src: LazySrcLoc, |
| 12060 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), | 12192 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 12061 | special: SpecialProng, | 12193 | else_prong: SpecialProng, |
| 12062 | scalar_cases_len: usize, | 12194 | scalar_cases_len: usize, |
| 12063 | multi_cases_len: usize, | 12195 | multi_cases_len: usize, |
| 12064 | union_originally: bool, | 12196 | union_originally: bool, |
| 12065 | maybe_union_ty: Type, | 12197 | maybe_union_ty: Type, |
| 12066 | err_set: bool, | 12198 | err_set: bool, |
| 12067 | switch_node_offset: std.zig.Ast.Node.Offset, | 12199 | switch_node_offset: std.zig.Ast.Node.Offset, |
| 12068 | special_prong_src: LazySrcLoc, | 12200 | else_prong_src: LazySrcLoc, |
| | 12201 | else_prong_is_underscore: bool, |
| 12069 | seen_enum_fields: []?LazySrcLoc, | 12202 | seen_enum_fields: []?LazySrcLoc, |
| 12070 | seen_errors: SwitchErrorSet, | 12203 | seen_errors: SwitchErrorSet, |
| 12071 | range_set: RangeSet, | 12204 | range_set: RangeSet, |
| ... | @@ -12073,6 +12206,11 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12073,6 +12206,11 @@ fn analyzeSwitchRuntimeBlock( |
| 12073 | false_count: u8, | 12206 | false_count: u8, |
| 12074 | cond_dbg_node_index: Zir.Inst.Index, | 12207 | cond_dbg_node_index: Zir.Inst.Index, |
| 12075 | allow_err_code_unwrap: bool, | 12208 | allow_err_code_unwrap: bool, |
| | 12209 | extra_prong: ?SpecialProng, |
| | 12210 | /// May be `undefined` if `extra_prong` is `null` |
| | 12211 | extra_prong_src: LazySrcLoc, |
| | 12212 | extra_prong_items: []const Air.Inst.Ref, |
| | 12213 | extra_prong_ranges: []const [2]Air.Inst.Ref, |
| 12076 | ) CompileError!Air.Inst.Ref { | 12214 | ) CompileError!Air.Inst.Ref { |
| 12077 | const pt = sema.pt; | 12215 | const pt = sema.pt; |
| 12078 | const zcu = pt.zcu; | 12216 | const zcu = pt.zcu; |
| ... | @@ -12096,7 +12234,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12096,7 +12234,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12096 | case_block.need_debug_scope = null; // this body is emitted regardless | 12234 | case_block.need_debug_scope = null; // this body is emitted regardless |
| 12097 | defer case_block.instructions.deinit(gpa); | 12235 | defer case_block.instructions.deinit(gpa); |
| 12098 | | 12236 | |
| 12099 | var extra_index: usize = special.end; | 12237 | var extra_index: usize = else_prong.end; |
| 12100 | | 12238 | |
| 12101 | var scalar_i: usize = 0; | 12239 | var scalar_i: usize = 0; |
| 12102 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 12240 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -12158,23 +12296,42 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12158,23 +12296,42 @@ fn analyzeSwitchRuntimeBlock( |
| 12158 | | 12296 | |
| 12159 | var cases_len = scalar_cases_len; | 12297 | var cases_len = scalar_cases_len; |
| 12160 | var case_val_idx: usize = scalar_cases_len; | 12298 | var case_val_idx: usize = scalar_cases_len; |
| | 12299 | const multi_cases_len_with_extra_prong = multi_cases_len + @intFromBool(extra_prong != null); |
| 12161 | var multi_i: u32 = 0; | 12300 | var multi_i: u32 = 0; |
| 12162 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 12301 | while (multi_i < multi_cases_len_with_extra_prong) : (multi_i += 1) { |
| 12163 | const items_len = sema.code.extra[extra_index]; | 12302 | const is_extra_prong = multi_i == multi_cases_len; |
| 12164 | extra_index += 1; | 12303 | var items: []const Air.Inst.Ref = undefined; |
| 12165 | const ranges_len = sema.code.extra[extra_index]; | 12304 | var info: Zir.Inst.SwitchBlock.ProngInfo = undefined; |
| 12166 | extra_index += 1; | 12305 | var ranges: []const [2]Air.Inst.Ref = undefined; |
| 12167 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); | 12306 | var body: []const Zir.Inst.Index = undefined; |
| 12168 | extra_index += 1 + items_len + 2 * ranges_len; | 12307 | if (is_extra_prong) { |
| | 12308 | const prong = extra_prong.?; |
| | 12309 | items = extra_prong_items; |
| | 12310 | ranges = extra_prong_ranges; |
| | 12311 | body = prong.body; |
| | 12312 | info = .{ |
| | 12313 | .body_len = undefined, |
| | 12314 | .capture = prong.capture, |
| | 12315 | .is_inline = prong.is_inline, |
| | 12316 | .has_tag_capture = prong.has_tag_capture, |
| | 12317 | }; |
| | 12318 | } else { |
| | 12319 | @branchHint(.likely); |
| | 12320 | const items_len = sema.code.extra[extra_index]; |
| | 12321 | extra_index += 1; |
| | 12322 | const ranges_len = sema.code.extra[extra_index]; |
| | 12323 | extra_index += 1; |
| | 12324 | info = @bitCast(sema.code.extra[extra_index]); |
| | 12325 | extra_index += 1 + items_len + ranges_len * 2; |
| 12169 | | 12326 | |
| 12170 | const items = case_vals.items[case_val_idx..][0..items_len]; | 12327 | items = case_vals.items[case_val_idx..][0..items_len]; |
| 12171 | case_val_idx += items_len; | 12328 | case_val_idx += items_len; |
| 12172 | // TODO: @ptrCast slice once Sema supports it | 12329 | ranges = @ptrCast(case_vals.items[case_val_idx..][0 .. ranges_len * 2]); |
| 12173 | const ranges: []const [2]Air.Inst.Ref = @as([*]const [2]Air.Inst.Ref, @ptrCast(case_vals.items[case_val_idx..]))[0..ranges_len]; | 12330 | case_val_idx += ranges_len * 2; |
| 12174 | case_val_idx += ranges_len * 2; | | |
| 12175 | | 12331 | |
| 12176 | const body = sema.code.bodySlice(extra_index, info.body_len); | 12332 | body = sema.code.bodySlice(extra_index, info.body_len); |
| 12177 | extra_index += info.body_len; | 12333 | extra_index += info.body_len; |
| | 12334 | } |
| 12178 | | 12335 | |
| 12179 | case_block.instructions.shrinkRetainingCapacity(0); | 12336 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12180 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12337 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| ... | @@ -12184,14 +12341,29 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12184,14 +12341,29 @@ fn analyzeSwitchRuntimeBlock( |
| 12184 | var emit_bb = false; | 12341 | var emit_bb = false; |
| 12185 | | 12342 | |
| 12186 | for (ranges, 0..) |range_items, range_i| { | 12343 | for (ranges, 0..) |range_items, range_i| { |
| 12187 | var item = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[0], undefined) catch unreachable; | 12344 | var item = sema.resolveConstDefinedValue(block, .unneeded, range_items[0], undefined) catch unreachable; |
| 12188 | const item_last = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[1], undefined) catch unreachable; | 12345 | const item_last = sema.resolveConstDefinedValue(block, .unneeded, range_items[1], undefined) catch unreachable; |
| 12189 | | 12346 | |
| 12190 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ | 12347 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ |
| 12191 | // Previous validation has resolved any possible lazy values. | 12348 | // Previous validation has resolved any possible lazy values. |
| 12192 | const result = try arith.incrementDefinedInt(sema, operand_ty, item); | 12349 | const int_val: Value, const int_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { |
| | 12350 | .int => .{ item, operand_ty }, |
| | 12351 | .@"enum" => b: { |
| | 12352 | const int_val = Value.fromInterned(ip.indexToKey(item.toIntern()).enum_tag.int); |
| | 12353 | break :b .{ int_val, int_val.typeOf(zcu) }; |
| | 12354 | }, |
| | 12355 | else => unreachable, |
| | 12356 | }; |
| | 12357 | const result = try arith.incrementDefinedInt(sema, int_ty, int_val); |
| 12193 | assert(!result.overflow); | 12358 | assert(!result.overflow); |
| 12194 | item = result.val; | 12359 | item = switch (operand_ty.zigTypeTag(zcu)) { |
| | 12360 | .int => result.val, |
| | 12361 | .@"enum" => .fromInterned(try pt.intern(.{ .enum_tag = .{ |
| | 12362 | .ty = operand_ty.toIntern(), |
| | 12363 | .int = result.val.toIntern(), |
| | 12364 | } })), |
| | 12365 | else => unreachable, |
| | 12366 | }; |
| 12195 | }) { | 12367 | }) { |
| 12196 | cases_len += 1; | 12368 | cases_len += 1; |
| 12197 | | 12369 | |
| ... | @@ -12200,11 +12372,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12200,11 +12372,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12200 | case_block.instructions.shrinkRetainingCapacity(0); | 12372 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12201 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12373 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12202 | | 12374 | |
| 12203 | if (emit_bb) try sema.emitBackwardBranch(block, block.src(.{ .switch_case_item = .{ | 12375 | if (emit_bb) { |
| 12204 | .switch_node_offset = switch_node_offset, | 12376 | const bb_src = if (is_extra_prong) extra_prong_src else block.src(.{ .switch_case_item = .{ |
| 12205 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, | 12377 | .switch_node_offset = switch_node_offset, |
| 12206 | .item_idx = .{ .kind = .range, .index = @intCast(range_i) }, | 12378 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, |
| 12207 | } })); | 12379 | .item_idx = .{ .kind = .range, .index = @intCast(range_i) }, |
| | 12380 | } }); |
| | 12381 | try sema.emitBackwardBranch(block, bb_src); |
| | 12382 | } |
| 12208 | emit_bb = true; | 12383 | emit_bb = true; |
| 12209 | | 12384 | |
| 12210 | const prong_hint = try spa.analyzeProngRuntime( | 12385 | const prong_hint = try spa.analyzeProngRuntime( |
| ... | @@ -12249,11 +12424,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12249,11 +12424,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12249 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; | 12424 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; |
| 12250 | } else true; | 12425 | } else true; |
| 12251 | | 12426 | |
| 12252 | if (emit_bb) try sema.emitBackwardBranch(block, block.src(.{ .switch_case_item = .{ | 12427 | if (emit_bb) { |
| 12253 | .switch_node_offset = switch_node_offset, | 12428 | const bb_src = if (is_extra_prong) extra_prong_src else block.src(.{ .switch_case_item = .{ |
| 12254 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, | 12429 | .switch_node_offset = switch_node_offset, |
| 12255 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, | 12430 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, |
| 12256 | } })); | 12431 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, |
| | 12432 | } }); |
| | 12433 | try sema.emitBackwardBranch(block, bb_src); |
| | 12434 | } |
| 12257 | emit_bb = true; | 12435 | emit_bb = true; |
| 12258 | | 12436 | |
| 12259 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { | 12437 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { |
| ... | @@ -12329,11 +12507,11 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12329,11 +12507,11 @@ fn analyzeSwitchRuntimeBlock( |
| 12329 | try branch_hints.append(gpa, prong_hint); | 12507 | try branch_hints.append(gpa, prong_hint); |
| 12330 | | 12508 | |
| 12331 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + | 12509 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12332 | items.len + 2 * ranges_len + | 12510 | items.len + ranges.len * 2 + |
| 12333 | case_block.instructions.items.len); | 12511 | case_block.instructions.items.len); |
| 12334 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ | 12512 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12335 | .items_len = @intCast(items.len), | 12513 | .items_len = @intCast(items.len), |
| 12336 | .ranges_len = @intCast(ranges_len), | 12514 | .ranges_len = @intCast(ranges.len), |
| 12337 | .body_len = @intCast(case_block.instructions.items.len), | 12515 | .body_len = @intCast(case_block.instructions.items.len), |
| 12338 | })); | 12516 | })); |
| 12339 | | 12517 | |
| ... | @@ -12350,12 +12528,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12350,12 +12528,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12350 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12528 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12351 | } | 12529 | } |
| 12352 | | 12530 | |
| 12353 | const else_body: []const Air.Inst.Index = if (special.body.len != 0 or case_block.wantSafety()) else_body: { | 12531 | const else_body: []const Air.Inst.Index = if (else_prong.body.len != 0 or case_block.wantSafety()) else_body: { |
| 12354 | var emit_bb = false; | 12532 | var emit_bb = false; |
| 12355 | if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) { | 12533 | // If this is true we must have a 'true' else prong and not an underscore because |
| | 12534 | // underscore prongs can never be inlined. We've already checked for this. |
| | 12535 | if (else_prong.is_inline) switch (operand_ty.zigTypeTag(zcu)) { |
| 12356 | .@"enum" => { | 12536 | .@"enum" => { |
| 12357 | if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) { | 12537 | if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) { |
| 12358 | return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ | 12538 | return sema.fail(block, else_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ |
| 12359 | operand_ty.fmt(pt), | 12539 | operand_ty.fmt(pt), |
| 12360 | }); | 12540 | }); |
| 12361 | } | 12541 | } |
| ... | @@ -12374,22 +12554,22 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12374,22 +12554,22 @@ fn analyzeSwitchRuntimeBlock( |
| 12374 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; | 12554 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; |
| 12375 | } else true; | 12555 | } else true; |
| 12376 | | 12556 | |
| 12377 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12557 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12378 | emit_bb = true; | 12558 | emit_bb = true; |
| 12379 | | 12559 | |
| 12380 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { | 12560 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { |
| 12381 | break :h try spa.analyzeProngRuntime( | 12561 | break :h try spa.analyzeProngRuntime( |
| 12382 | &case_block, | 12562 | &case_block, |
| 12383 | .special, | 12563 | .special, |
| 12384 | special.body, | 12564 | else_prong.body, |
| 12385 | special.capture, | 12565 | else_prong.capture, |
| 12386 | child_block.src(.{ .switch_capture = .{ | 12566 | child_block.src(.{ .switch_capture = .{ |
| 12387 | .switch_node_offset = switch_node_offset, | 12567 | .switch_node_offset = switch_node_offset, |
| 12388 | .case_idx = .special, | 12568 | .case_idx = .special_else, |
| 12389 | } }), | 12569 | } }), |
| 12390 | &.{item_ref}, | 12570 | &.{item_ref}, |
| 12391 | item_ref, | 12571 | item_ref, |
| 12392 | special.has_tag_capture, | 12572 | else_prong.has_tag_capture, |
| 12393 | ); | 12573 | ); |
| 12394 | } else h: { | 12574 | } else h: { |
| 12395 | _ = try case_block.addNoOp(.unreach); | 12575 | _ = try case_block.addNoOp(.unreach); |
| ... | @@ -12411,7 +12591,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12411,7 +12591,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12411 | }, | 12591 | }, |
| 12412 | .error_set => { | 12592 | .error_set => { |
| 12413 | if (operand_ty.isAnyError(zcu)) { | 12593 | if (operand_ty.isAnyError(zcu)) { |
| 12414 | return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ | 12594 | return sema.fail(block, else_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ |
| 12415 | operand_ty.fmt(pt), | 12595 | operand_ty.fmt(pt), |
| 12416 | }); | 12596 | }); |
| 12417 | } | 12597 | } |
| ... | @@ -12430,21 +12610,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12430,21 +12610,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12430 | case_block.instructions.shrinkRetainingCapacity(0); | 12610 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12431 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12611 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12432 | | 12612 | |
| 12433 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12613 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12434 | emit_bb = true; | 12614 | emit_bb = true; |
| 12435 | | 12615 | |
| 12436 | const prong_hint = try spa.analyzeProngRuntime( | 12616 | const prong_hint = try spa.analyzeProngRuntime( |
| 12437 | &case_block, | 12617 | &case_block, |
| 12438 | .special, | 12618 | .special, |
| 12439 | special.body, | 12619 | else_prong.body, |
| 12440 | special.capture, | 12620 | else_prong.capture, |
| 12441 | child_block.src(.{ .switch_capture = .{ | 12621 | child_block.src(.{ .switch_capture = .{ |
| 12442 | .switch_node_offset = switch_node_offset, | 12622 | .switch_node_offset = switch_node_offset, |
| 12443 | .case_idx = .special, | 12623 | .case_idx = .special_else, |
| 12444 | } }), | 12624 | } }), |
| 12445 | &.{item_ref}, | 12625 | &.{item_ref}, |
| 12446 | item_ref, | 12626 | item_ref, |
| 12447 | special.has_tag_capture, | 12627 | else_prong.has_tag_capture, |
| 12448 | ); | 12628 | ); |
| 12449 | try branch_hints.append(gpa, prong_hint); | 12629 | try branch_hints.append(gpa, prong_hint); |
| 12450 | | 12630 | |
| ... | @@ -12470,21 +12650,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12470,21 +12650,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12470 | case_block.instructions.shrinkRetainingCapacity(0); | 12650 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12471 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12651 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12472 | | 12652 | |
| 12473 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12653 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12474 | emit_bb = true; | 12654 | emit_bb = true; |
| 12475 | | 12655 | |
| 12476 | const prong_hint = try spa.analyzeProngRuntime( | 12656 | const prong_hint = try spa.analyzeProngRuntime( |
| 12477 | &case_block, | 12657 | &case_block, |
| 12478 | .special, | 12658 | .special, |
| 12479 | special.body, | 12659 | else_prong.body, |
| 12480 | special.capture, | 12660 | else_prong.capture, |
| 12481 | child_block.src(.{ .switch_capture = .{ | 12661 | child_block.src(.{ .switch_capture = .{ |
| 12482 | .switch_node_offset = switch_node_offset, | 12662 | .switch_node_offset = switch_node_offset, |
| 12483 | .case_idx = .special, | 12663 | .case_idx = .special_else, |
| 12484 | } }), | 12664 | } }), |
| 12485 | &.{item_ref}, | 12665 | &.{item_ref}, |
| 12486 | item_ref, | 12666 | item_ref, |
| 12487 | special.has_tag_capture, | 12667 | else_prong.has_tag_capture, |
| 12488 | ); | 12668 | ); |
| 12489 | try branch_hints.append(gpa, prong_hint); | 12669 | try branch_hints.append(gpa, prong_hint); |
| 12490 | | 12670 | |
| ... | @@ -12507,21 +12687,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12507,21 +12687,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12507 | case_block.instructions.shrinkRetainingCapacity(0); | 12687 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12508 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12688 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12509 | | 12689 | |
| 12510 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12690 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12511 | emit_bb = true; | 12691 | emit_bb = true; |
| 12512 | | 12692 | |
| 12513 | const prong_hint = try spa.analyzeProngRuntime( | 12693 | const prong_hint = try spa.analyzeProngRuntime( |
| 12514 | &case_block, | 12694 | &case_block, |
| 12515 | .special, | 12695 | .special, |
| 12516 | special.body, | 12696 | else_prong.body, |
| 12517 | special.capture, | 12697 | else_prong.capture, |
| 12518 | child_block.src(.{ .switch_capture = .{ | 12698 | child_block.src(.{ .switch_capture = .{ |
| 12519 | .switch_node_offset = switch_node_offset, | 12699 | .switch_node_offset = switch_node_offset, |
| 12520 | .case_idx = .special, | 12700 | .case_idx = .special_else, |
| 12521 | } }), | 12701 | } }), |
| 12522 | &.{.bool_true}, | 12702 | &.{.bool_true}, |
| 12523 | .bool_true, | 12703 | .bool_true, |
| 12524 | special.has_tag_capture, | 12704 | else_prong.has_tag_capture, |
| 12525 | ); | 12705 | ); |
| 12526 | try branch_hints.append(gpa, prong_hint); | 12706 | try branch_hints.append(gpa, prong_hint); |
| 12527 | | 12707 | |
| ... | @@ -12542,21 +12722,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12542,21 +12722,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12542 | case_block.instructions.shrinkRetainingCapacity(0); | 12722 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12543 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12723 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12544 | | 12724 | |
| 12545 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12725 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12546 | emit_bb = true; | 12726 | emit_bb = true; |
| 12547 | | 12727 | |
| 12548 | const prong_hint = try spa.analyzeProngRuntime( | 12728 | const prong_hint = try spa.analyzeProngRuntime( |
| 12549 | &case_block, | 12729 | &case_block, |
| 12550 | .special, | 12730 | .special, |
| 12551 | special.body, | 12731 | else_prong.body, |
| 12552 | special.capture, | 12732 | else_prong.capture, |
| 12553 | child_block.src(.{ .switch_capture = .{ | 12733 | child_block.src(.{ .switch_capture = .{ |
| 12554 | .switch_node_offset = switch_node_offset, | 12734 | .switch_node_offset = switch_node_offset, |
| 12555 | .case_idx = .special, | 12735 | .case_idx = .special_else, |
| 12556 | } }), | 12736 | } }), |
| 12557 | &.{.bool_false}, | 12737 | &.{.bool_false}, |
| 12558 | .bool_false, | 12738 | .bool_false, |
| 12559 | special.has_tag_capture, | 12739 | else_prong.has_tag_capture, |
| 12560 | ); | 12740 | ); |
| 12561 | try branch_hints.append(gpa, prong_hint); | 12741 | try branch_hints.append(gpa, prong_hint); |
| 12562 | | 12742 | |
| ... | @@ -12572,7 +12752,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12572,7 +12752,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12572 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12752 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12573 | } | 12753 | } |
| 12574 | }, | 12754 | }, |
| 12575 | else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ | 12755 | else => return sema.fail(block, else_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ |
| 12576 | operand_ty.fmt(pt), | 12756 | operand_ty.fmt(pt), |
| 12577 | }), | 12757 | }), |
| 12578 | }; | 12758 | }; |
| ... | @@ -12581,7 +12761,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12581,7 +12761,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12581 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12761 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12582 | | 12762 | |
| 12583 | if (zcu.backendSupportsFeature(.is_named_enum_value) and | 12763 | if (zcu.backendSupportsFeature(.is_named_enum_value) and |
| 12584 | special.body.len != 0 and block.wantSafety() and | 12764 | else_prong.body.len != 0 and block.wantSafety() and |
| 12585 | operand_ty.zigTypeTag(zcu) == .@"enum" and | 12765 | operand_ty.zigTypeTag(zcu) == .@"enum" and |
| 12586 | (!operand_ty.isNonexhaustiveEnum(zcu) or union_originally)) | 12766 | (!operand_ty.isNonexhaustiveEnum(zcu) or union_originally)) |
| 12587 | { | 12767 | { |
| ... | @@ -12590,7 +12770,12 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12590,7 +12770,12 @@ fn analyzeSwitchRuntimeBlock( |
| 12590 | try sema.addSafetyCheck(&case_block, src, ok, .corrupt_switch); | 12770 | try sema.addSafetyCheck(&case_block, src, ok, .corrupt_switch); |
| 12591 | } | 12771 | } |
| 12592 | | 12772 | |
| 12593 | const analyze_body = if (union_originally and !special.is_inline) | 12773 | const else_src_idx: LazySrcLoc.Offset.SwitchCaseIndex = if (else_prong_is_underscore) |
| | 12774 | .special_under |
| | 12775 | else |
| | 12776 | .special_else; |
| | 12777 | |
| | 12778 | const analyze_body = if (union_originally and !else_prong.is_inline) |
| 12594 | for (seen_enum_fields, 0..) |seen_field, index| { | 12779 | for (seen_enum_fields, 0..) |seen_field, index| { |
| 12595 | if (seen_field != null) continue; | 12780 | if (seen_field != null) continue; |
| 12596 | const union_obj = zcu.typeToUnion(maybe_union_ty).?; | 12781 | const union_obj = zcu.typeToUnion(maybe_union_ty).?; |
| ... | @@ -12599,20 +12784,20 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12599,20 +12784,20 @@ fn analyzeSwitchRuntimeBlock( |
| 12599 | } else false | 12784 | } else false |
| 12600 | else | 12785 | else |
| 12601 | true; | 12786 | true; |
| 12602 | const else_hint: std.builtin.BranchHint = if (special.body.len != 0 and err_set and | 12787 | const else_hint: std.builtin.BranchHint = if (else_prong.body.len != 0 and err_set and |
| 12603 | try sema.maybeErrorUnwrap(&case_block, special.body, operand, operand_src, allow_err_code_unwrap)) | 12788 | try sema.maybeErrorUnwrap(&case_block, else_prong.body, operand, operand_src, allow_err_code_unwrap)) |
| 12604 | h: { | 12789 | h: { |
| 12605 | // nothing to do here. weight against error branch | 12790 | // nothing to do here. weight against error branch |
| 12606 | break :h .unlikely; | 12791 | break :h .unlikely; |
| 12607 | } else if (special.body.len != 0 and analyze_body and !special.is_inline) h: { | 12792 | } else if (else_prong.body.len != 0 and analyze_body and !else_prong.is_inline) h: { |
| 12608 | break :h try spa.analyzeProngRuntime( | 12793 | break :h try spa.analyzeProngRuntime( |
| 12609 | &case_block, | 12794 | &case_block, |
| 12610 | .special, | 12795 | .special, |
| 12611 | special.body, | 12796 | else_prong.body, |
| 12612 | special.capture, | 12797 | else_prong.capture, |
| 12613 | child_block.src(.{ .switch_capture = .{ | 12798 | child_block.src(.{ .switch_capture = .{ |
| 12614 | .switch_node_offset = switch_node_offset, | 12799 | .switch_node_offset = switch_node_offset, |
| 12615 | .case_idx = .special, | 12800 | .case_idx = else_src_idx, |
| 12616 | } }), | 12801 | } }), |
| 12617 | undefined, // case_vals may be undefined for special prongs | 12802 | undefined, // case_vals may be undefined for special prongs |
| 12618 | .none, | 12803 | .none, |
| ... | @@ -12686,7 +12871,9 @@ fn resolveSwitchComptimeLoop( | ... | @@ -12686,7 +12871,9 @@ fn resolveSwitchComptimeLoop( |
| 12686 | cond_ty: Type, | 12871 | cond_ty: Type, |
| 12687 | init_cond_val: Value, | 12872 | init_cond_val: Value, |
| 12688 | switch_node_offset: std.zig.Ast.Node.Offset, | 12873 | switch_node_offset: std.zig.Ast.Node.Offset, |
| 12689 | special: SpecialProng, | 12874 | special_members_only: ?SpecialProng, |
| | 12875 | special_generic: SpecialProng, |
| | 12876 | special_generic_is_under: bool, |
| 12690 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), | 12877 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 12691 | scalar_cases_len: u32, | 12878 | scalar_cases_len: u32, |
| 12692 | multi_cases_len: u32, | 12879 | multi_cases_len: u32, |
| ... | @@ -12706,7 +12893,9 @@ fn resolveSwitchComptimeLoop( | ... | @@ -12706,7 +12893,9 @@ fn resolveSwitchComptimeLoop( |
| 12706 | cond_val, | 12893 | cond_val, |
| 12707 | cond_ty, | 12894 | cond_ty, |
| 12708 | switch_node_offset, | 12895 | switch_node_offset, |
| 12709 | special, | 12896 | special_members_only, |
| | 12897 | special_generic, |
| | 12898 | special_generic_is_under, |
| 12710 | case_vals, | 12899 | case_vals, |
| 12711 | scalar_cases_len, | 12900 | scalar_cases_len, |
| 12712 | multi_cases_len, | 12901 | multi_cases_len, |
| ... | @@ -12754,17 +12943,20 @@ fn resolveSwitchComptime( | ... | @@ -12754,17 +12943,20 @@ fn resolveSwitchComptime( |
| 12754 | operand_val: Value, | 12943 | operand_val: Value, |
| 12755 | operand_ty: Type, | 12944 | operand_ty: Type, |
| 12756 | switch_node_offset: std.zig.Ast.Node.Offset, | 12945 | switch_node_offset: std.zig.Ast.Node.Offset, |
| 12757 | special: SpecialProng, | 12946 | special_members_only: ?SpecialProng, |
| | 12947 | special_generic: SpecialProng, |
| | 12948 | special_generic_is_under: bool, |
| 12758 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), | 12949 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 12759 | scalar_cases_len: u32, | 12950 | scalar_cases_len: u32, |
| 12760 | multi_cases_len: u32, | 12951 | multi_cases_len: u32, |
| 12761 | err_set: bool, | 12952 | err_set: bool, |
| 12762 | empty_enum: bool, | 12953 | empty_enum: bool, |
| 12763 | ) CompileError!Air.Inst.Ref { | 12954 | ) CompileError!Air.Inst.Ref { |
| | 12955 | const zcu = sema.pt.zcu; |
| 12764 | const merges = &child_block.label.?.merges; | 12956 | const merges = &child_block.label.?.merges; |
| 12765 | const resolved_operand_val = try sema.resolveLazyValue(operand_val); | 12957 | const resolved_operand_val = try sema.resolveLazyValue(operand_val); |
| 12766 | | 12958 | |
| 12767 | var extra_index: usize = special.end; | 12959 | var extra_index: usize = special_generic.end; |
| 12768 | { | 12960 | { |
| 12769 | var scalar_i: usize = 0; | 12961 | var scalar_i: usize = 0; |
| 12770 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 12962 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -12865,23 +13057,45 @@ fn resolveSwitchComptime( | ... | @@ -12865,23 +13057,45 @@ fn resolveSwitchComptime( |
| 12865 | extra_index += info.body_len; | 13057 | extra_index += info.body_len; |
| 12866 | } | 13058 | } |
| 12867 | } | 13059 | } |
| 12868 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, special.body, cond_operand); | 13060 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, special_generic.body, cond_operand); |
| 12869 | if (empty_enum) { | 13061 | if (empty_enum) { |
| 12870 | return .void_value; | 13062 | return .void_value; |
| 12871 | } | 13063 | } |
| | 13064 | if (special_members_only) |special| { |
| | 13065 | assert(operand_ty.isNonexhaustiveEnum(zcu)); |
| | 13066 | if (operand_ty.enumTagFieldIndex(operand_val, zcu)) |_| { |
| | 13067 | return spa.resolveProngComptime( |
| | 13068 | child_block, |
| | 13069 | .special, |
| | 13070 | special.body, |
| | 13071 | special.capture, |
| | 13072 | child_block.src(.{ .switch_capture = .{ |
| | 13073 | .switch_node_offset = switch_node_offset, |
| | 13074 | .case_idx = .special_else, |
| | 13075 | } }), |
| | 13076 | undefined, // case_vals may be undefined for special prongs |
| | 13077 | if (special.is_inline) cond_operand else .none, |
| | 13078 | special.has_tag_capture, |
| | 13079 | merges, |
| | 13080 | ); |
| | 13081 | } |
| | 13082 | } |
| 12872 | | 13083 | |
| 12873 | return spa.resolveProngComptime( | 13084 | return spa.resolveProngComptime( |
| 12874 | child_block, | 13085 | child_block, |
| 12875 | .special, | 13086 | .special, |
| 12876 | special.body, | 13087 | special_generic.body, |
| 12877 | special.capture, | 13088 | special_generic.capture, |
| 12878 | child_block.src(.{ .switch_capture = .{ | 13089 | child_block.src(.{ .switch_capture = .{ |
| 12879 | .switch_node_offset = switch_node_offset, | 13090 | .switch_node_offset = switch_node_offset, |
| 12880 | .case_idx = .special, | 13091 | .case_idx = if (special_generic_is_under) |
| | 13092 | .special_under |
| | 13093 | else |
| | 13094 | .special_else, |
| 12881 | } }), | 13095 | } }), |
| 12882 | undefined, // case_vals may be undefined for special prongs | 13096 | undefined, // case_vals may be undefined for special prongs |
| 12883 | if (special.is_inline) cond_operand else .none, | 13097 | if (special_generic.is_inline) cond_operand else .none, |
| 12884 | special.has_tag_capture, | 13098 | special_generic.has_tag_capture, |
| 12885 | merges, | 13099 | merges, |
| 12886 | ); | 13100 | ); |
| 12887 | } | 13101 | } |