| ... | ... | @@ -2139,10 +2139,7 @@ fn genDefers( |
| 2139 | 2139 | .defer_error => { |
| 2140 | 2140 | const defer_scope = scope.cast(Scope.Defer).?; |
| 2141 | 2141 | scope = defer_scope.parent; |
| 2142 | | // TODO add this back when we have more errdefer support |
| 2143 | | // right now it is making stuff not get evaluated which causes |
| 2144 | | // unused vars. |
| 2145 | | // if (err_code == .none) continue; |
| 2142 | if (err_code == .none) continue; |
| 2146 | 2143 | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 2147 | 2144 | const prev_in_defer = gz.in_defer; |
| 2148 | 2145 | gz.in_defer = true; |
| ... | ... | @@ -2168,12 +2165,26 @@ fn checkUsed( |
| 2168 | 2165 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 2169 | 2166 | .local_val => { |
| 2170 | 2167 | const s = scope.cast(Scope.LocalVal).?; |
| 2171 | | if (!s.used) return astgen.failTok(s.token_src, "unused local constant", .{}); |
| 2168 | switch (s.used) { |
| 2169 | .used => {}, |
| 2170 | .fn_param => return astgen.failTok(s.token_src, "unused function parameter", .{}), |
| 2171 | .constant => return astgen.failTok(s.token_src, "unused local constant", .{}), |
| 2172 | .variable => unreachable, |
| 2173 | .loop_index => unreachable, |
| 2174 | .capture => return astgen.failTok(s.token_src, "unused capture", .{}), |
| 2175 | } |
| 2172 | 2176 | scope = s.parent; |
| 2173 | 2177 | }, |
| 2174 | 2178 | .local_ptr => { |
| 2175 | 2179 | const s = scope.cast(Scope.LocalPtr).?; |
| 2176 | | if (!s.used) return astgen.failTok(s.token_src, "unused local variable", .{}); |
| 2180 | switch (s.used) { |
| 2181 | .used => {}, |
| 2182 | .fn_param => unreachable, |
| 2183 | .constant => return astgen.failTok(s.token_src, "unused local constant", .{}), |
| 2184 | .variable => return astgen.failTok(s.token_src, "unused local variable", .{}), |
| 2185 | .loop_index => return astgen.failTok(s.token_src, "unused loop index capture", .{}), |
| 2186 | .capture => unreachable, |
| 2187 | } |
| 2177 | 2188 | scope = s.parent; |
| 2178 | 2189 | }, |
| 2179 | 2190 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| ... | ... | @@ -2303,6 +2314,7 @@ fn varDecl( |
| 2303 | 2314 | .name = ident_name, |
| 2304 | 2315 | .inst = init_inst, |
| 2305 | 2316 | .token_src = name_token, |
| 2317 | .used = .constant, |
| 2306 | 2318 | }; |
| 2307 | 2319 | return &sub_scope.base; |
| 2308 | 2320 | } |
| ... | ... | @@ -2370,6 +2382,7 @@ fn varDecl( |
| 2370 | 2382 | .name = ident_name, |
| 2371 | 2383 | .inst = init_inst, |
| 2372 | 2384 | .token_src = name_token, |
| 2385 | .used = .constant, |
| 2373 | 2386 | }; |
| 2374 | 2387 | return &sub_scope.base; |
| 2375 | 2388 | } |
| ... | ... | @@ -2399,6 +2412,7 @@ fn varDecl( |
| 2399 | 2412 | .ptr = init_scope.rl_ptr, |
| 2400 | 2413 | .token_src = name_token, |
| 2401 | 2414 | .maybe_comptime = true, |
| 2415 | .used = .constant, |
| 2402 | 2416 | }; |
| 2403 | 2417 | return &sub_scope.base; |
| 2404 | 2418 | }, |
| ... | ... | @@ -2455,6 +2469,7 @@ fn varDecl( |
| 2455 | 2469 | .ptr = var_data.alloc, |
| 2456 | 2470 | .token_src = name_token, |
| 2457 | 2471 | .maybe_comptime = is_comptime, |
| 2472 | .used = .variable, |
| 2458 | 2473 | }; |
| 2459 | 2474 | return &sub_scope.base; |
| 2460 | 2475 | }, |
| ... | ... | @@ -2943,6 +2958,10 @@ fn fnDecl( |
| 2943 | 2958 | const name_token = param.name_token orelse { |
| 2944 | 2959 | return astgen.failNode(param.type_expr, "missing parameter name", .{}); |
| 2945 | 2960 | }; |
| 2961 | if (param.type_expr != 0) |
| 2962 | _ = try typeExpr(&fn_gz, params_scope, param.type_expr); |
| 2963 | if (mem.eql(u8, "_", tree.tokenSlice(name_token))) |
| 2964 | continue; |
| 2946 | 2965 | const param_name = try astgen.identAsString(name_token); |
| 2947 | 2966 | // Create an arg instruction. This is needed to emit a semantic analysis |
| 2948 | 2967 | // error for shadowing decls. |
| ... | ... | @@ -2955,17 +2974,19 @@ fn fnDecl( |
| 2955 | 2974 | .name = param_name, |
| 2956 | 2975 | .inst = arg_inst, |
| 2957 | 2976 | .token_src = name_token, |
| 2958 | | // TODO make function paramater have different message instead of unused constant |
| 2977 | .used = .fn_param, |
| 2959 | 2978 | }; |
| 2960 | 2979 | params_scope = &sub_scope.base; |
| 2961 | 2980 | |
| 2962 | 2981 | // Additionally put the param name into `string_bytes` and reference it with |
| 2963 | 2982 | // `extra` so that we have access to the data in codegen, for debug info. |
| 2964 | 2983 | const str_index = try astgen.identAsString(name_token); |
| 2965 | | astgen.extra.appendAssumeCapacity(str_index); |
| 2984 | try astgen.extra.append(astgen.gpa, str_index); |
| 2966 | 2985 | } |
| 2986 | _ = try typeExpr(&fn_gz, params_scope, fn_proto.ast.return_type); |
| 2967 | 2987 | |
| 2968 | 2988 | _ = try expr(&fn_gz, params_scope, .none, body_node); |
| 2989 | try checkUsed(gz, &fn_gz.base, params_scope); |
| 2969 | 2990 | } |
| 2970 | 2991 | |
| 2971 | 2992 | const need_implicit_ret = blk: { |
| ... | ... | @@ -3396,7 +3417,6 @@ fn structDeclInner( |
| 3396 | 3417 | }; |
| 3397 | 3418 | defer block_scope.instructions.deinit(gpa); |
| 3398 | 3419 | |
| 3399 | | // TODO should we change this to scope in other places too? |
| 3400 | 3420 | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 3401 | 3421 | defer namespace.decls.deinit(gpa); |
| 3402 | 3422 | |
| ... | ... | @@ -3659,7 +3679,7 @@ fn unionDeclInner( |
| 3659 | 3679 | }; |
| 3660 | 3680 | defer block_scope.instructions.deinit(gpa); |
| 3661 | 3681 | |
| 3662 | | var namespace: Scope.Namespace = .{ .parent = &gz.base }; |
| 3682 | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 3663 | 3683 | defer namespace.decls.deinit(gpa); |
| 3664 | 3684 | |
| 3665 | 3685 | var wip_decls: WipDecls = .{}; |
| ... | ... | @@ -4060,7 +4080,7 @@ fn containerDecl( |
| 4060 | 4080 | }; |
| 4061 | 4081 | defer block_scope.instructions.deinit(gpa); |
| 4062 | 4082 | |
| 4063 | | var namespace: Scope.Namespace = .{ .parent = &gz.base }; |
| 4083 | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 4064 | 4084 | defer namespace.decls.deinit(gpa); |
| 4065 | 4085 | |
| 4066 | 4086 | var wip_decls: WipDecls = .{}; |
| ... | ... | @@ -4287,7 +4307,7 @@ fn containerDecl( |
| 4287 | 4307 | return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node); |
| 4288 | 4308 | }, |
| 4289 | 4309 | .keyword_opaque => { |
| 4290 | | var namespace: Scope.Namespace = .{ .parent = &gz.base }; |
| 4310 | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 4291 | 4311 | defer namespace.decls.deinit(gpa); |
| 4292 | 4312 | |
| 4293 | 4313 | var wip_decls: WipDecls = .{}; |
| ... | ... | @@ -4622,12 +4642,15 @@ fn orelseCatchExpr( |
| 4622 | 4642 | .name = err_name, |
| 4623 | 4643 | .inst = try then_scope.addUnNode(unwrap_code_op, operand, node), |
| 4624 | 4644 | .token_src = payload, |
| 4645 | .used = .capture, |
| 4625 | 4646 | }; |
| 4626 | 4647 | break :blk &err_val_scope.base; |
| 4627 | 4648 | }; |
| 4628 | 4649 | |
| 4629 | 4650 | block_scope.break_count += 1; |
| 4630 | 4651 | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, rhs); |
| 4652 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 4653 | |
| 4631 | 4654 | // We hold off on the break instructions as well as copying the then/else |
| 4632 | 4655 | // instructions into place until we know whether to keep store_to_block_ptr |
| 4633 | 4656 | // instructions or not. |
| ... | ... | @@ -4900,27 +4923,38 @@ fn ifExpr( |
| 4900 | 4923 | var payload_val_scope: Scope.LocalVal = undefined; |
| 4901 | 4924 | |
| 4902 | 4925 | const then_sub_scope = s: { |
| 4903 | | if (if_full.error_token) |error_token| { |
| 4904 | | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 4905 | | .err_union_payload_unsafe_ptr |
| 4906 | | else |
| 4907 | | .err_union_payload_unsafe; |
| 4908 | | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 4909 | | const ident_name = try astgen.identAsString(error_token); |
| 4910 | | payload_val_scope = .{ |
| 4911 | | .parent = &then_scope.base, |
| 4912 | | .gen_zir = &then_scope, |
| 4913 | | .name = ident_name, |
| 4914 | | .inst = payload_inst, |
| 4915 | | .token_src = error_token, |
| 4916 | | }; |
| 4917 | | break :s &payload_val_scope.base; |
| 4926 | if (if_full.error_token != null) { |
| 4927 | if (if_full.payload_token) |payload_token| { |
| 4928 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 4929 | .err_union_payload_unsafe_ptr |
| 4930 | else |
| 4931 | .err_union_payload_unsafe; |
| 4932 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 4933 | const token_name_index = payload_token + @boolToInt(payload_is_ref); |
| 4934 | const ident_name = try astgen.identAsString(token_name_index); |
| 4935 | const token_name_str = tree.tokenSlice(token_name_index); |
| 4936 | if (mem.eql(u8, "_", token_name_str)) |
| 4937 | break :s &then_scope.base; |
| 4938 | payload_val_scope = .{ |
| 4939 | .parent = &then_scope.base, |
| 4940 | .gen_zir = &then_scope, |
| 4941 | .name = ident_name, |
| 4942 | .inst = payload_inst, |
| 4943 | .token_src = payload_token, |
| 4944 | .used = .capture, |
| 4945 | }; |
| 4946 | break :s &payload_val_scope.base; |
| 4947 | } else { |
| 4948 | break :s &then_scope.base; |
| 4949 | } |
| 4918 | 4950 | } else if (if_full.payload_token) |payload_token| { |
| 4919 | 4951 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| 4920 | 4952 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 4921 | 4953 | .optional_payload_unsafe_ptr |
| 4922 | 4954 | else |
| 4923 | 4955 | .optional_payload_unsafe; |
| 4956 | if (mem.eql(u8, "_", tree.tokenSlice(ident_token))) |
| 4957 | break :s &then_scope.base; |
| 4924 | 4958 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 4925 | 4959 | const ident_name = try astgen.identAsString(ident_token); |
| 4926 | 4960 | payload_val_scope = .{ |
| ... | ... | @@ -4929,6 +4963,7 @@ fn ifExpr( |
| 4929 | 4963 | .name = ident_name, |
| 4930 | 4964 | .inst = payload_inst, |
| 4931 | 4965 | .token_src = ident_token, |
| 4966 | .used = .capture, |
| 4932 | 4967 | }; |
| 4933 | 4968 | break :s &payload_val_scope.base; |
| 4934 | 4969 | } else { |
| ... | ... | @@ -4938,6 +4973,7 @@ fn ifExpr( |
| 4938 | 4973 | |
| 4939 | 4974 | block_scope.break_count += 1; |
| 4940 | 4975 | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr); |
| 4976 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 4941 | 4977 | // We hold off on the break instructions as well as copying the then/else |
| 4942 | 4978 | // instructions into place until we know whether to keep store_to_block_ptr |
| 4943 | 4979 | // instructions or not. |
| ... | ... | @@ -4959,21 +4995,27 @@ fn ifExpr( |
| 4959 | 4995 | .err_union_code; |
| 4960 | 4996 | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| 4961 | 4997 | const ident_name = try astgen.identAsString(error_token); |
| 4998 | const error_token_str = tree.tokenSlice(error_token); |
| 4999 | if (mem.eql(u8, "_", error_token_str)) |
| 5000 | break :s &else_scope.base; |
| 4962 | 5001 | payload_val_scope = .{ |
| 4963 | 5002 | .parent = &else_scope.base, |
| 4964 | 5003 | .gen_zir = &else_scope, |
| 4965 | 5004 | .name = ident_name, |
| 4966 | 5005 | .inst = payload_inst, |
| 4967 | 5006 | .token_src = error_token, |
| 5007 | .used = .capture, |
| 4968 | 5008 | }; |
| 4969 | 5009 | break :s &payload_val_scope.base; |
| 4970 | 5010 | } else { |
| 4971 | 5011 | break :s &else_scope.base; |
| 4972 | 5012 | } |
| 4973 | 5013 | }; |
| 5014 | const e = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node); |
| 5015 | try checkUsed(parent_gz, &else_scope.base, sub_scope); |
| 4974 | 5016 | break :blk .{ |
| 4975 | 5017 | .src = else_node, |
| 4976 | | .result = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node), |
| 5018 | .result = e, |
| 4977 | 5019 | }; |
| 4978 | 5020 | } else .{ |
| 4979 | 5021 | .src = if_full.ast.then_expr, |
| ... | ... | @@ -5161,21 +5203,29 @@ fn whileExpr( |
| 5161 | 5203 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5162 | 5204 | |
| 5163 | 5205 | const then_sub_scope = s: { |
| 5164 | | if (while_full.error_token) |error_token| { |
| 5165 | | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 5166 | | .err_union_payload_unsafe_ptr |
| 5167 | | else |
| 5168 | | .err_union_payload_unsafe; |
| 5169 | | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 5170 | | const ident_name = try astgen.identAsString(error_token); |
| 5171 | | payload_val_scope = .{ |
| 5172 | | .parent = &then_scope.base, |
| 5173 | | .gen_zir = &then_scope, |
| 5174 | | .name = ident_name, |
| 5175 | | .inst = payload_inst, |
| 5176 | | .token_src = error_token, |
| 5177 | | }; |
| 5178 | | break :s &payload_val_scope.base; |
| 5206 | if (while_full.error_token != null) { |
| 5207 | if (while_full.payload_token) |payload_token| { |
| 5208 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 5209 | .err_union_payload_unsafe_ptr |
| 5210 | else |
| 5211 | .err_union_payload_unsafe; |
| 5212 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 5213 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| 5214 | if (mem.eql(u8, "_", tree.tokenSlice(ident_token))) |
| 5215 | break :s &then_scope.base; |
| 5216 | const ident_name = try astgen.identAsString(payload_token + @boolToInt(payload_is_ref)); |
| 5217 | payload_val_scope = .{ |
| 5218 | .parent = &then_scope.base, |
| 5219 | .gen_zir = &then_scope, |
| 5220 | .name = ident_name, |
| 5221 | .inst = payload_inst, |
| 5222 | .token_src = payload_token, |
| 5223 | .used = .capture, |
| 5224 | }; |
| 5225 | break :s &payload_val_scope.base; |
| 5226 | } else { |
| 5227 | break :s &then_scope.base; |
| 5228 | } |
| 5179 | 5229 | } else if (while_full.payload_token) |payload_token| { |
| 5180 | 5230 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| 5181 | 5231 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -5184,12 +5234,15 @@ fn whileExpr( |
| 5184 | 5234 | .optional_payload_unsafe; |
| 5185 | 5235 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 5186 | 5236 | const ident_name = try astgen.identAsString(ident_token); |
| 5237 | if (mem.eql(u8, "_", tree.tokenSlice(ident_token))) |
| 5238 | break :s &then_scope.base; |
| 5187 | 5239 | payload_val_scope = .{ |
| 5188 | 5240 | .parent = &then_scope.base, |
| 5189 | 5241 | .gen_zir = &then_scope, |
| 5190 | 5242 | .name = ident_name, |
| 5191 | 5243 | .inst = payload_inst, |
| 5192 | 5244 | .token_src = ident_token, |
| 5245 | .used = .capture, |
| 5193 | 5246 | }; |
| 5194 | 5247 | break :s &payload_val_scope.base; |
| 5195 | 5248 | } else { |
| ... | ... | @@ -5199,6 +5252,7 @@ fn whileExpr( |
| 5199 | 5252 | |
| 5200 | 5253 | loop_scope.break_count += 1; |
| 5201 | 5254 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); |
| 5255 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5202 | 5256 | |
| 5203 | 5257 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5204 | 5258 | defer else_scope.instructions.deinit(astgen.gpa); |
| ... | ... | @@ -5217,21 +5271,26 @@ fn whileExpr( |
| 5217 | 5271 | .err_union_code; |
| 5218 | 5272 | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| 5219 | 5273 | const ident_name = try astgen.identAsString(error_token); |
| 5274 | if (mem.eql(u8, tree.tokenSlice(error_token), "_")) |
| 5275 | break :s &else_scope.base; |
| 5220 | 5276 | payload_val_scope = .{ |
| 5221 | 5277 | .parent = &else_scope.base, |
| 5222 | 5278 | .gen_zir = &else_scope, |
| 5223 | 5279 | .name = ident_name, |
| 5224 | 5280 | .inst = payload_inst, |
| 5225 | 5281 | .token_src = error_token, |
| 5282 | .used = .capture, |
| 5226 | 5283 | }; |
| 5227 | 5284 | break :s &payload_val_scope.base; |
| 5228 | 5285 | } else { |
| 5229 | 5286 | break :s &else_scope.base; |
| 5230 | 5287 | } |
| 5231 | 5288 | }; |
| 5289 | const e = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); |
| 5290 | try checkUsed(parent_gz, &else_scope.base, sub_scope); |
| 5232 | 5291 | break :blk .{ |
| 5233 | 5292 | .src = else_node, |
| 5234 | | .result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node), |
| 5293 | .result = e, |
| 5235 | 5294 | }; |
| 5236 | 5295 | } else .{ |
| 5237 | 5296 | .src = while_full.ast.then_expr, |
| ... | ... | @@ -5362,6 +5421,7 @@ fn forExpr( |
| 5362 | 5421 | .name = name_str_index, |
| 5363 | 5422 | .inst = payload_inst, |
| 5364 | 5423 | .token_src = ident, |
| 5424 | .used = .capture, |
| 5365 | 5425 | }; |
| 5366 | 5426 | payload_sub_scope = &payload_val_scope.base; |
| 5367 | 5427 | } else if (is_ptr) { |
| ... | ... | @@ -5385,12 +5445,14 @@ fn forExpr( |
| 5385 | 5445 | .ptr = index_ptr, |
| 5386 | 5446 | .token_src = index_token, |
| 5387 | 5447 | .maybe_comptime = is_inline, |
| 5448 | .used = .loop_index, |
| 5388 | 5449 | }; |
| 5389 | 5450 | break :blk &index_scope.base; |
| 5390 | 5451 | }; |
| 5391 | 5452 | |
| 5392 | 5453 | loop_scope.break_count += 1; |
| 5393 | 5454 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); |
| 5455 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5394 | 5456 | |
| 5395 | 5457 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5396 | 5458 | defer else_scope.instructions.deinit(astgen.gpa); |
| ... | ... | @@ -5631,10 +5693,12 @@ fn switchExpr( |
| 5631 | 5693 | .name = capture_name, |
| 5632 | 5694 | .inst = capture, |
| 5633 | 5695 | .token_src = payload_token, |
| 5696 | .used = .capture, |
| 5634 | 5697 | }; |
| 5635 | 5698 | break :blk &capture_val_scope.base; |
| 5636 | 5699 | }; |
| 5637 | 5700 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 5701 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 5638 | 5702 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 5639 | 5703 | block_scope.break_count += 1; |
| 5640 | 5704 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| ... | ... | @@ -5723,6 +5787,7 @@ fn switchExpr( |
| 5723 | 5787 | .name = capture_name, |
| 5724 | 5788 | .inst = capture, |
| 5725 | 5789 | .token_src = payload_token, |
| 5790 | .used = .capture, |
| 5726 | 5791 | }; |
| 5727 | 5792 | break :blk &capture_val_scope.base; |
| 5728 | 5793 | }; |
| ... | ... | @@ -5756,6 +5821,7 @@ fn switchExpr( |
| 5756 | 5821 | } |
| 5757 | 5822 | |
| 5758 | 5823 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 5824 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 5759 | 5825 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 5760 | 5826 | block_scope.break_count += 1; |
| 5761 | 5827 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| ... | ... | @@ -5769,6 +5835,7 @@ fn switchExpr( |
| 5769 | 5835 | const item_node = case.ast.values[0]; |
| 5770 | 5836 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 5771 | 5837 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 5838 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 5772 | 5839 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 5773 | 5840 | block_scope.break_count += 1; |
| 5774 | 5841 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| ... | ... | @@ -6147,24 +6214,21 @@ fn identifier( |
| 6147 | 6214 | while (true) switch (s.tag) { |
| 6148 | 6215 | .local_val => { |
| 6149 | 6216 | const local_val = s.cast(Scope.LocalVal).?; |
| 6217 | |
| 6150 | 6218 | if (local_val.name == name_str_index) { |
| 6151 | | local_val.used = true; |
| 6152 | | } |
| 6153 | | if (hit_namespace) { |
| 6154 | | // captures of non-locals need to be emitted as decl_val or decl_ref |
| 6155 | | // This *might* be capturable depending on if it is comptime known |
| 6156 | | s = local_val.parent; |
| 6157 | | continue; |
| 6158 | | } |
| 6159 | | if (local_val.name == name_str_index) { |
| 6160 | | return rvalue(gz, scope, rl, local_val.inst, ident); |
| 6219 | local_val.used = .used; |
| 6220 | // Captures of non-locals need to be emitted as decl_val or decl_ref. |
| 6221 | // This *might* be capturable depending on if it is comptime known. |
| 6222 | if (!hit_namespace) { |
| 6223 | return rvalue(gz, scope, rl, local_val.inst, ident); |
| 6224 | } |
| 6161 | 6225 | } |
| 6162 | 6226 | s = local_val.parent; |
| 6163 | 6227 | }, |
| 6164 | 6228 | .local_ptr => { |
| 6165 | 6229 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6166 | 6230 | if (local_ptr.name == name_str_index) { |
| 6167 | | local_ptr.used = true; |
| 6231 | local_ptr.used = .used; |
| 6168 | 6232 | if (hit_namespace) { |
| 6169 | 6233 | if (local_ptr.maybe_comptime) |
| 6170 | 6234 | break |
| ... | ... | @@ -6456,7 +6520,7 @@ fn asmExpr( |
| 6456 | 6520 | .local_val => { |
| 6457 | 6521 | const local_val = s.cast(Scope.LocalVal).?; |
| 6458 | 6522 | if (local_val.name == str_index) { |
| 6459 | | local_val.used = true; |
| 6523 | local_val.used = .used; |
| 6460 | 6524 | break; |
| 6461 | 6525 | } |
| 6462 | 6526 | s = local_val.parent; |
| ... | ... | @@ -6464,7 +6528,7 @@ fn asmExpr( |
| 6464 | 6528 | .local_ptr => { |
| 6465 | 6529 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6466 | 6530 | if (local_ptr.name == str_index) { |
| 6467 | | local_ptr.used = true; |
| 6531 | local_ptr.used = .used; |
| 6468 | 6532 | break; |
| 6469 | 6533 | } |
| 6470 | 6534 | s = local_ptr.parent; |
| ... | ... | @@ -6815,7 +6879,7 @@ fn builtinCall( |
| 6815 | 6879 | .local_val => { |
| 6816 | 6880 | const local_val = s.cast(Scope.LocalVal).?; |
| 6817 | 6881 | if (local_val.name == decl_name) { |
| 6818 | | local_val.used = true; |
| 6882 | local_val.used = .used; |
| 6819 | 6883 | break; |
| 6820 | 6884 | } |
| 6821 | 6885 | s = local_val.parent; |
| ... | ... | @@ -6825,7 +6889,7 @@ fn builtinCall( |
| 6825 | 6889 | if (local_ptr.name == decl_name) { |
| 6826 | 6890 | if (!local_ptr.maybe_comptime) |
| 6827 | 6891 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); |
| 6828 | | local_ptr.used = true; |
| 6892 | local_ptr.used = .used; |
| 6829 | 6893 | break; |
| 6830 | 6894 | } |
| 6831 | 6895 | s = local_ptr.parent; |
| ... | ... | @@ -8394,6 +8458,15 @@ const Scope = struct { |
| 8394 | 8458 | top, |
| 8395 | 8459 | }; |
| 8396 | 8460 | |
| 8461 | // either .used or the type of the var/constant |
| 8462 | const Used = enum { |
| 8463 | fn_param, |
| 8464 | constant, |
| 8465 | variable, |
| 8466 | loop_index, |
| 8467 | capture, |
| 8468 | used, |
| 8469 | }; |
| 8397 | 8470 | /// This is always a `const` local and importantly the `inst` is a value type, not a pointer. |
| 8398 | 8471 | /// This structure lives as long as the AST generation of the Block |
| 8399 | 8472 | /// node that contains the variable. |
| ... | ... | @@ -8409,7 +8482,7 @@ const Scope = struct { |
| 8409 | 8482 | /// String table index. |
| 8410 | 8483 | name: u32, |
| 8411 | 8484 | /// has this variable been referenced? |
| 8412 | | used: bool = false, |
| 8485 | used: Used, |
| 8413 | 8486 | }; |
| 8414 | 8487 | |
| 8415 | 8488 | /// This could be a `const` or `var` local. It has a pointer instead of a value. |
| ... | ... | @@ -8429,7 +8502,7 @@ const Scope = struct { |
| 8429 | 8502 | /// 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. |
| 8430 | 8503 | maybe_comptime: bool, |
| 8431 | 8504 | /// has this variable been referenced? |
| 8432 | | used: bool = false, |
| 8505 | used: Used, |
| 8433 | 8506 | }; |
| 8434 | 8507 | |
| 8435 | 8508 | const Defer = struct { |