| ... | @@ -2161,10 +2161,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -2161,10 +2161,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2161 | const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | 2161 | const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; |
| 2162 | | 2162 | |
| 2163 | // Look for the label in the scope. | 2163 | // Look for the label in the scope. |
| 2164 | var scope = parent_scope; | 2164 | find_scope: switch (parent_scope.unwrap()) { |
| 2165 | find_scope: switch (scope.tag) { | 2165 | .gen_zir => |gen_zir| { |
| 2166 | .gen_zir => { | 2166 | const scope = &gen_zir.base; |
| 2167 | const gen_zir = scope.cast(GenZir).?; | | |
| 2168 | | 2167 | |
| 2169 | if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| { | 2168 | if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| { |
| 2170 | // We are breaking out of a `defer` block. | 2169 | // We are breaking out of a `defer` block. |
| ... | @@ -2185,13 +2184,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -2185,13 +2184,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2185 | } | 2184 | } |
| 2186 | } | 2185 | } |
| 2187 | // gz without or with different label, continue to parent scopes. | 2186 | // gz without or with different label, continue to parent scopes. |
| 2188 | scope = gen_zir.parent; | 2187 | continue :find_scope gen_zir.parent.unwrap(); |
| 2189 | continue :find_scope scope.tag; | | |
| 2190 | } else if (!gen_zir.allow_unlabeled_control_flow) { | 2188 | } else if (!gen_zir.allow_unlabeled_control_flow) { |
| 2191 | // This `break` is unlabeled and the gz we've found doesn't allow | 2189 | // This `break` is unlabeled and the gz we've found doesn't allow |
| 2192 | // unlabeled control flow. Continue to parent scopes. | 2190 | // unlabeled control flow. Continue to parent scopes. |
| 2193 | scope = gen_zir.parent; | 2191 | continue :find_scope gen_zir.parent.unwrap(); |
| 2194 | continue :find_scope scope.tag; | | |
| 2195 | } | 2192 | } |
| 2196 | | 2193 | |
| 2197 | const break_tag: Zir.Inst.Tag = if (gen_zir.is_inline) | 2194 | const break_tag: Zir.Inst.Tag = if (gen_zir.is_inline) |
| ... | @@ -2236,18 +2233,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -2236,18 +2233,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2236 | return .unreachable_value; | 2233 | return .unreachable_value; |
| 2237 | } | 2234 | } |
| 2238 | }, | 2235 | }, |
| 2239 | .local_val => { | 2236 | .local_val => |local_val| continue :find_scope local_val.parent.unwrap(), |
| 2240 | scope = scope.cast(Scope.LocalVal).?.parent; | 2237 | .local_ptr => |local_ptr| continue :find_scope local_ptr.parent.unwrap(), |
| 2241 | continue :find_scope scope.tag; | 2238 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 2242 | }, | | |
| 2243 | .local_ptr => { | | |
| 2244 | scope = scope.cast(Scope.LocalPtr).?.parent; | | |
| 2245 | continue :find_scope scope.tag; | | |
| 2246 | }, | | |
| 2247 | .defer_normal, .defer_error => { | | |
| 2248 | scope = scope.cast(Scope.Defer).?.parent; | | |
| 2249 | continue :find_scope scope.tag; | | |
| 2250 | }, | | |
| 2251 | .namespace => { | 2239 | .namespace => { |
| 2252 | if (opt_break_label.unwrap()) |break_label| { | 2240 | if (opt_break_label.unwrap()) |break_label| { |
| 2253 | const label_name = try astgen.identifierTokenString(break_label); | 2241 | const label_name = try astgen.identifierTokenString(break_label); |
| ... | @@ -2270,10 +2258,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) | ... | @@ -2270,10 +2258,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2270 | } | 2258 | } |
| 2271 | | 2259 | |
| 2272 | // Look for the label in the scope. | 2260 | // Look for the label in the scope. |
| 2273 | var scope = parent_scope; | 2261 | find_scope: switch (parent_scope.unwrap()) { |
| 2274 | find_scope: switch (scope.tag) { | 2262 | .gen_zir => |gen_zir| { |
| 2275 | .gen_zir => { | 2263 | const scope = &gen_zir.base; |
| 2276 | const gen_zir = scope.cast(GenZir).?; | | |
| 2277 | | 2264 | |
| 2278 | if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| { | 2265 | if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| { |
| 2279 | return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ | 2266 | return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ |
| ... | @@ -2305,24 +2292,21 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) | ... | @@ -2305,24 +2292,21 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2305 | } | 2292 | } |
| 2306 | } | 2293 | } |
| 2307 | // gz without or with different label, continue to parent scopes. | 2294 | // gz without or with different label, continue to parent scopes. |
| 2308 | scope = gen_zir.parent; | 2295 | continue :find_scope gen_zir.parent.unwrap(); |
| 2309 | continue :find_scope scope.tag; | | |
| 2310 | } else if (gen_zir.allow_unlabeled_control_flow) { | 2296 | } else if (gen_zir.allow_unlabeled_control_flow) { |
| 2311 | // This `continue` is unlabeled. If the gz we've found doesn't | 2297 | // This `continue` is unlabeled. If the gz we've found doesn't |
| 2312 | // provide a `continue` target or corresponds to a labeled | 2298 | // provide a `continue` target or corresponds to a labeled |
| 2313 | // `switch`, ignore it and continue to parent scopes. | 2299 | // `switch`, ignore it and continue to parent scopes. |
| 2314 | switch (gen_zir.continue_target) { | 2300 | switch (gen_zir.continue_target) { |
| 2315 | .none, .switch_continue => { | 2301 | .none, .switch_continue => { |
| 2316 | scope = gen_zir.parent; | 2302 | continue :find_scope gen_zir.parent.unwrap(); |
| 2317 | continue :find_scope scope.tag; | | |
| 2318 | }, | 2303 | }, |
| 2319 | .@"break" => {}, | 2304 | .@"break" => {}, |
| 2320 | } | 2305 | } |
| 2321 | } else { | 2306 | } else { |
| 2322 | // We don't have a break label and the gz we found doesn't allow | 2307 | // We don't have a break label and the gz we found doesn't allow |
| 2323 | // unlabeled control flow, so we continue to its parent scopes. | 2308 | // unlabeled control flow, so we continue to its parent scopes. |
| 2324 | scope = gen_zir.parent; | 2309 | continue :find_scope gen_zir.parent.unwrap(); |
| 2325 | continue :find_scope scope.tag; | | |
| 2326 | } | 2310 | } |
| 2327 | | 2311 | |
| 2328 | switch (gen_zir.continue_target) { | 2312 | switch (gen_zir.continue_target) { |
| ... | @@ -2360,18 +2344,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) | ... | @@ -2360,18 +2344,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2360 | }, | 2344 | }, |
| 2361 | } | 2345 | } |
| 2362 | }, | 2346 | }, |
| 2363 | .local_val => { | 2347 | .local_val => |local_val| continue :find_scope local_val.parent.unwrap(), |
| 2364 | scope = scope.cast(Scope.LocalVal).?.parent; | 2348 | .local_ptr => |local_ptr| continue :find_scope local_ptr.parent.unwrap(), |
| 2365 | continue :find_scope scope.tag; | 2349 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 2366 | }, | | |
| 2367 | .local_ptr => { | | |
| 2368 | scope = scope.cast(Scope.LocalPtr).?.parent; | | |
| 2369 | continue :find_scope scope.tag; | | |
| 2370 | }, | | |
| 2371 | .defer_normal, .defer_error => { | | |
| 2372 | scope = scope.cast(Scope.Defer).?.parent; | | |
| 2373 | continue :find_scope scope.tag; | | |
| 2374 | }, | | |
| 2375 | .namespace => { | 2350 | .namespace => { |
| 2376 | if (opt_break_label.unwrap()) |break_label| { | 2351 | if (opt_break_label.unwrap()) |break_label| { |
| 2377 | const label_name = try astgen.identifierTokenString(break_label); | 2352 | const label_name = try astgen.identifierTokenString(break_label); |
| ... | @@ -2466,33 +2441,29 @@ fn blockExpr( | ... | @@ -2466,33 +2441,29 @@ fn blockExpr( |
| 2466 | | 2441 | |
| 2467 | fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void { | 2442 | fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void { |
| 2468 | // Look for the label in the scope. | 2443 | // Look for the label in the scope. |
| 2469 | var scope = parent_scope; | 2444 | find_scope: switch (parent_scope.unwrap()) { |
| 2470 | while (true) { | 2445 | .gen_zir => |gen_zir| { |
| 2471 | switch (scope.tag) { | 2446 | if (gen_zir.label) |prev_label| { |
| 2472 | .gen_zir => { | 2447 | if (try astgen.tokenIdentEql(label, prev_label.token)) { |
| 2473 | const gen_zir = scope.cast(GenZir).?; | 2448 | const label_name = try astgen.identifierTokenString(label); |
| 2474 | if (gen_zir.label) |prev_label| { | 2449 | return astgen.failTokNotes(label, "redefinition of label '{s}'", .{ |
| 2475 | if (try astgen.tokenIdentEql(label, prev_label.token)) { | 2450 | label_name, |
| 2476 | const label_name = try astgen.identifierTokenString(label); | 2451 | }, &[_]u32{ |
| 2477 | return astgen.failTokNotes(label, "redefinition of label '{s}'", .{ | 2452 | try astgen.errNoteTok( |
| 2478 | label_name, | 2453 | prev_label.token, |
| 2479 | }, &[_]u32{ | 2454 | "previous definition here", |
| 2480 | try astgen.errNoteTok( | 2455 | .{}, |
| 2481 | prev_label.token, | 2456 | ), |
| 2482 | "previous definition here", | 2457 | }); |
| 2483 | .{}, | | |
| 2484 | ), | | |
| 2485 | }); | | |
| 2486 | } | | |
| 2487 | } | 2458 | } |
| 2488 | scope = gen_zir.parent; | 2459 | } |
| 2489 | }, | 2460 | continue :find_scope gen_zir.parent.unwrap(); |
| 2490 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 2461 | }, |
| 2491 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 2462 | .local_val => |local_val| continue :find_scope local_val.parent.unwrap(), |
| 2492 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2463 | .local_ptr => |local_ptr| continue :find_scope local_ptr.parent.unwrap(), |
| 2493 | .namespace => break, | 2464 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 2494 | .top => unreachable, | 2465 | .namespace => break :find_scope, |
| 2495 | } | 2466 | .top => unreachable, |
| 2496 | } | 2467 | } |
| 2497 | } | 2468 | } |
| 2498 | | 2469 | |
| ... | @@ -3007,18 +2978,16 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { | ... | @@ -3007,18 +2978,16 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { |
| 3007 | var need_err_code = false; | 2978 | var need_err_code = false; |
| 3008 | var scope = inner_scope; | 2979 | var scope = inner_scope; |
| 3009 | while (scope != outer_scope) { | 2980 | while (scope != outer_scope) { |
| 3010 | switch (scope.tag) { | 2981 | switch (scope.unwrap()) { |
| 3011 | .gen_zir => scope = scope.cast(GenZir).?.parent, | 2982 | .gen_zir => |gen_zir| scope = gen_zir.parent, |
| 3012 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 2983 | .local_val => |local_val| scope = local_val.parent, |
| 3013 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 2984 | .local_ptr => |local_ptr| scope = local_ptr.parent, |
| 3014 | .defer_normal => { | 2985 | .defer_normal => |defer_scope| { |
| 3015 | const defer_scope = scope.cast(Scope.Defer).?; | | |
| 3016 | scope = defer_scope.parent; | 2986 | scope = defer_scope.parent; |
| 3017 | | 2987 | |
| 3018 | have_normal = true; | 2988 | have_normal = true; |
| 3019 | }, | 2989 | }, |
| 3020 | .defer_error => { | 2990 | .defer_error => |defer_scope| { |
| 3021 | const defer_scope = scope.cast(Scope.Defer).?; | | |
| 3022 | scope = defer_scope.parent; | 2991 | scope = defer_scope.parent; |
| 3023 | | 2992 | |
| 3024 | have_err = true; | 2993 | have_err = true; |
| ... | @@ -3054,17 +3023,15 @@ fn genDefers( | ... | @@ -3054,17 +3023,15 @@ fn genDefers( |
| 3054 | | 3023 | |
| 3055 | var scope = inner_scope; | 3024 | var scope = inner_scope; |
| 3056 | while (scope != outer_scope) { | 3025 | while (scope != outer_scope) { |
| 3057 | switch (scope.tag) { | 3026 | switch (scope.unwrap()) { |
| 3058 | .gen_zir => scope = scope.cast(GenZir).?.parent, | 3027 | .gen_zir => |gen_zir| scope = gen_zir.parent, |
| 3059 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 3028 | .local_val => |local_val| scope = local_val.parent, |
| 3060 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 3029 | .local_ptr => |local_ptr| scope = local_ptr.parent, |
| 3061 | .defer_normal => { | 3030 | .defer_normal => |defer_scope| { |
| 3062 | const defer_scope = scope.cast(Scope.Defer).?; | | |
| 3063 | scope = defer_scope.parent; | 3031 | scope = defer_scope.parent; |
| 3064 | try gz.addDefer(defer_scope.index, defer_scope.len); | 3032 | try gz.addDefer(defer_scope.index, defer_scope.len); |
| 3065 | }, | 3033 | }, |
| 3066 | .defer_error => { | 3034 | .defer_error => |defer_scope| { |
| 3067 | const defer_scope = scope.cast(Scope.Defer).?; | | |
| 3068 | scope = defer_scope.parent; | 3035 | scope = defer_scope.parent; |
| 3069 | switch (which_ones) { | 3036 | switch (which_ones) { |
| 3070 | .both_sans_err => { | 3037 | .both_sans_err => { |
| ... | @@ -3107,10 +3074,9 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v | ... | @@ -3107,10 +3074,9 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3107 | | 3074 | |
| 3108 | var scope = inner_scope; | 3075 | var scope = inner_scope; |
| 3109 | while (scope != outer_scope) { | 3076 | while (scope != outer_scope) { |
| 3110 | switch (scope.tag) { | 3077 | switch (scope.unwrap()) { |
| 3111 | .gen_zir => scope = scope.cast(GenZir).?.parent, | 3078 | .gen_zir => |gen_zir| scope = gen_zir.parent, |
| 3112 | .local_val => { | 3079 | .local_val => |s| { |
| 3113 | const s = scope.cast(Scope.LocalVal).?; | | |
| 3114 | if (s.used == .none and s.discarded == .none) { | 3080 | if (s.used == .none and s.discarded == .none) { |
| 3115 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); | 3081 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 3116 | } else if (s.used != .none and s.discarded != .none) { | 3082 | } else if (s.used != .none and s.discarded != .none) { |
| ... | @@ -3120,8 +3086,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v | ... | @@ -3120,8 +3086,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3120 | } | 3086 | } |
| 3121 | scope = s.parent; | 3087 | scope = s.parent; |
| 3122 | }, | 3088 | }, |
| 3123 | .local_ptr => { | 3089 | .local_ptr => |s| { |
| 3124 | const s = scope.cast(Scope.LocalPtr).?; | | |
| 3125 | if (s.used == .none and s.discarded == .none) { | 3090 | if (s.used == .none and s.discarded == .none) { |
| 3126 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); | 3091 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 3127 | } else { | 3092 | } else { |
| ... | @@ -3136,10 +3101,9 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v | ... | @@ -3136,10 +3101,9 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3136 | }); | 3101 | }); |
| 3137 | } | 3102 | } |
| 3138 | } | 3103 | } |
| 3139 | | | |
| 3140 | scope = s.parent; | 3104 | scope = s.parent; |
| 3141 | }, | 3105 | }, |
| 3142 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 3106 | .defer_normal, .defer_error => |defer_scope| scope = defer_scope.parent, |
| 3143 | .namespace => unreachable, | 3107 | .namespace => unreachable, |
| 3144 | .top => unreachable, | 3108 | .top => unreachable, |
| 3145 | } | 3109 | } |
| ... | @@ -4805,13 +4769,11 @@ fn testDecl( | ... | @@ -4805,13 +4769,11 @@ fn testDecl( |
| 4805 | | 4769 | |
| 4806 | // Local variables, including function parameters. | 4770 | // Local variables, including function parameters. |
| 4807 | const name_str_index = try astgen.identAsString(test_name_token); | 4771 | const name_str_index = try astgen.identAsString(test_name_token); |
| 4808 | var s = scope; | | |
| 4809 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already | 4772 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already |
| 4810 | var num_namespaces_out: u32 = 0; | 4773 | var num_namespaces_out: u32 = 0; |
| 4811 | var capturing_namespace: ?*Scope.Namespace = null; | 4774 | var capturing_namespace: ?*Scope.Namespace = null; |
| 4812 | while (true) switch (s.tag) { | 4775 | find_scope: switch (scope.unwrap()) { |
| 4813 | .local_val => { | 4776 | .local_val => |local_val| { |
| 4814 | const local_val = s.cast(Scope.LocalVal).?; | | |
| 4815 | if (local_val.name == name_str_index) { | 4777 | if (local_val.name == name_str_index) { |
| 4816 | local_val.used = .fromToken(test_name_token); | 4778 | local_val.used = .fromToken(test_name_token); |
| 4817 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ | 4779 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ |
| ... | @@ -4822,10 +4784,9 @@ fn testDecl( | ... | @@ -4822,10 +4784,9 @@ fn testDecl( |
| 4822 | }), | 4784 | }), |
| 4823 | }); | 4785 | }); |
| 4824 | } | 4786 | } |
| 4825 | s = local_val.parent; | 4787 | continue :find_scope local_val.parent.unwrap(); |
| 4826 | }, | 4788 | }, |
| 4827 | .local_ptr => { | 4789 | .local_ptr => |local_ptr| { |
| 4828 | const local_ptr = s.cast(Scope.LocalPtr).?; | | |
| 4829 | if (local_ptr.name == name_str_index) { | 4790 | if (local_ptr.name == name_str_index) { |
| 4830 | local_ptr.used = .fromToken(test_name_token); | 4791 | local_ptr.used = .fromToken(test_name_token); |
| 4831 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ | 4792 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ |
| ... | @@ -4836,12 +4797,11 @@ fn testDecl( | ... | @@ -4836,12 +4797,11 @@ fn testDecl( |
| 4836 | }), | 4797 | }), |
| 4837 | }); | 4798 | }); |
| 4838 | } | 4799 | } |
| 4839 | s = local_ptr.parent; | 4800 | continue :find_scope local_ptr.parent.unwrap(); |
| 4840 | }, | 4801 | }, |
| 4841 | .gen_zir => s = s.cast(GenZir).?.parent, | 4802 | .gen_zir => |gen_zir| continue :find_scope gen_zir.parent.unwrap(), |
| 4842 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 4803 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 4843 | .namespace => { | 4804 | .namespace => |ns| { |
| 4844 | const ns = s.cast(Scope.Namespace).?; | | |
| 4845 | if (ns.decls.get(name_str_index)) |i| { | 4805 | if (ns.decls.get(name_str_index)) |i| { |
| 4846 | if (found_already) |f| { | 4806 | if (found_already) |f| { |
| 4847 | return astgen.failTokNotes(test_name_token, "ambiguous reference", .{}, &.{ | 4807 | return astgen.failTokNotes(test_name_token, "ambiguous reference", .{}, &.{ |
| ... | @@ -4854,10 +4814,10 @@ fn testDecl( | ... | @@ -4854,10 +4814,10 @@ fn testDecl( |
| 4854 | } | 4814 | } |
| 4855 | num_namespaces_out += 1; | 4815 | num_namespaces_out += 1; |
| 4856 | capturing_namespace = ns; | 4816 | capturing_namespace = ns; |
| 4857 | s = ns.parent; | 4817 | continue :find_scope ns.parent.unwrap(); |
| 4858 | }, | 4818 | }, |
| 4859 | .top => break, | 4819 | .top => break :find_scope, |
| 4860 | }; | 4820 | } |
| 4861 | if (found_already == null) { | 4821 | if (found_already == null) { |
| 4862 | const ident_name = try astgen.identifierTokenString(test_name_token); | 4822 | const ident_name = try astgen.identifierTokenString(test_name_token); |
| 4863 | return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name}); | 4823 | return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name}); |
| ... | @@ -8409,7 +8369,6 @@ fn localVarRef( | ... | @@ -8409,7 +8369,6 @@ fn localVarRef( |
| 8409 | ) InnerError!Zir.Inst.Ref { | 8369 | ) InnerError!Zir.Inst.Ref { |
| 8410 | const astgen = gz.astgen; | 8370 | const astgen = gz.astgen; |
| 8411 | const name_str_index = try astgen.identAsString(ident_token); | 8371 | const name_str_index = try astgen.identAsString(ident_token); |
| 8412 | var s = scope; | | |
| 8413 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already | 8372 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already |
| 8414 | var found_needs_tunnel: bool = undefined; // defined when `found_already != null` | 8373 | var found_needs_tunnel: bool = undefined; // defined when `found_already != null` |
| 8415 | var found_namespaces_out: u32 = undefined; // defined when `found_already != null` | 8374 | var found_namespaces_out: u32 = undefined; // defined when `found_already != null` |
| ... | @@ -8419,10 +8378,8 @@ fn localVarRef( | ... | @@ -8419,10 +8378,8 @@ fn localVarRef( |
| 8419 | // defined by `num_namespaces_out != 0` | 8378 | // defined by `num_namespaces_out != 0` |
| 8420 | var capturing_namespace: *Scope.Namespace = undefined; | 8379 | var capturing_namespace: *Scope.Namespace = undefined; |
| 8421 | | 8380 | |
| 8422 | while (true) switch (s.tag) { | 8381 | find_scope: switch (scope.unwrap()) { |
| 8423 | .local_val => { | 8382 | .local_val => |local_val| { |
| 8424 | const local_val = s.cast(Scope.LocalVal).?; | | |
| 8425 | | | |
| 8426 | if (local_val.name == name_str_index) { | 8383 | if (local_val.name == name_str_index) { |
| 8427 | // Locals cannot shadow anything, so we do not need to look for ambiguous | 8384 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 8428 | // references in this case. | 8385 | // references in this case. |
| ... | @@ -8445,10 +8402,9 @@ fn localVarRef( | ... | @@ -8445,10 +8402,9 @@ fn localVarRef( |
| 8445 | | 8402 | |
| 8446 | return rvalueNoCoercePreRef(gz, ri, value_inst, ident); | 8403 | return rvalueNoCoercePreRef(gz, ri, value_inst, ident); |
| 8447 | } | 8404 | } |
| 8448 | s = local_val.parent; | 8405 | continue :find_scope local_val.parent.unwrap(); |
| 8449 | }, | 8406 | }, |
| 8450 | .local_ptr => { | 8407 | .local_ptr => |local_ptr| { |
| 8451 | const local_ptr = s.cast(Scope.LocalPtr).?; | | |
| 8452 | if (local_ptr.name == name_str_index) { | 8408 | if (local_ptr.name == name_str_index) { |
| 8453 | if (ri.rl == .discard and ri.ctx == .assignment) { | 8409 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 8454 | local_ptr.discarded = .fromToken(ident_token); | 8410 | local_ptr.discarded = .fromToken(ident_token); |
| ... | @@ -8497,12 +8453,11 @@ fn localVarRef( | ... | @@ -8497,12 +8453,11 @@ fn localVarRef( |
| 8497 | }, | 8453 | }, |
| 8498 | } | 8454 | } |
| 8499 | } | 8455 | } |
| 8500 | s = local_ptr.parent; | 8456 | continue :find_scope local_ptr.parent.unwrap(); |
| 8501 | }, | 8457 | }, |
| 8502 | .gen_zir => s = s.cast(GenZir).?.parent, | 8458 | .gen_zir => |gen_zir| continue :find_scope gen_zir.parent.unwrap(), |
| 8503 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 8459 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 8504 | .namespace => { | 8460 | .namespace => |ns| { |
| 8505 | const ns = s.cast(Scope.Namespace).?; | | |
| 8506 | if (ns.decls.get(name_str_index)) |i| { | 8461 | if (ns.decls.get(name_str_index)) |i| { |
| 8507 | if (found_already) |f| { | 8462 | if (found_already) |f| { |
| 8508 | return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{ | 8463 | return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{ |
| ... | @@ -8517,10 +8472,10 @@ fn localVarRef( | ... | @@ -8517,10 +8472,10 @@ fn localVarRef( |
| 8517 | } | 8472 | } |
| 8518 | num_namespaces_out += 1; | 8473 | num_namespaces_out += 1; |
| 8519 | capturing_namespace = ns; | 8474 | capturing_namespace = ns; |
| 8520 | s = ns.parent; | 8475 | continue :find_scope ns.parent.unwrap(); |
| 8521 | }, | 8476 | }, |
| 8522 | .top => break, | 8477 | .top => break :find_scope, |
| 8523 | }; | 8478 | } |
| 8524 | if (found_already == null) { | 8479 | if (found_already == null) { |
| 8525 | const ident_name = try astgen.identifierTokenString(ident_token); | 8480 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 8526 | return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); | 8481 | return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); |
| ... | @@ -11812,6 +11767,26 @@ const Scope = struct { | ... | @@ -11812,6 +11767,26 @@ const Scope = struct { |
| 11812 | }; | 11767 | }; |
| 11813 | } | 11768 | } |
| 11814 | | 11769 | |
| | 11770 | fn unwrap(base: *Scope) Unwrapped { |
| | 11771 | return switch (base.tag) { |
| | 11772 | inline else => |tag| @unionInit( |
| | 11773 | Unwrapped, |
| | 11774 | @tagName(tag), |
| | 11775 | @alignCast(@fieldParentPtr("base", base)), |
| | 11776 | ), |
| | 11777 | }; |
| | 11778 | } |
| | 11779 | |
| | 11780 | const Unwrapped = union(Tag) { |
| | 11781 | gen_zir: *GenZir, |
| | 11782 | local_val: *LocalVal, |
| | 11783 | local_ptr: *LocalPtr, |
| | 11784 | defer_normal: *Defer, |
| | 11785 | defer_error: *Defer, |
| | 11786 | namespace: *Namespace, |
| | 11787 | top: *Top, |
| | 11788 | }; |
| | 11789 | |
| 11815 | const Tag = enum { | 11790 | const Tag = enum { |
| 11816 | gen_zir, | 11791 | gen_zir, |
| 11817 | local_val, | 11792 | local_val, |
| ... | @@ -13408,11 +13383,9 @@ fn detectLocalShadowing( | ... | @@ -13408,11 +13383,9 @@ fn detectLocalShadowing( |
| 13408 | }); | 13383 | }); |
| 13409 | } | 13384 | } |
| 13410 | | 13385 | |
| 13411 | var s = scope; | | |
| 13412 | var outer_scope = false; | 13386 | var outer_scope = false; |
| 13413 | while (true) switch (s.tag) { | 13387 | find_scope: switch (scope.unwrap()) { |
| 13414 | .local_val => { | 13388 | .local_val => |local_val| { |
| 13415 | const local_val = s.cast(Scope.LocalVal).?; | | |
| 13416 | if (local_val.name == ident_name) { | 13389 | if (local_val.name == ident_name) { |
| 13417 | const name_slice = mem.span(astgen.nullTerminatedString(ident_name)); | 13390 | const name_slice = mem.span(astgen.nullTerminatedString(ident_name)); |
| 13418 | const name = try gpa.dupe(u8, name_slice); | 13391 | const name = try gpa.dupe(u8, name_slice); |
| ... | @@ -13438,10 +13411,9 @@ fn detectLocalShadowing( | ... | @@ -13438,10 +13411,9 @@ fn detectLocalShadowing( |
| 13438 | ), | 13411 | ), |
| 13439 | }); | 13412 | }); |
| 13440 | } | 13413 | } |
| 13441 | s = local_val.parent; | 13414 | continue :find_scope local_val.parent.unwrap(); |
| 13442 | }, | 13415 | }, |
| 13443 | .local_ptr => { | 13416 | .local_ptr => |local_ptr| { |
| 13444 | const local_ptr = s.cast(Scope.LocalPtr).?; | | |
| 13445 | if (local_ptr.name == ident_name) { | 13417 | if (local_ptr.name == ident_name) { |
| 13446 | const name_slice = mem.span(astgen.nullTerminatedString(ident_name)); | 13418 | const name_slice = mem.span(astgen.nullTerminatedString(ident_name)); |
| 13447 | const name = try gpa.dupe(u8, name_slice); | 13419 | const name = try gpa.dupe(u8, name_slice); |
| ... | @@ -13467,14 +13439,12 @@ fn detectLocalShadowing( | ... | @@ -13467,14 +13439,12 @@ fn detectLocalShadowing( |
| 13467 | ), | 13439 | ), |
| 13468 | }); | 13440 | }); |
| 13469 | } | 13441 | } |
| 13470 | s = local_ptr.parent; | 13442 | continue :find_scope local_ptr.parent.unwrap(); |
| 13471 | }, | 13443 | }, |
| 13472 | .namespace => { | 13444 | .namespace => |ns| { |
| 13473 | outer_scope = true; | 13445 | outer_scope = true; |
| 13474 | const ns = s.cast(Scope.Namespace).?; | | |
| 13475 | const decl_node = ns.decls.get(ident_name) orelse { | 13446 | const decl_node = ns.decls.get(ident_name) orelse { |
| 13476 | s = ns.parent; | 13447 | continue :find_scope ns.parent.unwrap(); |
| 13477 | continue; | | |
| 13478 | }; | 13448 | }; |
| 13479 | const name_slice = mem.span(astgen.nullTerminatedString(ident_name)); | 13449 | const name_slice = mem.span(astgen.nullTerminatedString(ident_name)); |
| 13480 | const name = try gpa.dupe(u8, name_slice); | 13450 | const name = try gpa.dupe(u8, name_slice); |
| ... | @@ -13485,13 +13455,13 @@ fn detectLocalShadowing( | ... | @@ -13485,13 +13455,13 @@ fn detectLocalShadowing( |
| 13485 | try astgen.errNoteNode(decl_node, "declared here", .{}), | 13455 | try astgen.errNoteNode(decl_node, "declared here", .{}), |
| 13486 | }); | 13456 | }); |
| 13487 | }, | 13457 | }, |
| 13488 | .gen_zir => { | 13458 | .gen_zir => |gen_zir| { |
| 13489 | s = s.cast(GenZir).?.parent; | | |
| 13490 | outer_scope = true; | 13459 | outer_scope = true; |
| | 13460 | continue :find_scope gen_zir.parent.unwrap(); |
| 13491 | }, | 13461 | }, |
| 13492 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 13462 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 13493 | .top => break, | 13463 | .top => break :find_scope, |
| 13494 | }; | 13464 | } |
| 13495 | } | 13465 | } |
| 13496 | | 13466 | |
| 13497 | const LineColumn = struct { u32, u32 }; | 13467 | const LineColumn = struct { u32, u32 }; |
| ... | @@ -13728,10 +13698,8 @@ fn scanContainer( | ... | @@ -13728,10 +13698,8 @@ fn scanContainer( |
| 13728 | continue; | 13698 | continue; |
| 13729 | } | 13699 | } |
| 13730 | | 13700 | |
| 13731 | var s = namespace.parent; | 13701 | find_scope: switch (namespace.parent.unwrap()) { |
| 13732 | while (true) switch (s.tag) { | 13702 | .local_val => |local_val| { |
| 13733 | .local_val => { | | |
| 13734 | const local_val = s.cast(Scope.LocalVal).?; | | |
| 13735 | if (local_val.name == name_str_index) { | 13703 | if (local_val.name == name_str_index) { |
| 13736 | try astgen.appendErrorTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{ | 13704 | try astgen.appendErrorTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{ |
| 13737 | token_bytes, @tagName(local_val.id_cat), | 13705 | token_bytes, @tagName(local_val.id_cat), |
| ... | @@ -13743,12 +13711,11 @@ fn scanContainer( | ... | @@ -13743,12 +13711,11 @@ fn scanContainer( |
| 13743 | ), | 13711 | ), |
| 13744 | }); | 13712 | }); |
| 13745 | any_invalid_declarations = true; | 13713 | any_invalid_declarations = true; |
| 13746 | break; | 13714 | break :find_scope; |
| 13747 | } | 13715 | } |
| 13748 | s = local_val.parent; | 13716 | continue :find_scope local_val.parent.unwrap(); |
| 13749 | }, | 13717 | }, |
| 13750 | .local_ptr => { | 13718 | .local_ptr => |local_ptr| { |
| 13751 | const local_ptr = s.cast(Scope.LocalPtr).?; | | |
| 13752 | if (local_ptr.name == name_str_index) { | 13719 | if (local_ptr.name == name_str_index) { |
| 13753 | try astgen.appendErrorTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{ | 13720 | try astgen.appendErrorTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{ |
| 13754 | token_bytes, @tagName(local_ptr.id_cat), | 13721 | token_bytes, @tagName(local_ptr.id_cat), |
| ... | @@ -13760,15 +13727,15 @@ fn scanContainer( | ... | @@ -13760,15 +13727,15 @@ fn scanContainer( |
| 13760 | ), | 13727 | ), |
| 13761 | }); | 13728 | }); |
| 13762 | any_invalid_declarations = true; | 13729 | any_invalid_declarations = true; |
| 13763 | break; | 13730 | break :find_scope; |
| 13764 | } | 13731 | } |
| 13765 | s = local_ptr.parent; | 13732 | continue :find_scope local_ptr.parent.unwrap(); |
| 13766 | }, | 13733 | }, |
| 13767 | .namespace => s = s.cast(Scope.Namespace).?.parent, | 13734 | .namespace => |ns| continue :find_scope ns.parent.unwrap(), |
| 13768 | .gen_zir => s = s.cast(GenZir).?.parent, | 13735 | .gen_zir => |gen_zir| continue :find_scope gen_zir.parent.unwrap(), |
| 13769 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 13736 | .defer_normal, .defer_error => |defer_scope| continue :find_scope defer_scope.parent.unwrap(), |
| 13770 | .top => break, | 13737 | .top => break :find_scope, |
| 13771 | }; | 13738 | } |
| 13772 | } | 13739 | } |
| 13773 | | 13740 | |
| 13774 | if (!any_duplicates) { | 13741 | if (!any_duplicates) { |