| ... | @@ -10927,7 +10927,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -10927,7 +10927,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 10927 | const switch_src = block.nodeOffset(inst_data.src_node); | 10927 | const switch_src = block.nodeOffset(inst_data.src_node); |
| 10928 | const switch_src_node_offset = inst_data.src_node; | 10928 | const switch_src_node_offset = inst_data.src_node; |
| 10929 | const switch_operand_src = block.src(.{ .node_offset_switch_operand = switch_src_node_offset }); | 10929 | const switch_operand_src = block.src(.{ .node_offset_switch_operand = switch_src_node_offset }); |
| 10930 | const else_prong_src = block.src(.{ .node_offset_switch_special_prong = switch_src_node_offset }); | 10930 | const else_prong_src = block.src(.{ .node_offset_switch_else_prong = switch_src_node_offset }); |
| 10931 | const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); | 10931 | const extra = sema.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); |
| 10932 | const main_operand_src = block.src(.{ .node_offset_if_cond = extra.data.main_src_node_offset }); | 10932 | const main_operand_src = block.src(.{ .node_offset_if_cond = extra.data.main_src_node_offset }); |
| 10933 | const main_src = block.src(.{ .node_offset_main_token = extra.data.main_src_node_offset }); | 10933 | const main_src = block.src(.{ .node_offset_main_token = extra.data.main_src_node_offset }); |
| ... | @@ -11121,6 +11121,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11121,6 +11121,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11121 | err_val, | 11121 | err_val, |
| 11122 | operand_err_set_ty, | 11122 | operand_err_set_ty, |
| 11123 | switch_src_node_offset, | 11123 | switch_src_node_offset, |
| | 11124 | null, |
| 11124 | .{ | 11125 | .{ |
| 11125 | .body = else_case.body, | 11126 | .body = else_case.body, |
| 11126 | .end = else_case.end, | 11127 | .end = else_case.end, |
| ... | @@ -11128,6 +11129,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11128,6 +11129,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11128 | .is_inline = else_case.is_inline, | 11129 | .is_inline = else_case.is_inline, |
| 11129 | .has_tag_capture = false, | 11130 | .has_tag_capture = false, |
| 11130 | }, | 11131 | }, |
| | 11132 | false, |
| 11131 | case_vals, | 11133 | case_vals, |
| 11132 | scalar_cases_len, | 11134 | scalar_cases_len, |
| 11133 | multi_cases_len, | 11135 | multi_cases_len, |
| ... | @@ -11199,6 +11201,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11199,6 +11201,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11199 | true, | 11201 | true, |
| 11200 | switch_src_node_offset, | 11202 | switch_src_node_offset, |
| 11201 | else_prong_src, | 11203 | else_prong_src, |
| | 11204 | false, |
| 11202 | undefined, | 11205 | undefined, |
| 11203 | seen_errors, | 11206 | seen_errors, |
| 11204 | undefined, | 11207 | undefined, |
| ... | @@ -11206,6 +11209,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11206,6 +11209,10 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11206 | undefined, | 11209 | undefined, |
| 11207 | cond_dbg_node_index, | 11210 | cond_dbg_node_index, |
| 11208 | true, | 11211 | true, |
| | 11212 | null, |
| | 11213 | undefined, |
| | 11214 | &.{}, |
| | 11215 | &.{}, |
| 11209 | ); | 11216 | ); |
| 11210 | | 11217 | |
| 11211 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len + | 11218 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len + |
| ... | @@ -11242,12 +11249,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11242,12 +11249,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11242 | | 11249 | |
| 11243 | const pt = sema.pt; | 11250 | const pt = sema.pt; |
| 11244 | const zcu = pt.zcu; | 11251 | const zcu = pt.zcu; |
| | 11252 | const ip = &zcu.intern_pool; |
| 11245 | const gpa = sema.gpa; | 11253 | const gpa = sema.gpa; |
| 11246 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | 11254 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 11247 | const src = block.nodeOffset(inst_data.src_node); | 11255 | const src = block.nodeOffset(inst_data.src_node); |
| 11248 | const src_node_offset = inst_data.src_node; | 11256 | const src_node_offset = inst_data.src_node; |
| 11249 | const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); | 11257 | const operand_src = block.src(.{ .node_offset_switch_operand = src_node_offset }); |
| 11250 | const special_prong_src = block.src(.{ .node_offset_switch_special_prong = src_node_offset }); | 11258 | const else_prong_src = block.src(.{ .node_offset_switch_else_prong = src_node_offset }); |
| | 11259 | const under_prong_src = block.src(.{ .node_offset_switch_under_prong = src_node_offset }); |
| 11251 | const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); | 11260 | const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); |
| 11252 | | 11261 | |
| 11253 | const operand: SwitchProngAnalysis.Operand, const raw_operand_ty: Type = op: { | 11262 | const operand: SwitchProngAnalysis.Operand, const raw_operand_ty: Type = op: { |
| ... | @@ -11334,27 +11343,63 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11334,27 +11343,63 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11334 | var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len); | 11343 | var case_vals = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(gpa, scalar_cases_len + 2 * multi_cases_len); |
| 11335 | defer case_vals.deinit(gpa); | 11344 | defer case_vals.deinit(gpa); |
| 11336 | | 11345 | |
| 11337 | const special_prong = extra.data.bits.specialProng(); | 11346 | var single_absorbed_item: Zir.Inst.Ref = .none; |
| 11338 | const special: SpecialProng = switch (special_prong) { | 11347 | var absorbed_items: []const Zir.Inst.Ref = &.{}; |
| 11339 | .none => .{ | 11348 | var absorbed_ranges: []const Zir.Inst.Ref = &.{}; |
| 11340 | .body = &.{}, | 11349 | |
| 11341 | .end = header_extra_index, | 11350 | const special_prongs = extra.data.bits.special_prongs; |
| 11342 | .capture = .none, | 11351 | const has_else = special_prongs.hasElse(); |
| 11343 | .is_inline = false, | 11352 | const has_under = special_prongs.hasUnder(); |
| 11344 | .has_tag_capture = false, | 11353 | const special_else: SpecialProng = if (has_else) blk: { |
| 11345 | }, | 11354 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[header_extra_index]); |
| 11346 | .under, .@"else" => blk: { | 11355 | const extra_body_start = header_extra_index + 1; |
| 11347 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[header_extra_index]); | 11356 | break :blk .{ |
| 11348 | const extra_body_start = header_extra_index + 1; | 11357 | .body = sema.code.bodySlice(extra_body_start, info.body_len), |
| 11349 | break :blk .{ | 11358 | .end = extra_body_start + info.body_len, |
| 11350 | .body = sema.code.bodySlice(extra_body_start, info.body_len), | 11359 | .capture = info.capture, |
| 11351 | .end = extra_body_start + info.body_len, | 11360 | .is_inline = info.is_inline, |
| 11352 | .capture = info.capture, | 11361 | .has_tag_capture = info.has_tag_capture, |
| 11353 | .is_inline = info.is_inline, | 11362 | }; |
| 11354 | .has_tag_capture = info.has_tag_capture, | 11363 | } else .{ |
| 11355 | }; | 11364 | .body = &.{}, |
| 11356 | }, | 11365 | .end = header_extra_index, |
| | 11366 | .capture = .none, |
| | 11367 | .is_inline = false, |
| | 11368 | .has_tag_capture = false, |
| 11357 | }; | 11369 | }; |
| | 11370 | const special_under: SpecialProng = if (has_under) blk: { |
| | 11371 | var extra_index = special_else.end; |
| | 11372 | var trailing_items_len: usize = 0; |
| | 11373 | if (special_prongs.hasOneAdditionalItem()) { |
| | 11374 | single_absorbed_item = @enumFromInt(sema.code.extra[extra_index]); |
| | 11375 | extra_index += 1; |
| | 11376 | absorbed_items = @ptrCast(&single_absorbed_item); |
| | 11377 | } else if (special_prongs.hasManyAdditionalItems()) { |
| | 11378 | const items_len = sema.code.extra[extra_index]; |
| | 11379 | extra_index += 1; |
| | 11380 | const ranges_len = sema.code.extra[extra_index]; |
| | 11381 | extra_index += 1; |
| | 11382 | absorbed_items = sema.code.refSlice(extra_index + 1, items_len); |
| | 11383 | absorbed_ranges = sema.code.refSlice(extra_index + 1 + items_len, ranges_len * 2); |
| | 11384 | trailing_items_len = items_len + ranges_len * 2; |
| | 11385 | } |
| | 11386 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); |
| | 11387 | extra_index += 1 + trailing_items_len; |
| | 11388 | break :blk .{ |
| | 11389 | .body = sema.code.bodySlice(extra_index, info.body_len), |
| | 11390 | .end = extra_index + info.body_len, |
| | 11391 | .capture = info.capture, |
| | 11392 | .is_inline = info.is_inline, |
| | 11393 | .has_tag_capture = info.has_tag_capture, |
| | 11394 | }; |
| | 11395 | } else .{ |
| | 11396 | .body = &.{}, |
| | 11397 | .end = special_else.end, |
| | 11398 | .capture = .none, |
| | 11399 | .is_inline = false, |
| | 11400 | .has_tag_capture = false, |
| | 11401 | }; |
| | 11402 | const special_end = special_under.end; |
| 11358 | | 11403 | |
| 11359 | // Duplicate checking variables later also used for `inline else`. | 11404 | // Duplicate checking variables later also used for `inline else`. |
| 11360 | var seen_enum_fields: []?LazySrcLoc = &.{}; | 11405 | var seen_enum_fields: []?LazySrcLoc = &.{}; |
| ... | @@ -11374,7 +11419,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11374,7 +11419,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11374 | var else_error_ty: ?Type = null; | 11419 | var else_error_ty: ?Type = null; |
| 11375 | | 11420 | |
| 11376 | // Validate usage of '_' prongs. | 11421 | // Validate usage of '_' prongs. |
| 11377 | if (special_prong == .under and !raw_operand_ty.isNonexhaustiveEnum(zcu)) { | 11422 | if (has_under and !raw_operand_ty.isNonexhaustiveEnum(zcu)) { |
| 11378 | const msg = msg: { | 11423 | const msg = msg: { |
| 11379 | const msg = try sema.errMsg( | 11424 | const msg = try sema.errMsg( |
| 11380 | src, | 11425 | src, |
| ... | @@ -11383,7 +11428,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11383,7 +11428,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11383 | ); | 11428 | ); |
| 11384 | errdefer msg.destroy(gpa); | 11429 | errdefer msg.destroy(gpa); |
| 11385 | try sema.errNote( | 11430 | try sema.errNote( |
| 11386 | special_prong_src, | 11431 | under_prong_src, |
| 11387 | msg, | 11432 | msg, |
| 11388 | "'_' prong here", | 11433 | "'_' prong here", |
| 11389 | .{}, | 11434 | .{}, |
| ... | @@ -11408,7 +11453,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11408,7 +11453,23 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11408 | @memset(seen_enum_fields, null); | 11453 | @memset(seen_enum_fields, null); |
| 11409 | // `range_set` is used for non-exhaustive enum values that do not correspond to any tags. | 11454 | // `range_set` is used for non-exhaustive enum values that do not correspond to any tags. |
| 11410 | | 11455 | |
| 11411 | var extra_index: usize = special.end; | 11456 | for (absorbed_items, 0..) |item_ref, item_i| { |
| | 11457 | _ = try sema.validateSwitchItemEnum( |
| | 11458 | block, |
| | 11459 | seen_enum_fields, |
| | 11460 | &range_set, |
| | 11461 | item_ref, |
| | 11462 | cond_ty, |
| | 11463 | block.src(.{ .switch_case_item = .{ |
| | 11464 | .switch_node_offset = src_node_offset, |
| | 11465 | .case_idx = .special_under, |
| | 11466 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, |
| | 11467 | } }), |
| | 11468 | ); |
| | 11469 | } |
| | 11470 | try sema.validateSwitchNoRange(block, @intCast(absorbed_ranges.len), cond_ty, src_node_offset); |
| | 11471 | |
| | 11472 | var extra_index: usize = special_end; |
| 11412 | { | 11473 | { |
| 11413 | var scalar_i: u32 = 0; | 11474 | var scalar_i: u32 = 0; |
| 11414 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11475 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11466,13 +11527,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11466,13 +11527,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11466 | if (seen_src == null) break false; | 11527 | if (seen_src == null) break false; |
| 11467 | } else true; | 11528 | } else true; |
| 11468 | | 11529 | |
| 11469 | if (special_prong == .@"else") { | 11530 | if (has_else) { |
| 11470 | if (all_tags_handled and !cond_ty.isNonexhaustiveEnum(zcu)) return sema.fail( | 11531 | if (all_tags_handled) { |
| 11471 | block, | 11532 | if (cond_ty.isNonexhaustiveEnum(zcu)) { |
| 11472 | special_prong_src, | 11533 | if (has_under) return sema.fail( |
| 11473 | "unreachable else prong; all cases already handled", | 11534 | block, |
| 11474 | .{}, | 11535 | else_prong_src, |
| 11475 | ); | 11536 | "unreachable else prong; all explicit cases already handled", |
| | 11537 | .{}, |
| | 11538 | ); |
| | 11539 | } else return sema.fail( |
| | 11540 | block, |
| | 11541 | else_prong_src, |
| | 11542 | "unreachable else prong; all cases already handled", |
| | 11543 | .{}, |
| | 11544 | ); |
| | 11545 | } |
| 11476 | } else if (!all_tags_handled) { | 11546 | } else if (!all_tags_handled) { |
| 11477 | const msg = msg: { | 11547 | const msg = msg: { |
| 11478 | const msg = try sema.errMsg( | 11548 | const msg = try sema.errMsg( |
| ... | @@ -11490,7 +11560,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11490,7 +11560,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11490 | i, | 11560 | i, |
| 11491 | msg, | 11561 | msg, |
| 11492 | "unhandled enumeration value: '{f}'", | 11562 | "unhandled enumeration value: '{f}'", |
| 11493 | .{field_name.fmt(&zcu.intern_pool)}, | 11563 | .{field_name.fmt(ip)}, |
| 11494 | ); | 11564 | ); |
| 11495 | } | 11565 | } |
| 11496 | try sema.errNote( | 11566 | try sema.errNote( |
| ... | @@ -11502,11 +11572,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11502,11 +11572,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11502 | break :msg msg; | 11572 | break :msg msg; |
| 11503 | }; | 11573 | }; |
| 11504 | return sema.failWithOwnedErrorMsg(block, msg); | 11574 | return sema.failWithOwnedErrorMsg(block, msg); |
| 11505 | } else if (special_prong == .none and cond_ty.isNonexhaustiveEnum(zcu) and !union_originally) { | 11575 | } else if (special_prongs == .none and cond_ty.isNonexhaustiveEnum(zcu) and !union_originally) { |
| 11506 | return sema.fail( | 11576 | return sema.fail( |
| 11507 | block, | 11577 | block, |
| 11508 | src, | 11578 | src, |
| 11509 | "switch on non-exhaustive enum must include 'else' or '_' prong", | 11579 | "switch on non-exhaustive enum must include 'else' or '_' prong or both", |
| 11510 | .{}, | 11580 | .{}, |
| 11511 | ); | 11581 | ); |
| 11512 | } | 11582 | } |
| ... | @@ -11520,11 +11590,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11520,11 +11590,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11520 | inst_data, | 11590 | inst_data, |
| 11521 | scalar_cases_len, | 11591 | scalar_cases_len, |
| 11522 | multi_cases_len, | 11592 | multi_cases_len, |
| 11523 | .{ .body = special.body, .end = special.end, .src = special_prong_src }, | 11593 | .{ .body = special_else.body, .end = special_else.end, .src = else_prong_src }, |
| 11524 | special_prong == .@"else", | 11594 | has_else, |
| 11525 | ), | 11595 | ), |
| 11526 | .int, .comptime_int => { | 11596 | .int, .comptime_int => { |
| 11527 | var extra_index: usize = special.end; | 11597 | var extra_index: usize = special_end; |
| 11528 | { | 11598 | { |
| 11529 | var scalar_i: u32 = 0; | 11599 | var scalar_i: u32 = 0; |
| 11530 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11600 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11606,10 +11676,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11606,10 +11676,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11606 | const min_int = try cond_ty.minInt(pt, cond_ty); | 11676 | const min_int = try cond_ty.minInt(pt, cond_ty); |
| 11607 | const max_int = try cond_ty.maxInt(pt, cond_ty); | 11677 | const max_int = try cond_ty.maxInt(pt, cond_ty); |
| 11608 | if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) { | 11678 | if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) { |
| 11609 | if (special_prong == .@"else") { | 11679 | if (has_else) { |
| 11610 | return sema.fail( | 11680 | return sema.fail( |
| 11611 | block, | 11681 | block, |
| 11612 | special_prong_src, | 11682 | else_prong_src, |
| 11613 | "unreachable else prong; all cases already handled", | 11683 | "unreachable else prong; all cases already handled", |
| 11614 | .{}, | 11684 | .{}, |
| 11615 | ); | 11685 | ); |
| ... | @@ -11617,7 +11687,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11617,7 +11687,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11617 | break :check_range; | 11687 | break :check_range; |
| 11618 | } | 11688 | } |
| 11619 | } | 11689 | } |
| 11620 | if (special_prong != .@"else") { | 11690 | if (special_prongs == .none) { |
| 11621 | return sema.fail( | 11691 | return sema.fail( |
| 11622 | block, | 11692 | block, |
| 11623 | src, | 11693 | src, |
| ... | @@ -11628,7 +11698,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11628,7 +11698,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11628 | } | 11698 | } |
| 11629 | }, | 11699 | }, |
| 11630 | .bool => { | 11700 | .bool => { |
| 11631 | var extra_index: usize = special.end; | 11701 | var extra_index: usize = special_end; |
| 11632 | { | 11702 | { |
| 11633 | var scalar_i: u32 = 0; | 11703 | var scalar_i: u32 = 0; |
| 11634 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11704 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11680,31 +11750,28 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11680,31 +11750,28 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11680 | try sema.validateSwitchNoRange(block, ranges_len, cond_ty, src_node_offset); | 11750 | try sema.validateSwitchNoRange(block, ranges_len, cond_ty, src_node_offset); |
| 11681 | } | 11751 | } |
| 11682 | } | 11752 | } |
| 11683 | switch (special_prong) { | 11753 | if (has_else) { |
| 11684 | .@"else" => { | 11754 | if (true_count + false_count == 2) { |
| 11685 | if (true_count + false_count == 2) { | 11755 | return sema.fail( |
| 11686 | return sema.fail( | 11756 | block, |
| 11687 | block, | 11757 | else_prong_src, |
| 11688 | special_prong_src, | 11758 | "unreachable else prong; all cases already handled", |
| 11689 | "unreachable else prong; all cases already handled", | 11759 | .{}, |
| 11690 | .{}, | 11760 | ); |
| 11691 | ); | 11761 | } |
| 11692 | } | 11762 | } else { |
| 11693 | }, | 11763 | if (true_count + false_count < 2) { |
| 11694 | .under, .none => { | 11764 | return sema.fail( |
| 11695 | if (true_count + false_count < 2) { | 11765 | block, |
| 11696 | return sema.fail( | 11766 | src, |
| 11697 | block, | 11767 | "switch must handle all possibilities", |
| 11698 | src, | 11768 | .{}, |
| 11699 | "switch must handle all possibilities", | 11769 | ); |
| 11700 | .{}, | 11770 | } |
| 11701 | ); | | |
| 11702 | } | | |
| 11703 | }, | | |
| 11704 | } | 11771 | } |
| 11705 | }, | 11772 | }, |
| 11706 | .enum_literal, .void, .@"fn", .pointer, .type => { | 11773 | .enum_literal, .void, .@"fn", .pointer, .type => { |
| 11707 | if (special_prong != .@"else") { | 11774 | if (!has_else) { |
| 11708 | return sema.fail( | 11775 | return sema.fail( |
| 11709 | block, | 11776 | block, |
| 11710 | src, | 11777 | src, |
| ... | @@ -11716,7 +11783,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11716,7 +11783,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11716 | var seen_values = ValueSrcMap{}; | 11783 | var seen_values = ValueSrcMap{}; |
| 11717 | defer seen_values.deinit(gpa); | 11784 | defer seen_values.deinit(gpa); |
| 11718 | | 11785 | |
| 11719 | var extra_index: usize = special.end; | 11786 | var extra_index: usize = special_end; |
| 11720 | { | 11787 | { |
| 11721 | var scalar_i: u32 = 0; | 11788 | var scalar_i: u32 = 0; |
| 11722 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 11789 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -11789,6 +11856,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11789,6 +11856,16 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11789 | }), | 11856 | }), |
| 11790 | } | 11857 | } |
| 11791 | | 11858 | |
| | 11859 | var special_members_only: ?SpecialProng = null; |
| | 11860 | var special_members_only_src: LazySrcLoc = undefined; |
| | 11861 | const special_generic, const special_generic_src = if (has_under) b: { |
| | 11862 | if (has_else) { |
| | 11863 | special_members_only = special_else; |
| | 11864 | special_members_only_src = else_prong_src; |
| | 11865 | } |
| | 11866 | break :b .{ special_under, under_prong_src }; |
| | 11867 | } else .{ special_else, else_prong_src }; |
| | 11868 | |
| 11792 | const spa: SwitchProngAnalysis = .{ | 11869 | const spa: SwitchProngAnalysis = .{ |
| 11793 | .sema = sema, | 11870 | .sema = sema, |
| 11794 | .parent_block = block, | 11871 | .parent_block = block, |
| ... | @@ -11835,11 +11912,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11835,11 +11912,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11835 | defer child_block.instructions.deinit(gpa); | 11912 | defer child_block.instructions.deinit(gpa); |
| 11836 | defer merges.deinit(gpa); | 11913 | defer merges.deinit(gpa); |
| 11837 | | 11914 | |
| 11838 | if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) { | 11915 | if (scalar_cases_len + multi_cases_len == 0 and |
| | 11916 | special_members_only == null and |
| | 11917 | !special_generic.is_inline) |
| | 11918 | { |
| 11839 | if (empty_enum) { | 11919 | if (empty_enum) { |
| 11840 | return .void_value; | 11920 | return .void_value; |
| 11841 | } | 11921 | } |
| 11842 | if (special_prong == .none) { | 11922 | if (special_prongs == .none) { |
| 11843 | return sema.fail(block, src, "switch must handle all possibilities", .{}); | 11923 | return sema.fail(block, src, "switch must handle all possibilities", .{}); |
| 11844 | } | 11924 | } |
| 11845 | const init_cond = switch (operand) { | 11925 | const init_cond = switch (operand) { |
| ... | @@ -11853,7 +11933,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11853,7 +11933,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11853 | const ok = try block.addUnOp(.is_named_enum_value, init_cond); | 11933 | const ok = try block.addUnOp(.is_named_enum_value, init_cond); |
| 11854 | try sema.addSafetyCheck(block, src, ok, .corrupt_switch); | 11934 | try sema.addSafetyCheck(block, src, ok, .corrupt_switch); |
| 11855 | } | 11935 | } |
| 11856 | if (err_set and try sema.maybeErrorUnwrap(block, special.body, init_cond, operand_src, false)) { | 11936 | if (err_set and try sema.maybeErrorUnwrap(block, special_generic.body, init_cond, operand_src, false)) { |
| 11857 | return .unreachable_value; | 11937 | return .unreachable_value; |
| 11858 | } | 11938 | } |
| 11859 | } | 11939 | } |
| ... | @@ -11873,7 +11953,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11873,7 +11953,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11873 | cond_ty, | 11953 | cond_ty, |
| 11874 | cond_val, | 11954 | cond_val, |
| 11875 | src_node_offset, | 11955 | src_node_offset, |
| 11876 | special, | 11956 | special_members_only, |
| | 11957 | special_generic, |
| | 11958 | has_under, |
| 11877 | case_vals, | 11959 | case_vals, |
| 11878 | scalar_cases_len, | 11960 | scalar_cases_len, |
| 11879 | multi_cases_len, | 11961 | multi_cases_len, |
| ... | @@ -11883,15 +11965,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11883,15 +11965,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11883 | ); | 11965 | ); |
| 11884 | } | 11966 | } |
| 11885 | | 11967 | |
| 11886 | if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline and !extra.data.bits.has_continue) { | 11968 | if (scalar_cases_len + multi_cases_len == 0 and |
| | 11969 | special_members_only == null and |
| | 11970 | !special_generic.is_inline and |
| | 11971 | !extra.data.bits.has_continue) |
| | 11972 | { |
| 11887 | return spa.resolveProngComptime( | 11973 | return spa.resolveProngComptime( |
| 11888 | &child_block, | 11974 | &child_block, |
| 11889 | .special, | 11975 | .special, |
| 11890 | special.body, | 11976 | special_generic.body, |
| 11891 | special.capture, | 11977 | special_generic.capture, |
| 11892 | block.src(.{ .switch_capture = .{ | 11978 | block.src(.{ .switch_capture = .{ |
| 11893 | .switch_node_offset = src_node_offset, | 11979 | .switch_node_offset = src_node_offset, |
| 11894 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 11980 | .case_idx = if (has_under) .special_under else .special_else, |
| 11895 | } }), | 11981 | } }), |
| 11896 | undefined, // case_vals may be undefined for special prongs | 11982 | undefined, // case_vals may be undefined for special prongs |
| 11897 | .none, | 11983 | .none, |
| ... | @@ -11907,6 +11993,87 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11907,6 +11993,87 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11907 | unreachable; | 11993 | unreachable; |
| 11908 | } | 11994 | } |
| 11909 | | 11995 | |
| | 11996 | var extra_case_vals: struct { |
| | 11997 | items: std.ArrayListUnmanaged(Air.Inst.Ref), |
| | 11998 | ranges: std.ArrayListUnmanaged([2]Air.Inst.Ref), |
| | 11999 | } = .{ .items = .empty, .ranges = .empty }; |
| | 12000 | defer { |
| | 12001 | extra_case_vals.items.deinit(gpa); |
| | 12002 | extra_case_vals.ranges.deinit(gpa); |
| | 12003 | } |
| | 12004 | |
| | 12005 | // Runtime switch, if we have a special_members_only prong we need to unroll |
| | 12006 | // it to a prong with explicit items. |
| | 12007 | // Although this is potentially the same as `inline else` it does not count |
| | 12008 | // towards the backward branch quota because it's an implementation detail. |
| | 12009 | if (special_members_only != null) gen: { |
| | 12010 | assert(cond_ty.isNonexhaustiveEnum(zcu)); |
| | 12011 | |
| | 12012 | var min_i: usize = math.maxInt(usize); |
| | 12013 | var max_i: usize = 0; |
| | 12014 | var seen_field_count: usize = 0; |
| | 12015 | for (seen_enum_fields, 0..) |seen, enum_i| { |
| | 12016 | if (seen != null) { |
| | 12017 | seen_field_count += 1; |
| | 12018 | } else { |
| | 12019 | min_i = @min(min_i, enum_i); |
| | 12020 | max_i = @max(max_i, enum_i); |
| | 12021 | } |
| | 12022 | } |
| | 12023 | if (min_i == max_i) { |
| | 12024 | seen_enum_fields[min_i] = special_members_only_src; |
| | 12025 | const item_val = try pt.enumValueFieldIndex(cond_ty, @intCast(min_i)); |
| | 12026 | const item_ref = Air.internedToRef(item_val.toIntern()); |
| | 12027 | try extra_case_vals.items.append(gpa, item_ref); |
| | 12028 | break :gen; |
| | 12029 | } |
| | 12030 | const missing_field_count = seen_enum_fields.len - seen_field_count; |
| | 12031 | |
| | 12032 | extra_case_vals.items = try .initCapacity(gpa, missing_field_count / 2); |
| | 12033 | extra_case_vals.ranges = try .initCapacity(gpa, missing_field_count / 4); |
| | 12034 | const int_ty = cond_ty.intTagType(zcu); |
| | 12035 | |
| | 12036 | var last_val = try pt.enumValueFieldIndex(cond_ty, @intCast(min_i)); |
| | 12037 | var first_ref = Air.internedToRef(last_val.toIntern()); |
| | 12038 | seen_enum_fields[min_i] = special_members_only_src; |
| | 12039 | for (seen_enum_fields[(min_i + 1)..(max_i + 1)], (min_i + 1)..) |seen, enum_i| { |
| | 12040 | if (seen != null) continue; |
| | 12041 | seen_enum_fields[enum_i] = special_members_only_src; |
| | 12042 | |
| | 12043 | const item_val = try pt.enumValueFieldIndex(cond_ty, @intCast(enum_i)); |
| | 12044 | const item_ref = Air.internedToRef(item_val.toIntern()); |
| | 12045 | |
| | 12046 | const is_next = is_next: { |
| | 12047 | const prev_int = ip.indexToKey(last_val.toIntern()).enum_tag.int; |
| | 12048 | |
| | 12049 | const result = try arith.incrementDefinedInt(sema, int_ty, .fromInterned(prev_int)); |
| | 12050 | if (result.overflow) break :is_next false; |
| | 12051 | |
| | 12052 | const item_int = ip.indexToKey(item_val.toIntern()).enum_tag.int; |
| | 12053 | break :is_next try sema.valuesEqual(.fromInterned(item_int), result.val, int_ty); |
| | 12054 | }; |
| | 12055 | |
| | 12056 | if (is_next) { |
| | 12057 | last_val = item_val; |
| | 12058 | } else { |
| | 12059 | const last_ref = Air.internedToRef(last_val.toIntern()); |
| | 12060 | if (first_ref == last_ref) { |
| | 12061 | try extra_case_vals.items.append(gpa, first_ref); |
| | 12062 | } else { |
| | 12063 | try extra_case_vals.ranges.append(gpa, .{ first_ref, last_ref }); |
| | 12064 | } |
| | 12065 | first_ref = item_ref; |
| | 12066 | last_val = item_val; |
| | 12067 | } |
| | 12068 | } |
| | 12069 | const last_ref = Air.internedToRef(last_val.toIntern()); |
| | 12070 | if (first_ref == last_ref) { |
| | 12071 | try extra_case_vals.items.append(gpa, first_ref); |
| | 12072 | } else { |
| | 12073 | try extra_case_vals.ranges.append(gpa, .{ first_ref, last_ref }); |
| | 12074 | } |
| | 12075 | } |
| | 12076 | |
| 11910 | const air_switch_ref = try sema.analyzeSwitchRuntimeBlock( | 12077 | const air_switch_ref = try sema.analyzeSwitchRuntimeBlock( |
| 11911 | spa, | 12078 | spa, |
| 11912 | &child_block, | 12079 | &child_block, |
| ... | @@ -11918,14 +12085,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11918,14 +12085,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11918 | cond_ty, | 12085 | cond_ty, |
| 11919 | operand_src, | 12086 | operand_src, |
| 11920 | case_vals, | 12087 | case_vals, |
| 11921 | special, | 12088 | special_generic, |
| 11922 | scalar_cases_len, | 12089 | scalar_cases_len, |
| 11923 | multi_cases_len, | 12090 | multi_cases_len, |
| 11924 | union_originally, | 12091 | union_originally, |
| 11925 | raw_operand_ty, | 12092 | raw_operand_ty, |
| 11926 | err_set, | 12093 | err_set, |
| 11927 | src_node_offset, | 12094 | src_node_offset, |
| 11928 | special_prong_src, | 12095 | special_generic_src, |
| | 12096 | has_under, |
| 11929 | seen_enum_fields, | 12097 | seen_enum_fields, |
| 11930 | seen_errors, | 12098 | seen_errors, |
| 11931 | range_set, | 12099 | range_set, |
| ... | @@ -11933,6 +12101,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -11933,6 +12101,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 11933 | false_count, | 12101 | false_count, |
| 11934 | cond_dbg_node_index, | 12102 | cond_dbg_node_index, |
| 11935 | false, | 12103 | false, |
| | 12104 | special_members_only, |
| | 12105 | special_members_only_src, |
| | 12106 | extra_case_vals.items.items, |
| | 12107 | extra_case_vals.ranges.items, |
| 11936 | ); | 12108 | ); |
| 11937 | | 12109 | |
| 11938 | for (merges.extra_insts.items, merges.extra_src_locs.items) |placeholder_inst, dispatch_src| { | 12110 | for (merges.extra_insts.items, merges.extra_src_locs.items) |placeholder_inst, dispatch_src| { |
| ... | @@ -12016,14 +12188,15 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12016,14 +12188,15 @@ fn analyzeSwitchRuntimeBlock( |
| 12016 | operand_ty: Type, | 12188 | operand_ty: Type, |
| 12017 | operand_src: LazySrcLoc, | 12189 | operand_src: LazySrcLoc, |
| 12018 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), | 12190 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 12019 | special: SpecialProng, | 12191 | else_prong: SpecialProng, |
| 12020 | scalar_cases_len: usize, | 12192 | scalar_cases_len: usize, |
| 12021 | multi_cases_len: usize, | 12193 | multi_cases_len: usize, |
| 12022 | union_originally: bool, | 12194 | union_originally: bool, |
| 12023 | maybe_union_ty: Type, | 12195 | maybe_union_ty: Type, |
| 12024 | err_set: bool, | 12196 | err_set: bool, |
| 12025 | switch_node_offset: std.zig.Ast.Node.Offset, | 12197 | switch_node_offset: std.zig.Ast.Node.Offset, |
| 12026 | special_prong_src: LazySrcLoc, | 12198 | else_prong_src: LazySrcLoc, |
| | 12199 | else_prong_is_underscore: bool, |
| 12027 | seen_enum_fields: []?LazySrcLoc, | 12200 | seen_enum_fields: []?LazySrcLoc, |
| 12028 | seen_errors: SwitchErrorSet, | 12201 | seen_errors: SwitchErrorSet, |
| 12029 | range_set: RangeSet, | 12202 | range_set: RangeSet, |
| ... | @@ -12031,6 +12204,11 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12031,6 +12204,11 @@ fn analyzeSwitchRuntimeBlock( |
| 12031 | false_count: u8, | 12204 | false_count: u8, |
| 12032 | cond_dbg_node_index: Zir.Inst.Index, | 12205 | cond_dbg_node_index: Zir.Inst.Index, |
| 12033 | allow_err_code_unwrap: bool, | 12206 | allow_err_code_unwrap: bool, |
| | 12207 | extra_prong: ?SpecialProng, |
| | 12208 | /// May be `undefined` if `extra_prong` is `null` |
| | 12209 | extra_prong_src: LazySrcLoc, |
| | 12210 | extra_prong_items: []const Air.Inst.Ref, |
| | 12211 | extra_prong_ranges: []const [2]Air.Inst.Ref, |
| 12034 | ) CompileError!Air.Inst.Ref { | 12212 | ) CompileError!Air.Inst.Ref { |
| 12035 | const pt = sema.pt; | 12213 | const pt = sema.pt; |
| 12036 | const zcu = pt.zcu; | 12214 | const zcu = pt.zcu; |
| ... | @@ -12054,7 +12232,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12054,7 +12232,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12054 | case_block.need_debug_scope = null; // this body is emitted regardless | 12232 | case_block.need_debug_scope = null; // this body is emitted regardless |
| 12055 | defer case_block.instructions.deinit(gpa); | 12233 | defer case_block.instructions.deinit(gpa); |
| 12056 | | 12234 | |
| 12057 | var extra_index: usize = special.end; | 12235 | var extra_index: usize = else_prong.end; |
| 12058 | | 12236 | |
| 12059 | var scalar_i: usize = 0; | 12237 | var scalar_i: usize = 0; |
| 12060 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 12238 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -12116,23 +12294,42 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12116,23 +12294,42 @@ fn analyzeSwitchRuntimeBlock( |
| 12116 | | 12294 | |
| 12117 | var cases_len = scalar_cases_len; | 12295 | var cases_len = scalar_cases_len; |
| 12118 | var case_val_idx: usize = scalar_cases_len; | 12296 | var case_val_idx: usize = scalar_cases_len; |
| | 12297 | const multi_cases_len_with_extra_prong = multi_cases_len + @intFromBool(extra_prong != null); |
| 12119 | var multi_i: u32 = 0; | 12298 | var multi_i: u32 = 0; |
| 12120 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 12299 | while (multi_i < multi_cases_len_with_extra_prong) : (multi_i += 1) { |
| 12121 | const items_len = sema.code.extra[extra_index]; | 12300 | const is_extra_prong = multi_i == multi_cases_len; |
| 12122 | extra_index += 1; | 12301 | var items: []const Air.Inst.Ref = undefined; |
| 12123 | const ranges_len = sema.code.extra[extra_index]; | 12302 | var info: Zir.Inst.SwitchBlock.ProngInfo = undefined; |
| 12124 | extra_index += 1; | 12303 | var ranges: []const [2]Air.Inst.Ref = undefined; |
| 12125 | const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(sema.code.extra[extra_index]); | 12304 | var body: []const Zir.Inst.Index = undefined; |
| 12126 | extra_index += 1 + items_len + 2 * ranges_len; | 12305 | if (is_extra_prong) { |
| | 12306 | const prong = extra_prong.?; |
| | 12307 | items = extra_prong_items; |
| | 12308 | ranges = extra_prong_ranges; |
| | 12309 | body = prong.body; |
| | 12310 | info = .{ |
| | 12311 | .body_len = undefined, |
| | 12312 | .capture = prong.capture, |
| | 12313 | .is_inline = prong.is_inline, |
| | 12314 | .has_tag_capture = prong.has_tag_capture, |
| | 12315 | }; |
| | 12316 | } else { |
| | 12317 | @branchHint(.likely); |
| | 12318 | const items_len = sema.code.extra[extra_index]; |
| | 12319 | extra_index += 1; |
| | 12320 | const ranges_len = sema.code.extra[extra_index]; |
| | 12321 | extra_index += 1; |
| | 12322 | info = @bitCast(sema.code.extra[extra_index]); |
| | 12323 | extra_index += 1 + items_len + ranges_len * 2; |
| 12127 | | 12324 | |
| 12128 | const items = case_vals.items[case_val_idx..][0..items_len]; | 12325 | items = case_vals.items[case_val_idx..][0..items_len]; |
| 12129 | case_val_idx += items_len; | 12326 | case_val_idx += items_len; |
| 12130 | // TODO: @ptrCast slice once Sema supports it | 12327 | ranges = @ptrCast(case_vals.items[case_val_idx..][0 .. ranges_len * 2]); |
| 12131 | const ranges: []const [2]Air.Inst.Ref = @as([*]const [2]Air.Inst.Ref, @ptrCast(case_vals.items[case_val_idx..]))[0..ranges_len]; | 12328 | case_val_idx += ranges_len * 2; |
| 12132 | case_val_idx += ranges_len * 2; | | |
| 12133 | | 12329 | |
| 12134 | const body = sema.code.bodySlice(extra_index, info.body_len); | 12330 | body = sema.code.bodySlice(extra_index, info.body_len); |
| 12135 | extra_index += info.body_len; | 12331 | extra_index += info.body_len; |
| | 12332 | } |
| 12136 | | 12333 | |
| 12137 | case_block.instructions.shrinkRetainingCapacity(0); | 12334 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12138 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12335 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| ... | @@ -12142,14 +12339,29 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12142,14 +12339,29 @@ fn analyzeSwitchRuntimeBlock( |
| 12142 | var emit_bb = false; | 12339 | var emit_bb = false; |
| 12143 | | 12340 | |
| 12144 | for (ranges, 0..) |range_items, range_i| { | 12341 | for (ranges, 0..) |range_items, range_i| { |
| 12145 | var item = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[0], undefined) catch unreachable; | 12342 | var item = sema.resolveConstDefinedValue(block, .unneeded, range_items[0], undefined) catch unreachable; |
| 12146 | const item_last = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, range_items[1], undefined) catch unreachable; | 12343 | const item_last = sema.resolveConstDefinedValue(block, .unneeded, range_items[1], undefined) catch unreachable; |
| 12147 | | 12344 | |
| 12148 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ | 12345 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ |
| 12149 | // Previous validation has resolved any possible lazy values. | 12346 | // Previous validation has resolved any possible lazy values. |
| 12150 | const result = try arith.incrementDefinedInt(sema, operand_ty, item); | 12347 | const int_val: Value, const int_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { |
| | 12348 | .int => .{ item, operand_ty }, |
| | 12349 | .@"enum" => b: { |
| | 12350 | const int_val = Value.fromInterned(ip.indexToKey(item.toIntern()).enum_tag.int); |
| | 12351 | break :b .{ int_val, int_val.typeOf(zcu) }; |
| | 12352 | }, |
| | 12353 | else => unreachable, |
| | 12354 | }; |
| | 12355 | const result = try arith.incrementDefinedInt(sema, int_ty, int_val); |
| 12151 | assert(!result.overflow); | 12356 | assert(!result.overflow); |
| 12152 | item = result.val; | 12357 | item = switch (operand_ty.zigTypeTag(zcu)) { |
| | 12358 | .int => result.val, |
| | 12359 | .@"enum" => .fromInterned(try pt.intern(.{ .enum_tag = .{ |
| | 12360 | .ty = operand_ty.toIntern(), |
| | 12361 | .int = result.val.toIntern(), |
| | 12362 | } })), |
| | 12363 | else => unreachable, |
| | 12364 | }; |
| 12153 | }) { | 12365 | }) { |
| 12154 | cases_len += 1; | 12366 | cases_len += 1; |
| 12155 | | 12367 | |
| ... | @@ -12158,11 +12370,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12158,11 +12370,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12158 | case_block.instructions.shrinkRetainingCapacity(0); | 12370 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12159 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12371 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12160 | | 12372 | |
| 12161 | if (emit_bb) try sema.emitBackwardBranch(block, block.src(.{ .switch_case_item = .{ | 12373 | if (emit_bb) { |
| 12162 | .switch_node_offset = switch_node_offset, | 12374 | const bb_src = if (is_extra_prong) extra_prong_src else block.src(.{ .switch_case_item = .{ |
| 12163 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, | 12375 | .switch_node_offset = switch_node_offset, |
| 12164 | .item_idx = .{ .kind = .range, .index = @intCast(range_i) }, | 12376 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, |
| 12165 | } })); | 12377 | .item_idx = .{ .kind = .range, .index = @intCast(range_i) }, |
| | 12378 | } }); |
| | 12379 | try sema.emitBackwardBranch(block, bb_src); |
| | 12380 | } |
| 12166 | emit_bb = true; | 12381 | emit_bb = true; |
| 12167 | | 12382 | |
| 12168 | const prong_hint = try spa.analyzeProngRuntime( | 12383 | const prong_hint = try spa.analyzeProngRuntime( |
| ... | @@ -12207,11 +12422,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12207,11 +12422,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12207 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; | 12422 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; |
| 12208 | } else true; | 12423 | } else true; |
| 12209 | | 12424 | |
| 12210 | if (emit_bb) try sema.emitBackwardBranch(block, block.src(.{ .switch_case_item = .{ | 12425 | if (emit_bb) { |
| 12211 | .switch_node_offset = switch_node_offset, | 12426 | const bb_src = if (is_extra_prong) extra_prong_src else block.src(.{ .switch_case_item = .{ |
| 12212 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, | 12427 | .switch_node_offset = switch_node_offset, |
| 12213 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, | 12428 | .case_idx = .{ .kind = .multi, .index = @intCast(multi_i) }, |
| 12214 | } })); | 12429 | .item_idx = .{ .kind = .single, .index = @intCast(item_i) }, |
| | 12430 | } }); |
| | 12431 | try sema.emitBackwardBranch(block, bb_src); |
| | 12432 | } |
| 12215 | emit_bb = true; | 12433 | emit_bb = true; |
| 12216 | | 12434 | |
| 12217 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { | 12435 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { |
| ... | @@ -12287,11 +12505,11 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12287,11 +12505,11 @@ fn analyzeSwitchRuntimeBlock( |
| 12287 | try branch_hints.append(gpa, prong_hint); | 12505 | try branch_hints.append(gpa, prong_hint); |
| 12288 | | 12506 | |
| 12289 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + | 12507 | try cases_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr.Case).@"struct".fields.len + |
| 12290 | items.len + 2 * ranges_len + | 12508 | items.len + ranges.len * 2 + |
| 12291 | case_block.instructions.items.len); | 12509 | case_block.instructions.items.len); |
| 12292 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ | 12510 | cases_extra.appendSliceAssumeCapacity(&payloadToExtraItems(Air.SwitchBr.Case{ |
| 12293 | .items_len = @intCast(items.len), | 12511 | .items_len = @intCast(items.len), |
| 12294 | .ranges_len = @intCast(ranges_len), | 12512 | .ranges_len = @intCast(ranges.len), |
| 12295 | .body_len = @intCast(case_block.instructions.items.len), | 12513 | .body_len = @intCast(case_block.instructions.items.len), |
| 12296 | })); | 12514 | })); |
| 12297 | | 12515 | |
| ... | @@ -12308,12 +12526,14 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12308,12 +12526,14 @@ fn analyzeSwitchRuntimeBlock( |
| 12308 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12526 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12309 | } | 12527 | } |
| 12310 | | 12528 | |
| 12311 | const else_body: []const Air.Inst.Index = if (special.body.len != 0 or case_block.wantSafety()) else_body: { | 12529 | const else_body: []const Air.Inst.Index = if (else_prong.body.len != 0 or case_block.wantSafety()) else_body: { |
| 12312 | var emit_bb = false; | 12530 | var emit_bb = false; |
| 12313 | if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) { | 12531 | // If this is true we must have a 'true' else prong and not an underscore because |
| | 12532 | // underscore prongs can never be inlined. We've already checked for this. |
| | 12533 | if (else_prong.is_inline) switch (operand_ty.zigTypeTag(zcu)) { |
| 12314 | .@"enum" => { | 12534 | .@"enum" => { |
| 12315 | if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) { | 12535 | if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) { |
| 12316 | return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ | 12536 | return sema.fail(block, else_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ |
| 12317 | operand_ty.fmt(pt), | 12537 | operand_ty.fmt(pt), |
| 12318 | }); | 12538 | }); |
| 12319 | } | 12539 | } |
| ... | @@ -12332,22 +12552,22 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12332,22 +12552,22 @@ fn analyzeSwitchRuntimeBlock( |
| 12332 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; | 12552 | break :blk field_ty.zigTypeTag(zcu) != .noreturn; |
| 12333 | } else true; | 12553 | } else true; |
| 12334 | | 12554 | |
| 12335 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12555 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12336 | emit_bb = true; | 12556 | emit_bb = true; |
| 12337 | | 12557 | |
| 12338 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { | 12558 | const prong_hint: std.builtin.BranchHint = if (analyze_body) h: { |
| 12339 | break :h try spa.analyzeProngRuntime( | 12559 | break :h try spa.analyzeProngRuntime( |
| 12340 | &case_block, | 12560 | &case_block, |
| 12341 | .special, | 12561 | .special, |
| 12342 | special.body, | 12562 | else_prong.body, |
| 12343 | special.capture, | 12563 | else_prong.capture, |
| 12344 | child_block.src(.{ .switch_capture = .{ | 12564 | child_block.src(.{ .switch_capture = .{ |
| 12345 | .switch_node_offset = switch_node_offset, | 12565 | .switch_node_offset = switch_node_offset, |
| 12346 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 12566 | .case_idx = .special_else, |
| 12347 | } }), | 12567 | } }), |
| 12348 | &.{item_ref}, | 12568 | &.{item_ref}, |
| 12349 | item_ref, | 12569 | item_ref, |
| 12350 | special.has_tag_capture, | 12570 | else_prong.has_tag_capture, |
| 12351 | ); | 12571 | ); |
| 12352 | } else h: { | 12572 | } else h: { |
| 12353 | _ = try case_block.addNoOp(.unreach); | 12573 | _ = try case_block.addNoOp(.unreach); |
| ... | @@ -12369,7 +12589,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12369,7 +12589,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12369 | }, | 12589 | }, |
| 12370 | .error_set => { | 12590 | .error_set => { |
| 12371 | if (operand_ty.isAnyError(zcu)) { | 12591 | if (operand_ty.isAnyError(zcu)) { |
| 12372 | return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ | 12592 | return sema.fail(block, else_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ |
| 12373 | operand_ty.fmt(pt), | 12593 | operand_ty.fmt(pt), |
| 12374 | }); | 12594 | }); |
| 12375 | } | 12595 | } |
| ... | @@ -12388,21 +12608,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12388,21 +12608,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12388 | case_block.instructions.shrinkRetainingCapacity(0); | 12608 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12389 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12609 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12390 | | 12610 | |
| 12391 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12611 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12392 | emit_bb = true; | 12612 | emit_bb = true; |
| 12393 | | 12613 | |
| 12394 | const prong_hint = try spa.analyzeProngRuntime( | 12614 | const prong_hint = try spa.analyzeProngRuntime( |
| 12395 | &case_block, | 12615 | &case_block, |
| 12396 | .special, | 12616 | .special, |
| 12397 | special.body, | 12617 | else_prong.body, |
| 12398 | special.capture, | 12618 | else_prong.capture, |
| 12399 | child_block.src(.{ .switch_capture = .{ | 12619 | child_block.src(.{ .switch_capture = .{ |
| 12400 | .switch_node_offset = switch_node_offset, | 12620 | .switch_node_offset = switch_node_offset, |
| 12401 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 12621 | .case_idx = .special_else, |
| 12402 | } }), | 12622 | } }), |
| 12403 | &.{item_ref}, | 12623 | &.{item_ref}, |
| 12404 | item_ref, | 12624 | item_ref, |
| 12405 | special.has_tag_capture, | 12625 | else_prong.has_tag_capture, |
| 12406 | ); | 12626 | ); |
| 12407 | try branch_hints.append(gpa, prong_hint); | 12627 | try branch_hints.append(gpa, prong_hint); |
| 12408 | | 12628 | |
| ... | @@ -12428,21 +12648,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12428,21 +12648,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12428 | case_block.instructions.shrinkRetainingCapacity(0); | 12648 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12429 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12649 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12430 | | 12650 | |
| 12431 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12651 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12432 | emit_bb = true; | 12652 | emit_bb = true; |
| 12433 | | 12653 | |
| 12434 | const prong_hint = try spa.analyzeProngRuntime( | 12654 | const prong_hint = try spa.analyzeProngRuntime( |
| 12435 | &case_block, | 12655 | &case_block, |
| 12436 | .special, | 12656 | .special, |
| 12437 | special.body, | 12657 | else_prong.body, |
| 12438 | special.capture, | 12658 | else_prong.capture, |
| 12439 | child_block.src(.{ .switch_capture = .{ | 12659 | child_block.src(.{ .switch_capture = .{ |
| 12440 | .switch_node_offset = switch_node_offset, | 12660 | .switch_node_offset = switch_node_offset, |
| 12441 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 12661 | .case_idx = .special_else, |
| 12442 | } }), | 12662 | } }), |
| 12443 | &.{item_ref}, | 12663 | &.{item_ref}, |
| 12444 | item_ref, | 12664 | item_ref, |
| 12445 | special.has_tag_capture, | 12665 | else_prong.has_tag_capture, |
| 12446 | ); | 12666 | ); |
| 12447 | try branch_hints.append(gpa, prong_hint); | 12667 | try branch_hints.append(gpa, prong_hint); |
| 12448 | | 12668 | |
| ... | @@ -12465,21 +12685,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12465,21 +12685,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12465 | case_block.instructions.shrinkRetainingCapacity(0); | 12685 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12466 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12686 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12467 | | 12687 | |
| 12468 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12688 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12469 | emit_bb = true; | 12689 | emit_bb = true; |
| 12470 | | 12690 | |
| 12471 | const prong_hint = try spa.analyzeProngRuntime( | 12691 | const prong_hint = try spa.analyzeProngRuntime( |
| 12472 | &case_block, | 12692 | &case_block, |
| 12473 | .special, | 12693 | .special, |
| 12474 | special.body, | 12694 | else_prong.body, |
| 12475 | special.capture, | 12695 | else_prong.capture, |
| 12476 | child_block.src(.{ .switch_capture = .{ | 12696 | child_block.src(.{ .switch_capture = .{ |
| 12477 | .switch_node_offset = switch_node_offset, | 12697 | .switch_node_offset = switch_node_offset, |
| 12478 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 12698 | .case_idx = .special_else, |
| 12479 | } }), | 12699 | } }), |
| 12480 | &.{.bool_true}, | 12700 | &.{.bool_true}, |
| 12481 | .bool_true, | 12701 | .bool_true, |
| 12482 | special.has_tag_capture, | 12702 | else_prong.has_tag_capture, |
| 12483 | ); | 12703 | ); |
| 12484 | try branch_hints.append(gpa, prong_hint); | 12704 | try branch_hints.append(gpa, prong_hint); |
| 12485 | | 12705 | |
| ... | @@ -12500,21 +12720,21 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12500,21 +12720,21 @@ fn analyzeSwitchRuntimeBlock( |
| 12500 | case_block.instructions.shrinkRetainingCapacity(0); | 12720 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12501 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12721 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12502 | | 12722 | |
| 12503 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12723 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 12504 | emit_bb = true; | 12724 | emit_bb = true; |
| 12505 | | 12725 | |
| 12506 | const prong_hint = try spa.analyzeProngRuntime( | 12726 | const prong_hint = try spa.analyzeProngRuntime( |
| 12507 | &case_block, | 12727 | &case_block, |
| 12508 | .special, | 12728 | .special, |
| 12509 | special.body, | 12729 | else_prong.body, |
| 12510 | special.capture, | 12730 | else_prong.capture, |
| 12511 | child_block.src(.{ .switch_capture = .{ | 12731 | child_block.src(.{ .switch_capture = .{ |
| 12512 | .switch_node_offset = switch_node_offset, | 12732 | .switch_node_offset = switch_node_offset, |
| 12513 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 12733 | .case_idx = .special_else, |
| 12514 | } }), | 12734 | } }), |
| 12515 | &.{.bool_false}, | 12735 | &.{.bool_false}, |
| 12516 | .bool_false, | 12736 | .bool_false, |
| 12517 | special.has_tag_capture, | 12737 | else_prong.has_tag_capture, |
| 12518 | ); | 12738 | ); |
| 12519 | try branch_hints.append(gpa, prong_hint); | 12739 | try branch_hints.append(gpa, prong_hint); |
| 12520 | | 12740 | |
| ... | @@ -12530,7 +12750,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12530,7 +12750,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12530 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); | 12750 | cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items)); |
| 12531 | } | 12751 | } |
| 12532 | }, | 12752 | }, |
| 12533 | else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ | 12753 | else => return sema.fail(block, else_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{ |
| 12534 | operand_ty.fmt(pt), | 12754 | operand_ty.fmt(pt), |
| 12535 | }), | 12755 | }), |
| 12536 | }; | 12756 | }; |
| ... | @@ -12539,7 +12759,7 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12539,7 +12759,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12539 | case_block.error_return_trace_index = child_block.error_return_trace_index; | 12759 | case_block.error_return_trace_index = child_block.error_return_trace_index; |
| 12540 | | 12760 | |
| 12541 | if (zcu.backendSupportsFeature(.is_named_enum_value) and | 12761 | if (zcu.backendSupportsFeature(.is_named_enum_value) and |
| 12542 | special.body.len != 0 and block.wantSafety() and | 12762 | else_prong.body.len != 0 and block.wantSafety() and |
| 12543 | operand_ty.zigTypeTag(zcu) == .@"enum" and | 12763 | operand_ty.zigTypeTag(zcu) == .@"enum" and |
| 12544 | (!operand_ty.isNonexhaustiveEnum(zcu) or union_originally)) | 12764 | (!operand_ty.isNonexhaustiveEnum(zcu) or union_originally)) |
| 12545 | { | 12765 | { |
| ... | @@ -12548,7 +12768,12 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12548,7 +12768,12 @@ fn analyzeSwitchRuntimeBlock( |
| 12548 | try sema.addSafetyCheck(&case_block, src, ok, .corrupt_switch); | 12768 | try sema.addSafetyCheck(&case_block, src, ok, .corrupt_switch); |
| 12549 | } | 12769 | } |
| 12550 | | 12770 | |
| 12551 | const analyze_body = if (union_originally and !special.is_inline) | 12771 | const else_src_idx: LazySrcLoc.Offset.SwitchCaseIndex = if (else_prong_is_underscore) |
| | 12772 | .special_under |
| | 12773 | else |
| | 12774 | .special_else; |
| | 12775 | |
| | 12776 | const analyze_body = if (union_originally and !else_prong.is_inline) |
| 12552 | for (seen_enum_fields, 0..) |seen_field, index| { | 12777 | for (seen_enum_fields, 0..) |seen_field, index| { |
| 12553 | if (seen_field != null) continue; | 12778 | if (seen_field != null) continue; |
| 12554 | const union_obj = zcu.typeToUnion(maybe_union_ty).?; | 12779 | const union_obj = zcu.typeToUnion(maybe_union_ty).?; |
| ... | @@ -12557,20 +12782,20 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12557,20 +12782,20 @@ fn analyzeSwitchRuntimeBlock( |
| 12557 | } else false | 12782 | } else false |
| 12558 | else | 12783 | else |
| 12559 | true; | 12784 | true; |
| 12560 | const else_hint: std.builtin.BranchHint = if (special.body.len != 0 and err_set and | 12785 | const else_hint: std.builtin.BranchHint = if (else_prong.body.len != 0 and err_set and |
| 12561 | try sema.maybeErrorUnwrap(&case_block, special.body, operand, operand_src, allow_err_code_unwrap)) | 12786 | try sema.maybeErrorUnwrap(&case_block, else_prong.body, operand, operand_src, allow_err_code_unwrap)) |
| 12562 | h: { | 12787 | h: { |
| 12563 | // nothing to do here. weight against error branch | 12788 | // nothing to do here. weight against error branch |
| 12564 | break :h .unlikely; | 12789 | break :h .unlikely; |
| 12565 | } else if (special.body.len != 0 and analyze_body and !special.is_inline) h: { | 12790 | } else if (else_prong.body.len != 0 and analyze_body and !else_prong.is_inline) h: { |
| 12566 | break :h try spa.analyzeProngRuntime( | 12791 | break :h try spa.analyzeProngRuntime( |
| 12567 | &case_block, | 12792 | &case_block, |
| 12568 | .special, | 12793 | .special, |
| 12569 | special.body, | 12794 | else_prong.body, |
| 12570 | special.capture, | 12795 | else_prong.capture, |
| 12571 | child_block.src(.{ .switch_capture = .{ | 12796 | child_block.src(.{ .switch_capture = .{ |
| 12572 | .switch_node_offset = switch_node_offset, | 12797 | .switch_node_offset = switch_node_offset, |
| 12573 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 12798 | .case_idx = else_src_idx, |
| 12574 | } }), | 12799 | } }), |
| 12575 | undefined, // case_vals may be undefined for special prongs | 12800 | undefined, // case_vals may be undefined for special prongs |
| 12576 | .none, | 12801 | .none, |
| ... | @@ -12644,7 +12869,9 @@ fn resolveSwitchComptimeLoop( | ... | @@ -12644,7 +12869,9 @@ fn resolveSwitchComptimeLoop( |
| 12644 | cond_ty: Type, | 12869 | cond_ty: Type, |
| 12645 | init_cond_val: Value, | 12870 | init_cond_val: Value, |
| 12646 | switch_node_offset: std.zig.Ast.Node.Offset, | 12871 | switch_node_offset: std.zig.Ast.Node.Offset, |
| 12647 | special: SpecialProng, | 12872 | special_members_only: ?SpecialProng, |
| | 12873 | special_generic: SpecialProng, |
| | 12874 | special_generic_is_under: bool, |
| 12648 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), | 12875 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 12649 | scalar_cases_len: u32, | 12876 | scalar_cases_len: u32, |
| 12650 | multi_cases_len: u32, | 12877 | multi_cases_len: u32, |
| ... | @@ -12664,7 +12891,9 @@ fn resolveSwitchComptimeLoop( | ... | @@ -12664,7 +12891,9 @@ fn resolveSwitchComptimeLoop( |
| 12664 | cond_val, | 12891 | cond_val, |
| 12665 | cond_ty, | 12892 | cond_ty, |
| 12666 | switch_node_offset, | 12893 | switch_node_offset, |
| 12667 | special, | 12894 | special_members_only, |
| | 12895 | special_generic, |
| | 12896 | special_generic_is_under, |
| 12668 | case_vals, | 12897 | case_vals, |
| 12669 | scalar_cases_len, | 12898 | scalar_cases_len, |
| 12670 | multi_cases_len, | 12899 | multi_cases_len, |
| ... | @@ -12712,17 +12941,20 @@ fn resolveSwitchComptime( | ... | @@ -12712,17 +12941,20 @@ fn resolveSwitchComptime( |
| 12712 | operand_val: Value, | 12941 | operand_val: Value, |
| 12713 | operand_ty: Type, | 12942 | operand_ty: Type, |
| 12714 | switch_node_offset: std.zig.Ast.Node.Offset, | 12943 | switch_node_offset: std.zig.Ast.Node.Offset, |
| 12715 | special: SpecialProng, | 12944 | special_members_only: ?SpecialProng, |
| | 12945 | special_generic: SpecialProng, |
| | 12946 | special_generic_is_under: bool, |
| 12716 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), | 12947 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 12717 | scalar_cases_len: u32, | 12948 | scalar_cases_len: u32, |
| 12718 | multi_cases_len: u32, | 12949 | multi_cases_len: u32, |
| 12719 | err_set: bool, | 12950 | err_set: bool, |
| 12720 | empty_enum: bool, | 12951 | empty_enum: bool, |
| 12721 | ) CompileError!Air.Inst.Ref { | 12952 | ) CompileError!Air.Inst.Ref { |
| | 12953 | const zcu = sema.pt.zcu; |
| 12722 | const merges = &child_block.label.?.merges; | 12954 | const merges = &child_block.label.?.merges; |
| 12723 | const resolved_operand_val = try sema.resolveLazyValue(operand_val); | 12955 | const resolved_operand_val = try sema.resolveLazyValue(operand_val); |
| 12724 | | 12956 | |
| 12725 | var extra_index: usize = special.end; | 12957 | var extra_index: usize = special_generic.end; |
| 12726 | { | 12958 | { |
| 12727 | var scalar_i: usize = 0; | 12959 | var scalar_i: usize = 0; |
| 12728 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 12960 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| ... | @@ -12823,23 +13055,45 @@ fn resolveSwitchComptime( | ... | @@ -12823,23 +13055,45 @@ fn resolveSwitchComptime( |
| 12823 | extra_index += info.body_len; | 13055 | extra_index += info.body_len; |
| 12824 | } | 13056 | } |
| 12825 | } | 13057 | } |
| 12826 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, special.body, cond_operand); | 13058 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, special_generic.body, cond_operand); |
| 12827 | if (empty_enum) { | 13059 | if (empty_enum) { |
| 12828 | return .void_value; | 13060 | return .void_value; |
| 12829 | } | 13061 | } |
| | 13062 | if (special_members_only) |special| { |
| | 13063 | assert(operand_ty.isNonexhaustiveEnum(zcu)); |
| | 13064 | if (operand_ty.enumTagFieldIndex(operand_val, zcu)) |_| { |
| | 13065 | return spa.resolveProngComptime( |
| | 13066 | child_block, |
| | 13067 | .special, |
| | 13068 | special.body, |
| | 13069 | special.capture, |
| | 13070 | child_block.src(.{ .switch_capture = .{ |
| | 13071 | .switch_node_offset = switch_node_offset, |
| | 13072 | .case_idx = .special_else, |
| | 13073 | } }), |
| | 13074 | undefined, // case_vals may be undefined for special prongs |
| | 13075 | if (special.is_inline) cond_operand else .none, |
| | 13076 | special.has_tag_capture, |
| | 13077 | merges, |
| | 13078 | ); |
| | 13079 | } |
| | 13080 | } |
| 12830 | | 13081 | |
| 12831 | return spa.resolveProngComptime( | 13082 | return spa.resolveProngComptime( |
| 12832 | child_block, | 13083 | child_block, |
| 12833 | .special, | 13084 | .special, |
| 12834 | special.body, | 13085 | special_generic.body, |
| 12835 | special.capture, | 13086 | special_generic.capture, |
| 12836 | child_block.src(.{ .switch_capture = .{ | 13087 | child_block.src(.{ .switch_capture = .{ |
| 12837 | .switch_node_offset = switch_node_offset, | 13088 | .switch_node_offset = switch_node_offset, |
| 12838 | .case_idx = LazySrcLoc.Offset.SwitchCaseIndex.special, | 13089 | .case_idx = if (special_generic_is_under) |
| | 13090 | .special_under |
| | 13091 | else |
| | 13092 | .special_else, |
| 12839 | } }), | 13093 | } }), |
| 12840 | undefined, // case_vals may be undefined for special prongs | 13094 | undefined, // case_vals may be undefined for special prongs |
| 12841 | if (special.is_inline) cond_operand else .none, | 13095 | if (special_generic.is_inline) cond_operand else .none, |
| 12842 | special.has_tag_capture, | 13096 | special_generic.has_tag_capture, |
| 12843 | merges, | 13097 | merges, |
| 12844 | ); | 13098 | ); |
| 12845 | } | 13099 | } |