| ... | @@ -2216,25 +2216,15 @@ fn checkUsed( | ... | @@ -2216,25 +2216,15 @@ fn checkUsed( |
| 2216 | .gen_zir => scope = scope.cast(GenZir).?.parent, | 2216 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 2217 | .local_val => { | 2217 | .local_val => { |
| 2218 | const s = scope.cast(Scope.LocalVal).?; | 2218 | const s = scope.cast(Scope.LocalVal).?; |
| 2219 | switch (s.used) { | 2219 | if (!s.used) { |
| 2220 | .used => {}, | 2220 | return astgen.failTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 2221 | .fn_param => return astgen.failTok(s.token_src, "unused function parameter", .{}), | | |
| 2222 | .constant => return astgen.failTok(s.token_src, "unused local constant", .{}), | | |
| 2223 | .variable => unreachable, | | |
| 2224 | .loop_index => unreachable, | | |
| 2225 | .capture => return astgen.failTok(s.token_src, "unused capture", .{}), | | |
| 2226 | } | 2221 | } |
| 2227 | scope = s.parent; | 2222 | scope = s.parent; |
| 2228 | }, | 2223 | }, |
| 2229 | .local_ptr => { | 2224 | .local_ptr => { |
| 2230 | const s = scope.cast(Scope.LocalPtr).?; | 2225 | const s = scope.cast(Scope.LocalPtr).?; |
| 2231 | switch (s.used) { | 2226 | if (!s.used) { |
| 2232 | .used => {}, | 2227 | return astgen.failTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 2233 | .fn_param => unreachable, | | |
| 2234 | .constant => return astgen.failTok(s.token_src, "unused local constant", .{}), | | |
| 2235 | .variable => return astgen.failTok(s.token_src, "unused local variable", .{}), | | |
| 2236 | .loop_index => return astgen.failTok(s.token_src, "unused loop index capture", .{}), | | |
| 2237 | .capture => unreachable, | | |
| 2238 | } | 2228 | } |
| 2239 | scope = s.parent; | 2229 | scope = s.parent; |
| 2240 | }, | 2230 | }, |
| ... | @@ -2280,63 +2270,7 @@ fn varDecl( | ... | @@ -2280,63 +2270,7 @@ fn varDecl( |
| 2280 | } | 2270 | } |
| 2281 | const ident_name = try astgen.identAsString(name_token); | 2271 | const ident_name = try astgen.identAsString(name_token); |
| 2282 | | 2272 | |
| 2283 | // Local variables shadowing detection, including function parameters. | 2273 | try astgen.detectLocalShadowing(scope, ident_name, name_token); |
| 2284 | { | | |
| 2285 | var s = scope; | | |
| 2286 | while (true) switch (s.tag) { | | |
| 2287 | .local_val => { | | |
| 2288 | const local_val = s.cast(Scope.LocalVal).?; | | |
| 2289 | if (local_val.name == ident_name) { | | |
| 2290 | const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name))); | | |
| 2291 | defer gpa.free(name); | | |
| 2292 | return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{ | | |
| 2293 | name, | | |
| 2294 | }, &[_]u32{ | | |
| 2295 | try astgen.errNoteTok( | | |
| 2296 | local_val.token_src, | | |
| 2297 | "previously declared here", | | |
| 2298 | .{}, | | |
| 2299 | ), | | |
| 2300 | }); | | |
| 2301 | } | | |
| 2302 | s = local_val.parent; | | |
| 2303 | }, | | |
| 2304 | .local_ptr => { | | |
| 2305 | const local_ptr = s.cast(Scope.LocalPtr).?; | | |
| 2306 | if (local_ptr.name == ident_name) { | | |
| 2307 | const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name))); | | |
| 2308 | defer gpa.free(name); | | |
| 2309 | return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{ | | |
| 2310 | name, | | |
| 2311 | }, &[_]u32{ | | |
| 2312 | try astgen.errNoteTok( | | |
| 2313 | local_ptr.token_src, | | |
| 2314 | "previously declared here", | | |
| 2315 | .{}, | | |
| 2316 | ), | | |
| 2317 | }); | | |
| 2318 | } | | |
| 2319 | s = local_ptr.parent; | | |
| 2320 | }, | | |
| 2321 | .namespace => { | | |
| 2322 | const ns = s.cast(Scope.Namespace).?; | | |
| 2323 | const decl_node = ns.decls.get(ident_name) orelse { | | |
| 2324 | s = ns.parent; | | |
| 2325 | continue; | | |
| 2326 | }; | | |
| 2327 | const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name))); | | |
| 2328 | defer gpa.free(name); | | |
| 2329 | return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{ | | |
| 2330 | name, | | |
| 2331 | }, &[_]u32{ | | |
| 2332 | try astgen.errNoteNode(decl_node, "declared here", .{}), | | |
| 2333 | }); | | |
| 2334 | }, | | |
| 2335 | .gen_zir => s = s.cast(GenZir).?.parent, | | |
| 2336 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | | |
| 2337 | .top => break, | | |
| 2338 | }; | | |
| 2339 | } | | |
| 2340 | | 2274 | |
| 2341 | if (var_decl.ast.init_node == 0) { | 2275 | if (var_decl.ast.init_node == 0) { |
| 2342 | return astgen.failNode(node, "variables must be initialized", .{}); | 2276 | return astgen.failNode(node, "variables must be initialized", .{}); |
| ... | @@ -2369,7 +2303,7 @@ fn varDecl( | ... | @@ -2369,7 +2303,7 @@ fn varDecl( |
| 2369 | .name = ident_name, | 2303 | .name = ident_name, |
| 2370 | .inst = init_inst, | 2304 | .inst = init_inst, |
| 2371 | .token_src = name_token, | 2305 | .token_src = name_token, |
| 2372 | .used = .constant, | 2306 | .id_cat = .@"local constant", |
| 2373 | }; | 2307 | }; |
| 2374 | return &sub_scope.base; | 2308 | return &sub_scope.base; |
| 2375 | } | 2309 | } |
| ... | @@ -2438,7 +2372,7 @@ fn varDecl( | ... | @@ -2438,7 +2372,7 @@ fn varDecl( |
| 2438 | .name = ident_name, | 2372 | .name = ident_name, |
| 2439 | .inst = init_inst, | 2373 | .inst = init_inst, |
| 2440 | .token_src = name_token, | 2374 | .token_src = name_token, |
| 2441 | .used = .constant, | 2375 | .id_cat = .@"local constant", |
| 2442 | }; | 2376 | }; |
| 2443 | return &sub_scope.base; | 2377 | return &sub_scope.base; |
| 2444 | } | 2378 | } |
| ... | @@ -2468,7 +2402,7 @@ fn varDecl( | ... | @@ -2468,7 +2402,7 @@ fn varDecl( |
| 2468 | .ptr = init_scope.rl_ptr, | 2402 | .ptr = init_scope.rl_ptr, |
| 2469 | .token_src = name_token, | 2403 | .token_src = name_token, |
| 2470 | .maybe_comptime = true, | 2404 | .maybe_comptime = true, |
| 2471 | .used = .constant, | 2405 | .id_cat = .@"local constant", |
| 2472 | }; | 2406 | }; |
| 2473 | return &sub_scope.base; | 2407 | return &sub_scope.base; |
| 2474 | }, | 2408 | }, |
| ... | @@ -2525,7 +2459,7 @@ fn varDecl( | ... | @@ -2525,7 +2459,7 @@ fn varDecl( |
| 2525 | .ptr = var_data.alloc, | 2459 | .ptr = var_data.alloc, |
| 2526 | .token_src = name_token, | 2460 | .token_src = name_token, |
| 2527 | .maybe_comptime = is_comptime, | 2461 | .maybe_comptime = is_comptime, |
| 2528 | .used = .variable, | 2462 | .id_cat = .@"local variable", |
| 2529 | }; | 2463 | }; |
| 2530 | return &sub_scope.base; | 2464 | return &sub_scope.base; |
| 2531 | }, | 2465 | }, |
| ... | @@ -3028,7 +2962,7 @@ fn fnDecl( | ... | @@ -3028,7 +2962,7 @@ fn fnDecl( |
| 3028 | const param_name = try astgen.identAsString(name_token); | 2962 | const param_name = try astgen.identAsString(name_token); |
| 3029 | // Create an arg instruction. This is needed to emit a semantic analysis | 2963 | // Create an arg instruction. This is needed to emit a semantic analysis |
| 3030 | // error for shadowing decls. | 2964 | // error for shadowing decls. |
| 3031 | // TODO emit a compile error here for shadowing locals. | 2965 | try astgen.detectLocalShadowing(params_scope, param_name, name_token); |
| 3032 | const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token); | 2966 | const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token); |
| 3033 | const sub_scope = try astgen.arena.create(Scope.LocalVal); | 2967 | const sub_scope = try astgen.arena.create(Scope.LocalVal); |
| 3034 | sub_scope.* = .{ | 2968 | sub_scope.* = .{ |
| ... | @@ -3037,7 +2971,7 @@ fn fnDecl( | ... | @@ -3037,7 +2971,7 @@ fn fnDecl( |
| 3037 | .name = param_name, | 2971 | .name = param_name, |
| 3038 | .inst = arg_inst, | 2972 | .inst = arg_inst, |
| 3039 | .token_src = name_token, | 2973 | .token_src = name_token, |
| 3040 | .used = .fn_param, | 2974 | .id_cat = .@"function parameter", |
| 3041 | }; | 2975 | }; |
| 3042 | params_scope = &sub_scope.base; | 2976 | params_scope = &sub_scope.base; |
| 3043 | | 2977 | |
| ... | @@ -4701,7 +4635,7 @@ fn orelseCatchExpr( | ... | @@ -4701,7 +4635,7 @@ fn orelseCatchExpr( |
| 4701 | .name = err_name, | 4635 | .name = err_name, |
| 4702 | .inst = try then_scope.addUnNode(unwrap_code_op, operand, node), | 4636 | .inst = try then_scope.addUnNode(unwrap_code_op, operand, node), |
| 4703 | .token_src = payload, | 4637 | .token_src = payload, |
| 4704 | .used = .capture, | 4638 | .id_cat = .@"capture", |
| 4705 | }; | 4639 | }; |
| 4706 | break :blk &err_val_scope.base; | 4640 | break :blk &err_val_scope.base; |
| 4707 | }; | 4641 | }; |
| ... | @@ -4993,7 +4927,7 @@ fn ifExpr( | ... | @@ -4993,7 +4927,7 @@ fn ifExpr( |
| 4993 | .name = ident_name, | 4927 | .name = ident_name, |
| 4994 | .inst = payload_inst, | 4928 | .inst = payload_inst, |
| 4995 | .token_src = payload_token, | 4929 | .token_src = payload_token, |
| 4996 | .used = .capture, | 4930 | .id_cat = .@"capture", |
| 4997 | }; | 4931 | }; |
| 4998 | break :s &payload_val_scope.base; | 4932 | break :s &payload_val_scope.base; |
| 4999 | } else { | 4933 | } else { |
| ... | @@ -5015,7 +4949,7 @@ fn ifExpr( | ... | @@ -5015,7 +4949,7 @@ fn ifExpr( |
| 5015 | .name = ident_name, | 4949 | .name = ident_name, |
| 5016 | .inst = payload_inst, | 4950 | .inst = payload_inst, |
| 5017 | .token_src = ident_token, | 4951 | .token_src = ident_token, |
| 5018 | .used = .capture, | 4952 | .id_cat = .@"capture", |
| 5019 | }; | 4953 | }; |
| 5020 | break :s &payload_val_scope.base; | 4954 | break :s &payload_val_scope.base; |
| 5021 | } else { | 4955 | } else { |
| ... | @@ -5056,7 +4990,7 @@ fn ifExpr( | ... | @@ -5056,7 +4990,7 @@ fn ifExpr( |
| 5056 | .name = ident_name, | 4990 | .name = ident_name, |
| 5057 | .inst = payload_inst, | 4991 | .inst = payload_inst, |
| 5058 | .token_src = error_token, | 4992 | .token_src = error_token, |
| 5059 | .used = .capture, | 4993 | .id_cat = .@"capture", |
| 5060 | }; | 4994 | }; |
| 5061 | break :s &payload_val_scope.base; | 4995 | break :s &payload_val_scope.base; |
| 5062 | } else { | 4996 | } else { |
| ... | @@ -5250,7 +5184,7 @@ fn whileExpr( | ... | @@ -5250,7 +5184,7 @@ fn whileExpr( |
| 5250 | .name = ident_name, | 5184 | .name = ident_name, |
| 5251 | .inst = payload_inst, | 5185 | .inst = payload_inst, |
| 5252 | .token_src = payload_token, | 5186 | .token_src = payload_token, |
| 5253 | .used = .capture, | 5187 | .id_cat = .@"capture", |
| 5254 | }; | 5188 | }; |
| 5255 | break :s &payload_val_scope.base; | 5189 | break :s &payload_val_scope.base; |
| 5256 | } else { | 5190 | } else { |
| ... | @@ -5272,7 +5206,7 @@ fn whileExpr( | ... | @@ -5272,7 +5206,7 @@ fn whileExpr( |
| 5272 | .name = ident_name, | 5206 | .name = ident_name, |
| 5273 | .inst = payload_inst, | 5207 | .inst = payload_inst, |
| 5274 | .token_src = ident_token, | 5208 | .token_src = ident_token, |
| 5275 | .used = .capture, | 5209 | .id_cat = .@"capture", |
| 5276 | }; | 5210 | }; |
| 5277 | break :s &payload_val_scope.base; | 5211 | break :s &payload_val_scope.base; |
| 5278 | } else { | 5212 | } else { |
| ... | @@ -5329,7 +5263,7 @@ fn whileExpr( | ... | @@ -5329,7 +5263,7 @@ fn whileExpr( |
| 5329 | .name = ident_name, | 5263 | .name = ident_name, |
| 5330 | .inst = payload_inst, | 5264 | .inst = payload_inst, |
| 5331 | .token_src = error_token, | 5265 | .token_src = error_token, |
| 5332 | .used = .capture, | 5266 | .id_cat = .@"capture", |
| 5333 | }; | 5267 | }; |
| 5334 | break :s &payload_val_scope.base; | 5268 | break :s &payload_val_scope.base; |
| 5335 | } else { | 5269 | } else { |
| ... | @@ -5468,7 +5402,7 @@ fn forExpr( | ... | @@ -5468,7 +5402,7 @@ fn forExpr( |
| 5468 | .name = name_str_index, | 5402 | .name = name_str_index, |
| 5469 | .inst = payload_inst, | 5403 | .inst = payload_inst, |
| 5470 | .token_src = ident, | 5404 | .token_src = ident, |
| 5471 | .used = .capture, | 5405 | .id_cat = .@"capture", |
| 5472 | }; | 5406 | }; |
| 5473 | payload_sub_scope = &payload_val_scope.base; | 5407 | payload_sub_scope = &payload_val_scope.base; |
| 5474 | } else if (is_ptr) { | 5408 | } else if (is_ptr) { |
| ... | @@ -5492,7 +5426,7 @@ fn forExpr( | ... | @@ -5492,7 +5426,7 @@ fn forExpr( |
| 5492 | .ptr = index_ptr, | 5426 | .ptr = index_ptr, |
| 5493 | .token_src = index_token, | 5427 | .token_src = index_token, |
| 5494 | .maybe_comptime = is_inline, | 5428 | .maybe_comptime = is_inline, |
| 5495 | .used = .loop_index, | 5429 | .id_cat = .@"loop index capture", |
| 5496 | }; | 5430 | }; |
| 5497 | break :blk &index_scope.base; | 5431 | break :blk &index_scope.base; |
| 5498 | }; | 5432 | }; |
| ... | @@ -5737,7 +5671,7 @@ fn switchExpr( | ... | @@ -5737,7 +5671,7 @@ fn switchExpr( |
| 5737 | .name = capture_name, | 5671 | .name = capture_name, |
| 5738 | .inst = capture, | 5672 | .inst = capture, |
| 5739 | .token_src = payload_token, | 5673 | .token_src = payload_token, |
| 5740 | .used = .capture, | 5674 | .id_cat = .@"capture", |
| 5741 | }; | 5675 | }; |
| 5742 | break :blk &capture_val_scope.base; | 5676 | break :blk &capture_val_scope.base; |
| 5743 | }; | 5677 | }; |
| ... | @@ -5831,7 +5765,7 @@ fn switchExpr( | ... | @@ -5831,7 +5765,7 @@ fn switchExpr( |
| 5831 | .name = capture_name, | 5765 | .name = capture_name, |
| 5832 | .inst = capture, | 5766 | .inst = capture, |
| 5833 | .token_src = payload_token, | 5767 | .token_src = payload_token, |
| 5834 | .used = .capture, | 5768 | .id_cat = .@"capture", |
| 5835 | }; | 5769 | }; |
| 5836 | break :blk &capture_val_scope.base; | 5770 | break :blk &capture_val_scope.base; |
| 5837 | }; | 5771 | }; |
| ... | @@ -6261,7 +6195,7 @@ fn identifier( | ... | @@ -6261,7 +6195,7 @@ fn identifier( |
| 6261 | const local_val = s.cast(Scope.LocalVal).?; | 6195 | const local_val = s.cast(Scope.LocalVal).?; |
| 6262 | | 6196 | |
| 6263 | if (local_val.name == name_str_index) { | 6197 | if (local_val.name == name_str_index) { |
| 6264 | local_val.used = .used; | 6198 | local_val.used = true; |
| 6265 | // Captures of non-locals need to be emitted as decl_val or decl_ref. | 6199 | // Captures of non-locals need to be emitted as decl_val or decl_ref. |
| 6266 | // This *might* be capturable depending on if it is comptime known. | 6200 | // This *might* be capturable depending on if it is comptime known. |
| 6267 | if (!hit_namespace) { | 6201 | if (!hit_namespace) { |
| ... | @@ -6273,7 +6207,7 @@ fn identifier( | ... | @@ -6273,7 +6207,7 @@ fn identifier( |
| 6273 | .local_ptr => { | 6207 | .local_ptr => { |
| 6274 | const local_ptr = s.cast(Scope.LocalPtr).?; | 6208 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6275 | if (local_ptr.name == name_str_index) { | 6209 | if (local_ptr.name == name_str_index) { |
| 6276 | local_ptr.used = .used; | 6210 | local_ptr.used = true; |
| 6277 | if (hit_namespace) { | 6211 | if (hit_namespace) { |
| 6278 | if (local_ptr.maybe_comptime) | 6212 | if (local_ptr.maybe_comptime) |
| 6279 | break | 6213 | break |
| ... | @@ -6609,7 +6543,7 @@ fn asmExpr( | ... | @@ -6609,7 +6543,7 @@ fn asmExpr( |
| 6609 | .local_val => { | 6543 | .local_val => { |
| 6610 | const local_val = s.cast(Scope.LocalVal).?; | 6544 | const local_val = s.cast(Scope.LocalVal).?; |
| 6611 | if (local_val.name == str_index) { | 6545 | if (local_val.name == str_index) { |
| 6612 | local_val.used = .used; | 6546 | local_val.used = true; |
| 6613 | break; | 6547 | break; |
| 6614 | } | 6548 | } |
| 6615 | s = local_val.parent; | 6549 | s = local_val.parent; |
| ... | @@ -6617,7 +6551,7 @@ fn asmExpr( | ... | @@ -6617,7 +6551,7 @@ fn asmExpr( |
| 6617 | .local_ptr => { | 6551 | .local_ptr => { |
| 6618 | const local_ptr = s.cast(Scope.LocalPtr).?; | 6552 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6619 | if (local_ptr.name == str_index) { | 6553 | if (local_ptr.name == str_index) { |
| 6620 | local_ptr.used = .used; | 6554 | local_ptr.used = true; |
| 6621 | break; | 6555 | break; |
| 6622 | } | 6556 | } |
| 6623 | s = local_ptr.parent; | 6557 | s = local_ptr.parent; |
| ... | @@ -6968,7 +6902,7 @@ fn builtinCall( | ... | @@ -6968,7 +6902,7 @@ fn builtinCall( |
| 6968 | .local_val => { | 6902 | .local_val => { |
| 6969 | const local_val = s.cast(Scope.LocalVal).?; | 6903 | const local_val = s.cast(Scope.LocalVal).?; |
| 6970 | if (local_val.name == decl_name) { | 6904 | if (local_val.name == decl_name) { |
| 6971 | local_val.used = .used; | 6905 | local_val.used = true; |
| 6972 | break; | 6906 | break; |
| 6973 | } | 6907 | } |
| 6974 | s = local_val.parent; | 6908 | s = local_val.parent; |
| ... | @@ -6978,7 +6912,7 @@ fn builtinCall( | ... | @@ -6978,7 +6912,7 @@ fn builtinCall( |
| 6978 | if (local_ptr.name == decl_name) { | 6912 | if (local_ptr.name == decl_name) { |
| 6979 | if (!local_ptr.maybe_comptime) | 6913 | if (!local_ptr.maybe_comptime) |
| 6980 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); | 6914 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); |
| 6981 | local_ptr.used = .used; | 6915 | local_ptr.used = true; |
| 6982 | break; | 6916 | break; |
| 6983 | } | 6917 | } |
| 6984 | s = local_ptr.parent; | 6918 | s = local_ptr.parent; |
| ... | @@ -8545,15 +8479,15 @@ const Scope = struct { | ... | @@ -8545,15 +8479,15 @@ const Scope = struct { |
| 8545 | top, | 8479 | top, |
| 8546 | }; | 8480 | }; |
| 8547 | | 8481 | |
| 8548 | // either .used or the type of the var/constant | 8482 | /// The category of identifier. These tag names are user-visible in compile errors. |
| 8549 | const Used = enum { | 8483 | const IdCat = enum { |
| 8550 | fn_param, | 8484 | @"function parameter", |
| 8551 | constant, | 8485 | @"local constant", |
| 8552 | variable, | 8486 | @"local variable", |
| 8553 | loop_index, | 8487 | @"loop index capture", |
| 8554 | capture, | 8488 | @"capture", |
| 8555 | used, | | |
| 8556 | }; | 8489 | }; |
| | 8490 | |
| 8557 | /// This is always a `const` local and importantly the `inst` is a value type, not a pointer. | 8491 | /// This is always a `const` local and importantly the `inst` is a value type, not a pointer. |
| 8558 | /// This structure lives as long as the AST generation of the Block | 8492 | /// This structure lives as long as the AST generation of the Block |
| 8559 | /// node that contains the variable. | 8493 | /// node that contains the variable. |
| ... | @@ -8568,8 +8502,9 @@ const Scope = struct { | ... | @@ -8568,8 +8502,9 @@ const Scope = struct { |
| 8568 | token_src: ast.TokenIndex, | 8502 | token_src: ast.TokenIndex, |
| 8569 | /// String table index. | 8503 | /// String table index. |
| 8570 | name: u32, | 8504 | name: u32, |
| 8571 | /// has this variable been referenced? | 8505 | id_cat: IdCat, |
| 8572 | used: Used, | 8506 | /// Track whether the name has been referenced. |
| | 8507 | used: bool = false, |
| 8573 | }; | 8508 | }; |
| 8574 | | 8509 | |
| 8575 | /// This could be a `const` or `var` local. It has a pointer instead of a value. | 8510 | /// This could be a `const` or `var` local. It has a pointer instead of a value. |
| ... | @@ -8586,10 +8521,12 @@ const Scope = struct { | ... | @@ -8586,10 +8521,12 @@ const Scope = struct { |
| 8586 | token_src: ast.TokenIndex, | 8521 | token_src: ast.TokenIndex, |
| 8587 | /// String table index. | 8522 | /// String table index. |
| 8588 | name: u32, | 8523 | name: u32, |
| 8589 | /// true means we find out during Sema whether the value is comptime. false means it is already known at AstGen the value is runtime-known. | 8524 | id_cat: IdCat, |
| | 8525 | /// true means we find out during Sema whether the value is comptime. |
| | 8526 | /// false means it is already known at AstGen the value is runtime-known. |
| 8590 | maybe_comptime: bool, | 8527 | maybe_comptime: bool, |
| 8591 | /// has this variable been referenced? | 8528 | /// Track whether the name has been referenced. |
| 8592 | used: Used, | 8529 | used: bool = false, |
| 8593 | }; | 8530 | }; |
| 8594 | | 8531 | |
| 8595 | const Defer = struct { | 8532 | const Defer = struct { |
| ... | @@ -9680,6 +9617,71 @@ fn declareNewName( | ... | @@ -9680,6 +9617,71 @@ fn declareNewName( |
| 9680 | } | 9617 | } |
| 9681 | } | 9618 | } |
| 9682 | | 9619 | |
| | 9620 | /// Local variables shadowing detection, including function parameters. |
| | 9621 | fn detectLocalShadowing( |
| | 9622 | astgen: *AstGen, |
| | 9623 | scope: *Scope, |
| | 9624 | ident_name: u32, |
| | 9625 | name_token: ast.TokenIndex, |
| | 9626 | ) !void { |
| | 9627 | const gpa = astgen.gpa; |
| | 9628 | |
| | 9629 | var s = scope; |
| | 9630 | while (true) switch (s.tag) { |
| | 9631 | .local_val => { |
| | 9632 | const local_val = s.cast(Scope.LocalVal).?; |
| | 9633 | if (local_val.name == ident_name) { |
| | 9634 | const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name))); |
| | 9635 | defer gpa.free(name); |
| | 9636 | return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{ |
| | 9637 | @tagName(local_val.id_cat), name, |
| | 9638 | }, &[_]u32{ |
| | 9639 | try astgen.errNoteTok( |
| | 9640 | local_val.token_src, |
| | 9641 | "previously declared here", |
| | 9642 | .{}, |
| | 9643 | ), |
| | 9644 | }); |
| | 9645 | } |
| | 9646 | s = local_val.parent; |
| | 9647 | }, |
| | 9648 | .local_ptr => { |
| | 9649 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| | 9650 | if (local_ptr.name == ident_name) { |
| | 9651 | const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name))); |
| | 9652 | defer gpa.free(name); |
| | 9653 | return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{ |
| | 9654 | @tagName(local_ptr.id_cat), name, |
| | 9655 | }, &[_]u32{ |
| | 9656 | try astgen.errNoteTok( |
| | 9657 | local_ptr.token_src, |
| | 9658 | "previously declared here", |
| | 9659 | .{}, |
| | 9660 | ), |
| | 9661 | }); |
| | 9662 | } |
| | 9663 | s = local_ptr.parent; |
| | 9664 | }, |
| | 9665 | .namespace => { |
| | 9666 | const ns = s.cast(Scope.Namespace).?; |
| | 9667 | const decl_node = ns.decls.get(ident_name) orelse { |
| | 9668 | s = ns.parent; |
| | 9669 | continue; |
| | 9670 | }; |
| | 9671 | const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name))); |
| | 9672 | defer gpa.free(name); |
| | 9673 | return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{ |
| | 9674 | name, |
| | 9675 | }, &[_]u32{ |
| | 9676 | try astgen.errNoteNode(decl_node, "declared here", .{}), |
| | 9677 | }); |
| | 9678 | }, |
| | 9679 | .gen_zir => s = s.cast(GenZir).?.parent, |
| | 9680 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| | 9681 | .top => break, |
| | 9682 | }; |
| | 9683 | } |
| | 9684 | |
| 9683 | fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { | 9685 | fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 9684 | var i = astgen.source_offset; | 9686 | var i = astgen.source_offset; |
| 9685 | var line = astgen.source_line; | 9687 | var line = astgen.source_line; |