| ... | ... | @@ -2474,7 +2474,7 @@ fn analyzeSwitch( |
| 2474 | 2474 | |
| 2475 | 2475 | var extra_index: usize = special.end; |
| 2476 | 2476 | { |
| 2477 | | var scalar_i: usize = 0; |
| 2477 | var scalar_i: u32 = 0; |
| 2478 | 2478 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 2479 | 2479 | const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]); |
| 2480 | 2480 | extra_index += 1; |
| ... | ... | @@ -2489,11 +2489,12 @@ fn analyzeSwitch( |
| 2489 | 2489 | &false_count, |
| 2490 | 2490 | item_ref, |
| 2491 | 2491 | src_node_offset, |
| 2492 | .{ .scalar = scalar_i }, |
| 2492 | 2493 | ); |
| 2493 | 2494 | } |
| 2494 | 2495 | } |
| 2495 | 2496 | { |
| 2496 | | var multi_i: usize = 0; |
| 2497 | var multi_i: u32 = 0; |
| 2497 | 2498 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 2498 | 2499 | const items_len = sema.code.extra[extra_index]; |
| 2499 | 2500 | extra_index += 1; |
| ... | ... | @@ -2504,13 +2505,14 @@ fn analyzeSwitch( |
| 2504 | 2505 | const items = sema.code.refSlice(extra_index, items_len); |
| 2505 | 2506 | extra_index += items_len + body_len; |
| 2506 | 2507 | |
| 2507 | | for (items) |item_ref| { |
| 2508 | for (items) |item_ref, item_i| { |
| 2508 | 2509 | try sema.validateSwitchItemBool( |
| 2509 | 2510 | block, |
| 2510 | 2511 | &true_count, |
| 2511 | 2512 | &false_count, |
| 2512 | 2513 | item_ref, |
| 2513 | 2514 | src_node_offset, |
| 2515 | .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } }, |
| 2514 | 2516 | ); |
| 2515 | 2517 | } |
| 2516 | 2518 | |
| ... | ... | @@ -2877,6 +2879,29 @@ fn analyzeSwitch( |
| 2877 | 2879 | return sema.analyzeBlockBody(block, &child_block, merges); |
| 2878 | 2880 | } |
| 2879 | 2881 | |
| 2882 | fn resolveSwitchItemVal( |
| 2883 | sema: *Sema, |
| 2884 | block: *Scope.Block, |
| 2885 | item_ref: zir.Inst.Ref, |
| 2886 | switch_node_offset: i32, |
| 2887 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2888 | range_expand: AstGen.SwitchProngSrc.RangeExpand, |
| 2889 | ) InnerError!Value { |
| 2890 | const item = try sema.resolveInst(item_ref); |
| 2891 | // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc |
| 2892 | // because we only have the switch AST node. Only if we know for sure we need to report |
| 2893 | // a compile error do we resolve the full source locations. |
| 2894 | if (item.value()) |val| { |
| 2895 | if (val.isUndef()) { |
| 2896 | const src = switch_prong_src.resolve(block.src_decl, switch_node_offset, range_expand); |
| 2897 | return sema.failWithUseOfUndef(block, src); |
| 2898 | } |
| 2899 | return val; |
| 2900 | } |
| 2901 | const src = switch_prong_src.resolve(block.src_decl, switch_node_offset, range_expand); |
| 2902 | return sema.failWithNeededComptime(block, src); |
| 2903 | } |
| 2904 | |
| 2880 | 2905 | fn validateSwitchRange( |
| 2881 | 2906 | sema: *Sema, |
| 2882 | 2907 | block: *Scope.Block, |
| ... | ... | @@ -2886,33 +2911,8 @@ fn validateSwitchRange( |
| 2886 | 2911 | src_node_offset: i32, |
| 2887 | 2912 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2888 | 2913 | ) InnerError!void { |
| 2889 | | const first = try sema.resolveInst(first_ref); |
| 2890 | | const last = try sema.resolveInst(last_ref); |
| 2891 | | // We have to avoid the helper functions here because we cannot construct a LazySrcLoc |
| 2892 | | // because we only have the switch AST node. Only if we know for sure we need to report |
| 2893 | | // a compile error do we resolve the full source locations. |
| 2894 | | const first_val = val: { |
| 2895 | | if (first.value()) |val| { |
| 2896 | | if (val.isUndef()) { |
| 2897 | | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .first); |
| 2898 | | return sema.failWithUseOfUndef(block, src); |
| 2899 | | } |
| 2900 | | break :val val; |
| 2901 | | } |
| 2902 | | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .first); |
| 2903 | | return sema.failWithNeededComptime(block, src); |
| 2904 | | }; |
| 2905 | | const last_val = val: { |
| 2906 | | if (last.value()) |val| { |
| 2907 | | if (val.isUndef()) { |
| 2908 | | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .last); |
| 2909 | | return sema.failWithUseOfUndef(block, src); |
| 2910 | | } |
| 2911 | | break :val val; |
| 2912 | | } |
| 2913 | | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .last); |
| 2914 | | return sema.failWithNeededComptime(block, src); |
| 2915 | | }; |
| 2914 | const first_val = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first); |
| 2915 | const last_val = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last); |
| 2916 | 2916 | const maybe_prev_src = try range_set.add(first_val, last_val, switch_prong_src); |
| 2917 | 2917 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| 2918 | 2918 | } |
| ... | ... | @@ -2925,22 +2925,8 @@ fn validateSwitchItem( |
| 2925 | 2925 | src_node_offset: i32, |
| 2926 | 2926 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2927 | 2927 | ) InnerError!void { |
| 2928 | | const item = try sema.resolveInst(item_ref); |
| 2929 | | // We have to avoid the helper functions here because we cannot construct a LazySrcLoc |
| 2930 | | // because we only have the switch AST node. Only if we know for sure we need to report |
| 2931 | | // a compile error do we resolve the full source locations. |
| 2932 | | const value = val: { |
| 2933 | | if (item.value()) |val| { |
| 2934 | | if (val.isUndef()) { |
| 2935 | | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none); |
| 2936 | | return sema.failWithUseOfUndef(block, src); |
| 2937 | | } |
| 2938 | | break :val val; |
| 2939 | | } |
| 2940 | | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none); |
| 2941 | | return sema.failWithNeededComptime(block, src); |
| 2942 | | }; |
| 2943 | | const maybe_prev_src = try range_set.add(value, value, switch_prong_src); |
| 2928 | const item_val = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); |
| 2929 | const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src); |
| 2944 | 2930 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| 2945 | 2931 | } |
| 2946 | 2932 | |
| ... | ... | @@ -2981,8 +2967,18 @@ fn validateSwitchItemBool( |
| 2981 | 2967 | false_count: *u8, |
| 2982 | 2968 | item_ref: zir.Inst.Ref, |
| 2983 | 2969 | src_node_offset: i32, |
| 2970 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2984 | 2971 | ) InnerError!void { |
| 2985 | | @panic("TODO"); |
| 2972 | const item_val = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); |
| 2973 | if (item_val.toBool()) { |
| 2974 | true_count.* += 1; |
| 2975 | } else { |
| 2976 | false_count.* += 1; |
| 2977 | } |
| 2978 | if (true_count.* + false_count.* > 2) { |
| 2979 | const src = switch_prong_src.resolve(block.src_decl, src_node_offset, .none); |
| 2980 | return sema.mod.fail(&block.base, src, "duplicate switch value", .{}); |
| 2981 | } |
| 2986 | 2982 | } |
| 2987 | 2983 | |
| 2988 | 2984 | fn validateSwitchItemSparse( |