| ... | ... | @@ -2685,11 +2685,7 @@ fn genDefers( |
| 2685 | 2685 | } |
| 2686 | 2686 | } |
| 2687 | 2687 | |
| 2688 | | fn checkUsed( |
| 2689 | | gz: *GenZir, |
| 2690 | | outer_scope: *Scope, |
| 2691 | | inner_scope: *Scope, |
| 2692 | | ) InnerError!void { |
| 2688 | fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!void { |
| 2693 | 2689 | const astgen = gz.astgen; |
| 2694 | 2690 | |
| 2695 | 2691 | var scope = inner_scope; |
| ... | ... | @@ -2698,15 +2694,23 @@ fn checkUsed( |
| 2698 | 2694 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 2699 | 2695 | .local_val => { |
| 2700 | 2696 | const s = scope.cast(Scope.LocalVal).?; |
| 2701 | | if (!s.used) { |
| 2697 | if (s.used == 0 and s.discarded == 0) { |
| 2702 | 2698 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 2699 | } else if (s.used != 0 and s.discarded != 0) { |
| 2700 | try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ |
| 2701 | try gz.astgen.errNoteTok(s.used, "used here", .{}), |
| 2702 | }); |
| 2703 | 2703 | } |
| 2704 | 2704 | scope = s.parent; |
| 2705 | 2705 | }, |
| 2706 | 2706 | .local_ptr => { |
| 2707 | 2707 | const s = scope.cast(Scope.LocalPtr).?; |
| 2708 | | if (!s.used) { |
| 2708 | if (s.used == 0 and s.discarded == 0) { |
| 2709 | 2709 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 2710 | } else if (s.used != 0 and s.discarded != 0) { |
| 2711 | try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ |
| 2712 | try gz.astgen.errNoteTok(s.used, "used here", .{}), |
| 2713 | }); |
| 2710 | 2714 | } |
| 2711 | 2715 | scope = s.parent; |
| 2712 | 2716 | }, |
| ... | ... | @@ -6848,11 +6852,10 @@ fn localVarRef( |
| 6848 | 6852 | scope: *Scope, |
| 6849 | 6853 | rl: ResultLoc, |
| 6850 | 6854 | ident: Ast.Node.Index, |
| 6851 | | ident_token: Ast.Node.Index, |
| 6855 | ident_token: Ast.TokenIndex, |
| 6852 | 6856 | ) InnerError!Zir.Inst.Ref { |
| 6853 | 6857 | const astgen = gz.astgen; |
| 6854 | 6858 | const gpa = astgen.gpa; |
| 6855 | | |
| 6856 | 6859 | const name_str_index = try astgen.identAsString(ident_token); |
| 6857 | 6860 | var s = scope; |
| 6858 | 6861 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already |
| ... | ... | @@ -6865,7 +6868,11 @@ fn localVarRef( |
| 6865 | 6868 | if (local_val.name == name_str_index) { |
| 6866 | 6869 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 6867 | 6870 | // references in this case. |
| 6868 | | local_val.used = true; |
| 6871 | if (rl == .discard) { |
| 6872 | local_val.discarded = ident_token; |
| 6873 | } else { |
| 6874 | local_val.used = ident_token; |
| 6875 | } |
| 6869 | 6876 | |
| 6870 | 6877 | const value_inst = try tunnelThroughClosure( |
| 6871 | 6878 | gz, |
| ... | ... | @@ -6884,7 +6891,11 @@ fn localVarRef( |
| 6884 | 6891 | .local_ptr => { |
| 6885 | 6892 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6886 | 6893 | if (local_ptr.name == name_str_index) { |
| 6887 | | local_ptr.used = true; |
| 6894 | if (rl == .discard) { |
| 6895 | local_ptr.discarded = ident_token; |
| 6896 | } else { |
| 6897 | local_ptr.used = ident_token; |
| 6898 | } |
| 6888 | 6899 | |
| 6889 | 6900 | // Can't close over a runtime variable |
| 6890 | 6901 | if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) { |
| ... | ... | @@ -7519,7 +7530,7 @@ fn builtinCall( |
| 7519 | 7530 | .local_val => { |
| 7520 | 7531 | const local_val = s.cast(Scope.LocalVal).?; |
| 7521 | 7532 | if (local_val.name == decl_name) { |
| 7522 | | local_val.used = true; |
| 7533 | local_val.used = ident_token; |
| 7523 | 7534 | _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ |
| 7524 | 7535 | .operand = local_val.inst, |
| 7525 | 7536 | .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), |
| ... | ... | @@ -7533,7 +7544,7 @@ fn builtinCall( |
| 7533 | 7544 | if (local_ptr.name == decl_name) { |
| 7534 | 7545 | if (!local_ptr.maybe_comptime) |
| 7535 | 7546 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); |
| 7536 | | local_ptr.used = true; |
| 7547 | local_ptr.used = ident_token; |
| 7537 | 7548 | const loaded = try gz.addUnNode(.load, local_ptr.ptr, node); |
| 7538 | 7549 | _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ |
| 7539 | 7550 | .operand = loaded, |
| ... | ... | @@ -10065,11 +10076,15 @@ const Scope = struct { |
| 10065 | 10076 | inst: Zir.Inst.Ref, |
| 10066 | 10077 | /// Source location of the corresponding variable declaration. |
| 10067 | 10078 | token_src: Ast.TokenIndex, |
| 10079 | /// Track the first identifer where it is referenced. |
| 10080 | /// 0 means never referenced. |
| 10081 | used: Ast.TokenIndex = 0, |
| 10082 | /// Track the identifier where it is discarded, like this `_ = foo;`. |
| 10083 | /// 0 means never discarded. |
| 10084 | discarded: Ast.TokenIndex = 0, |
| 10068 | 10085 | /// String table index. |
| 10069 | 10086 | name: u32, |
| 10070 | 10087 | id_cat: IdCat, |
| 10071 | | /// Track whether the name has been referenced. |
| 10072 | | used: bool = false, |
| 10073 | 10088 | }; |
| 10074 | 10089 | |
| 10075 | 10090 | /// This could be a `const` or `var` local. It has a pointer instead of a value. |
| ... | ... | @@ -10084,14 +10099,18 @@ const Scope = struct { |
| 10084 | 10099 | ptr: Zir.Inst.Ref, |
| 10085 | 10100 | /// Source location of the corresponding variable declaration. |
| 10086 | 10101 | token_src: Ast.TokenIndex, |
| 10102 | /// Track the first identifer where it is referenced. |
| 10103 | /// 0 means never referenced. |
| 10104 | used: Ast.TokenIndex = 0, |
| 10105 | /// Track the identifier where it is discarded, like this `_ = foo;`. |
| 10106 | /// 0 means never discarded. |
| 10107 | discarded: Ast.TokenIndex = 0, |
| 10087 | 10108 | /// String table index. |
| 10088 | 10109 | name: u32, |
| 10089 | 10110 | id_cat: IdCat, |
| 10090 | 10111 | /// true means we find out during Sema whether the value is comptime. |
| 10091 | 10112 | /// false means it is already known at AstGen the value is runtime-known. |
| 10092 | 10113 | maybe_comptime: bool, |
| 10093 | | /// Track whether the name has been referenced. |
| 10094 | | used: bool = false, |
| 10095 | 10114 | }; |
| 10096 | 10115 | |
| 10097 | 10116 | const Defer = struct { |