| ... | @@ -2474,7 +2474,7 @@ fn analyzeSwitch( | ... | @@ -2474,7 +2474,7 @@ fn analyzeSwitch( |
| 2474 | | 2474 | |
| 2475 | var extra_index: usize = special.end; | 2475 | var extra_index: usize = special.end; |
| 2476 | { | 2476 | { |
| 2477 | var scalar_i: usize = 0; | 2477 | var scalar_i: u32 = 0; |
| 2478 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | 2478 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 2479 | const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]); | 2479 | const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]); |
| 2480 | extra_index += 1; | 2480 | extra_index += 1; |
| ... | @@ -2489,11 +2489,12 @@ fn analyzeSwitch( | ... | @@ -2489,11 +2489,12 @@ fn analyzeSwitch( |
| 2489 | &false_count, | 2489 | &false_count, |
| 2490 | item_ref, | 2490 | item_ref, |
| 2491 | src_node_offset, | 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 | while (multi_i < multi_cases_len) : (multi_i += 1) { | 2498 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 2498 | const items_len = sema.code.extra[extra_index]; | 2499 | const items_len = sema.code.extra[extra_index]; |
| 2499 | extra_index += 1; | 2500 | extra_index += 1; |
| ... | @@ -2504,13 +2505,14 @@ fn analyzeSwitch( | ... | @@ -2504,13 +2505,14 @@ fn analyzeSwitch( |
| 2504 | const items = sema.code.refSlice(extra_index, items_len); | 2505 | const items = sema.code.refSlice(extra_index, items_len); |
| 2505 | extra_index += items_len + body_len; | 2506 | extra_index += items_len + body_len; |
| 2506 | | 2507 | |
| 2507 | for (items) |item_ref| { | 2508 | for (items) |item_ref, item_i| { |
| 2508 | try sema.validateSwitchItemBool( | 2509 | try sema.validateSwitchItemBool( |
| 2509 | block, | 2510 | block, |
| 2510 | &true_count, | 2511 | &true_count, |
| 2511 | &false_count, | 2512 | &false_count, |
| 2512 | item_ref, | 2513 | item_ref, |
| 2513 | src_node_offset, | 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,6 +2879,29 @@ fn analyzeSwitch( |
| 2877 | return sema.analyzeBlockBody(block, &child_block, merges); | 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 | fn validateSwitchRange( | 2905 | fn validateSwitchRange( |
| 2881 | sema: *Sema, | 2906 | sema: *Sema, |
| 2882 | block: *Scope.Block, | 2907 | block: *Scope.Block, |
| ... | @@ -2886,33 +2911,8 @@ fn validateSwitchRange( | ... | @@ -2886,33 +2911,8 @@ fn validateSwitchRange( |
| 2886 | src_node_offset: i32, | 2911 | src_node_offset: i32, |
| 2887 | switch_prong_src: AstGen.SwitchProngSrc, | 2912 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2888 | ) InnerError!void { | 2913 | ) InnerError!void { |
| 2889 | const first = try sema.resolveInst(first_ref); | 2914 | const first_val = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first); |
| 2890 | const last = try sema.resolveInst(last_ref); | 2915 | const last_val = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last); |
| 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 | }; | | |
| 2916 | const maybe_prev_src = try range_set.add(first_val, last_val, switch_prong_src); | 2916 | const maybe_prev_src = try range_set.add(first_val, last_val, switch_prong_src); |
| 2917 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 2917 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); |
| 2918 | } | 2918 | } |
| ... | @@ -2925,22 +2925,8 @@ fn validateSwitchItem( | ... | @@ -2925,22 +2925,8 @@ fn validateSwitchItem( |
| 2925 | src_node_offset: i32, | 2925 | src_node_offset: i32, |
| 2926 | switch_prong_src: AstGen.SwitchProngSrc, | 2926 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2927 | ) InnerError!void { | 2927 | ) InnerError!void { |
| 2928 | const item = try sema.resolveInst(item_ref); | 2928 | const item_val = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); |
| 2929 | // We have to avoid the helper functions here because we cannot construct a LazySrcLoc | 2929 | const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src); |
| 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); | | |
| 2944 | return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset); | 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,8 +2967,18 @@ fn validateSwitchItemBool( |
| 2981 | false_count: *u8, | 2967 | false_count: *u8, |
| 2982 | item_ref: zir.Inst.Ref, | 2968 | item_ref: zir.Inst.Ref, |
| 2983 | src_node_offset: i32, | 2969 | src_node_offset: i32, |
| | 2970 | switch_prong_src: AstGen.SwitchProngSrc, |
| 2984 | ) InnerError!void { | 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 | fn validateSwitchItemSparse( | 2984 | fn validateSwitchItemSparse( |