| ... | @@ -308,6 +308,9 @@ const ResultInfo = struct { | ... | @@ -308,6 +308,9 @@ const ResultInfo = struct { |
| 308 | /// The expression must generate a pointer rather than a value, and the pointer will be coerced | 308 | /// The expression must generate a pointer rather than a value, and the pointer will be coerced |
| 309 | /// by other code to this type, which is guaranteed by earlier instructions to be a pointer type. | 309 | /// by other code to this type, which is guaranteed by earlier instructions to be a pointer type. |
| 310 | ref_coerced_ty: Zir.Inst.Ref, | 310 | ref_coerced_ty: Zir.Inst.Ref, |
| | 311 | /// Like `ref`, but the pointer will never be stored to, so local variables should not be |
| | 312 | /// marked as possibly being mutated. |
| | 313 | ref_const, |
| 311 | /// The expression must store its result into this typed pointer. The result instruction | 314 | /// The expression must store its result into this typed pointer. The result instruction |
| 312 | /// from the expression must be ignored. | 315 | /// from the expression must be ignored. |
| 313 | ptr: PtrResultLoc, | 316 | ptr: PtrResultLoc, |
| ... | @@ -339,7 +342,7 @@ const ResultInfo = struct { | ... | @@ -339,7 +342,7 @@ const ResultInfo = struct { |
| 339 | /// If the location does not have a known result type, returns `null`. | 342 | /// If the location does not have a known result type, returns `null`. |
| 340 | fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref { | 343 | fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref { |
| 341 | return switch (rl) { | 344 | return switch (rl) { |
| 342 | .discard, .none, .ref, .inferred_ptr, .destructure => null, | 345 | .discard, .none, .ref, .ref_const, .inferred_ptr, .destructure => null, |
| 343 | .ty, .coerced_ty => |ty_ref| ty_ref, | 346 | .ty, .coerced_ty => |ty_ref| ty_ref, |
| 344 | .ref_coerced_ty => |ptr_ty| try gz.addUnNode(.elem_type, ptr_ty, node), | 347 | .ref_coerced_ty => |ptr_ty| try gz.addUnNode(.elem_type, ptr_ty, node), |
| 345 | .ptr => |ptr| { | 348 | .ptr => |ptr| { |
| ... | @@ -937,7 +940,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -937,7 +940,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 937 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node); | 940 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node); |
| 938 | _ = try gz.addUnNode(.validate_deref, lhs, node); | 941 | _ = try gz.addUnNode(.validate_deref, lhs, node); |
| 939 | switch (ri.rl) { | 942 | switch (ri.rl) { |
| 940 | .ref, .ref_coerced_ty => return lhs, | 943 | .ref, |
| | 944 | .ref_coerced_ty, |
| | 945 | .ref_const, |
| | 946 | => return lhs, |
| | 947 | |
| 941 | else => { | 948 | else => { |
| 942 | const result = try gz.addUnNode(.load, lhs, node); | 949 | const result = try gz.addUnNode(.load, lhs, node); |
| 943 | return rvalue(gz, ri, result, node); | 950 | return rvalue(gz, ri, result, node); |
| ... | @@ -973,6 +980,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -973,6 +980,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 973 | | 980 | |
| 974 | return gz.addUnNode(.optional_payload_safe_ptr, lhs, node); | 981 | return gz.addUnNode(.optional_payload_safe_ptr, lhs, node); |
| 975 | }, | 982 | }, |
| | 983 | .ref_const => { |
| | 984 | const lhs = try expr(gz, scope, .{ .rl = .ref_const }, tree.nodeData(node).node_and_token[0]); |
| | 985 | |
| | 986 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| | 987 | try emitDbgStmt(gz, cursor); |
| | 988 | |
| | 989 | return gz.addUnNode(.optional_payload_safe_ptr, lhs, node); |
| | 990 | }, |
| 976 | else => { | 991 | else => { |
| 977 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]); | 992 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]); |
| 978 | | 993 | |
| ... | @@ -998,7 +1013,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -998,7 +1013,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 998 | .field_name_start = str_index, | 1013 | .field_name_start = str_index, |
| 999 | }); | 1014 | }); |
| 1000 | switch (ri.rl) { | 1015 | switch (ri.rl) { |
| 1001 | .discard, .none, .ref, .inferred_ptr, .destructure => unreachable, // no result type | 1016 | .discard, .none, .ref, .ref_const, .inferred_ptr, .destructure => unreachable, // no result type |
| 1002 | .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us | 1017 | .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us |
| 1003 | .ref_coerced_ty, .ptr => return rvalue(gz, ri, res, node), | 1018 | .ref_coerced_ty, .ptr => return rvalue(gz, ri, res, node), |
| 1004 | } | 1019 | } |
| ... | @@ -1030,7 +1045,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -1030,7 +1045,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1030 | return switchExpr(gz, scope, ri.br(), node, switch_full, .@"catch"); | 1045 | return switchExpr(gz, scope, ri.br(), node, switch_full, .@"catch"); |
| 1031 | } | 1046 | } |
| 1032 | switch (ri.rl) { | 1047 | switch (ri.rl) { |
| 1033 | .ref, .ref_coerced_ty => return orelseCatchExpr( | 1048 | .ref, .ref_const, .ref_coerced_ty => return orelseCatchExpr( |
| 1034 | gz, | 1049 | gz, |
| 1035 | scope, | 1050 | scope, |
| 1036 | ri, | 1051 | ri, |
| ... | @@ -1053,7 +1068,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -1053,7 +1068,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1053 | } | 1068 | } |
| 1054 | }, | 1069 | }, |
| 1055 | .@"orelse" => switch (ri.rl) { | 1070 | .@"orelse" => switch (ri.rl) { |
| 1056 | .ref, .ref_coerced_ty => return orelseCatchExpr( | 1071 | .ref, .ref_const, .ref_coerced_ty => return orelseCatchExpr( |
| 1057 | gz, | 1072 | gz, |
| 1058 | scope, | 1073 | scope, |
| 1059 | ri, | 1074 | ri, |
| ... | @@ -1511,7 +1526,7 @@ fn arrayInitExpr( | ... | @@ -1511,7 +1526,7 @@ fn arrayInitExpr( |
| 1511 | } | 1526 | } |
| 1512 | return .void_value; | 1527 | return .void_value; |
| 1513 | }, | 1528 | }, |
| 1514 | .ref => return arrayInitExprTyped(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, true), | 1529 | .ref, .ref_const => return arrayInitExprTyped(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, true), |
| 1515 | else => { | 1530 | else => { |
| 1516 | const array_inst = try arrayInitExprTyped(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, false); | 1531 | const array_inst = try arrayInitExprTyped(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, false); |
| 1517 | return rvalue(gz, ri, array_inst, node); | 1532 | return rvalue(gz, ri, array_inst, node); |
| ... | @@ -1527,7 +1542,7 @@ fn arrayInitExpr( | ... | @@ -1527,7 +1542,7 @@ fn arrayInitExpr( |
| 1527 | } | 1542 | } |
| 1528 | return Zir.Inst.Ref.void_value; | 1543 | return Zir.Inst.Ref.void_value; |
| 1529 | }, | 1544 | }, |
| 1530 | .ref => { | 1545 | .ref, .ref_const => { |
| 1531 | const result = try arrayInitExprAnon(gz, scope, node, array_init.ast.elements); | 1546 | const result = try arrayInitExprAnon(gz, scope, node, array_init.ast.elements); |
| 1532 | return gz.addUnTok(.ref, result, tree.firstToken(node)); | 1547 | return gz.addUnTok(.ref, result, tree.firstToken(node)); |
| 1533 | }, | 1548 | }, |
| ... | @@ -1701,7 +1716,7 @@ fn structInitExpr( | ... | @@ -1701,7 +1716,7 @@ fn structInitExpr( |
| 1701 | const val = try gz.addUnNode(.struct_init_empty_result, ty_inst, node); | 1716 | const val = try gz.addUnNode(.struct_init_empty_result, ty_inst, node); |
| 1702 | return rvalue(gz, ri, val, node); | 1717 | return rvalue(gz, ri, val, node); |
| 1703 | }, | 1718 | }, |
| 1704 | .none, .ref, .inferred_ptr => { | 1719 | .none, .ref, .ref_const, .inferred_ptr => { |
| 1705 | return rvalue(gz, ri, .empty_tuple, node); | 1720 | return rvalue(gz, ri, .empty_tuple, node); |
| 1706 | }, | 1721 | }, |
| 1707 | .destructure => |destructure| { | 1722 | .destructure => |destructure| { |
| ... | @@ -1817,7 +1832,7 @@ fn structInitExpr( | ... | @@ -1817,7 +1832,7 @@ fn structInitExpr( |
| 1817 | const ty_inst = try typeExpr(gz, scope, type_expr); | 1832 | const ty_inst = try typeExpr(gz, scope, type_expr); |
| 1818 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); | 1833 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); |
| 1819 | switch (ri.rl) { | 1834 | switch (ri.rl) { |
| 1820 | .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true), | 1835 | .ref, .ref_const => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true), |
| 1821 | else => { | 1836 | else => { |
| 1822 | const struct_inst = try structInitExprTyped(gz, scope, node, struct_init, ty_inst, false); | 1837 | const struct_inst = try structInitExprTyped(gz, scope, node, struct_init, ty_inst, false); |
| 1823 | return rvalue(gz, ri, struct_inst, node); | 1838 | return rvalue(gz, ri, struct_inst, node); |
| ... | @@ -1834,7 +1849,7 @@ fn structInitExpr( | ... | @@ -1834,7 +1849,7 @@ fn structInitExpr( |
| 1834 | } | 1849 | } |
| 1835 | return .void_value; | 1850 | return .void_value; |
| 1836 | }, | 1851 | }, |
| 1837 | .ref => { | 1852 | .ref, .ref_const => { |
| 1838 | const result = try structInitExprAnon(gz, scope, node, struct_init); | 1853 | const result = try structInitExprAnon(gz, scope, node, struct_init); |
| 1839 | return gz.addUnTok(.ref, result, tree.firstToken(node)); | 1854 | return gz.addUnTok(.ref, result, tree.firstToken(node)); |
| 1840 | }, | 1855 | }, |
| ... | @@ -5832,6 +5847,7 @@ fn tryExpr( | ... | @@ -5832,6 +5847,7 @@ fn tryExpr( |
| 5832 | | 5847 | |
| 5833 | const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) { | 5848 | const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) { |
| 5834 | .ref, .ref_coerced_ty => .{ .ref, .try_ptr }, | 5849 | .ref, .ref_coerced_ty => .{ .ref, .try_ptr }, |
| | 5850 | .ref_const => .{ .ref_const, .try_ptr }, |
| 5835 | else => .{ .none, .@"try" }, | 5851 | else => .{ .none, .@"try" }, |
| 5836 | }; | 5852 | }; |
| 5837 | const operand_ri: ResultInfo = .{ .rl = operand_rl, .ctx = .error_handling_expr }; | 5853 | const operand_ri: ResultInfo = .{ .rl = operand_rl, .ctx = .error_handling_expr }; |
| ... | @@ -5856,7 +5872,7 @@ fn tryExpr( | ... | @@ -5856,7 +5872,7 @@ fn tryExpr( |
| 5856 | defer else_scope.unstack(); | 5872 | defer else_scope.unstack(); |
| 5857 | | 5873 | |
| 5858 | const err_tag = switch (ri.rl) { | 5874 | const err_tag = switch (ri.rl) { |
| 5859 | .ref, .ref_coerced_ty => Zir.Inst.Tag.err_union_code_ptr, | 5875 | .ref, .ref_const, .ref_coerced_ty => Zir.Inst.Tag.err_union_code_ptr, |
| 5860 | else => Zir.Inst.Tag.err_union_code, | 5876 | else => Zir.Inst.Tag.err_union_code, |
| 5861 | }; | 5877 | }; |
| 5862 | const err_code = try else_scope.addUnNode(err_tag, operand, node); | 5878 | const err_code = try else_scope.addUnNode(err_tag, operand, node); |
| ... | @@ -5867,7 +5883,7 @@ fn tryExpr( | ... | @@ -5867,7 +5883,7 @@ fn tryExpr( |
| 5867 | try else_scope.setTryBody(try_inst, operand); | 5883 | try else_scope.setTryBody(try_inst, operand); |
| 5868 | const result = try_inst.toRef(); | 5884 | const result = try_inst.toRef(); |
| 5869 | switch (ri.rl) { | 5885 | switch (ri.rl) { |
| 5870 | .ref, .ref_coerced_ty => return result, | 5886 | .ref, .ref_const, .ref_coerced_ty => return result, |
| 5871 | else => return rvalue(parent_gz, ri, result, node), | 5887 | else => return rvalue(parent_gz, ri, result, node), |
| 5872 | } | 5888 | } |
| 5873 | } | 5889 | } |
| ... | @@ -5909,6 +5925,7 @@ fn orelseCatchExpr( | ... | @@ -5909,6 +5925,7 @@ fn orelseCatchExpr( |
| 5909 | | 5925 | |
| 5910 | const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) { | 5926 | const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) { |
| 5911 | .ref, .ref_coerced_ty => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none }, | 5927 | .ref, .ref_coerced_ty => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none }, |
| | 5928 | .ref_const => .{ .rl = .ref_const, .ctx = if (do_err_trace) .error_handling_expr else .none }, |
| 5912 | else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none }, | 5929 | else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none }, |
| 5913 | }; | 5930 | }; |
| 5914 | // This could be a pointer or value depending on the `operand_ri` parameter. | 5931 | // This could be a pointer or value depending on the `operand_ri` parameter. |
| ... | @@ -5930,7 +5947,7 @@ fn orelseCatchExpr( | ... | @@ -5930,7 +5947,7 @@ fn orelseCatchExpr( |
| 5930 | // This could be a pointer or value depending on `unwrap_op`. | 5947 | // This could be a pointer or value depending on `unwrap_op`. |
| 5931 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); | 5948 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); |
| 5932 | const then_result = switch (ri.rl) { | 5949 | const then_result = switch (ri.rl) { |
| 5933 | .ref, .ref_coerced_ty => unwrapped_payload, | 5950 | .ref, .ref_const, .ref_coerced_ty => unwrapped_payload, |
| 5934 | else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node), | 5951 | else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node), |
| 5935 | }; | 5952 | }; |
| 5936 | _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, node); | 5953 | _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, node); |
| ... | @@ -6026,8 +6043,9 @@ fn fieldAccess( | ... | @@ -6026,8 +6043,9 @@ fn fieldAccess( |
| 6026 | ) InnerError!Zir.Inst.Ref { | 6043 | ) InnerError!Zir.Inst.Ref { |
| 6027 | switch (ri.rl) { | 6044 | switch (ri.rl) { |
| 6028 | .ref, .ref_coerced_ty => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node), | 6045 | .ref, .ref_coerced_ty => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node), |
| | 6046 | .ref_const => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref_const }, node), |
| 6029 | else => { | 6047 | else => { |
| 6030 | const access = try addFieldAccess(.field_ptr_load, gz, scope, .{ .rl = .ref }, node); | 6048 | const access = try addFieldAccess(.field_ptr_load, gz, scope, .{ .rl = .ref_const }, node); |
| 6031 | return rvalue(gz, ri, access, node); | 6049 | return rvalue(gz, ri, access, node); |
| 6032 | }, | 6050 | }, |
| 6033 | } | 6051 | } |
| ... | @@ -6075,9 +6093,20 @@ fn arrayAccess( | ... | @@ -6075,9 +6093,20 @@ fn arrayAccess( |
| 6075 | | 6093 | |
| 6076 | return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); | 6094 | return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); |
| 6077 | }, | 6095 | }, |
| | 6096 | .ref_const => { |
| | 6097 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; |
| | 6098 | const lhs = try expr(gz, scope, .{ .rl = .ref_const }, lhs_node); |
| | 6099 | |
| | 6100 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| | 6101 | |
| | 6102 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node); |
| | 6103 | try emitDbgStmt(gz, cursor); |
| | 6104 | |
| | 6105 | return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); |
| | 6106 | }, |
| 6078 | else => { | 6107 | else => { |
| 6079 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | 6108 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; |
| 6080 | const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node); | 6109 | const lhs = try expr(gz, scope, .{ .rl = .ref_const }, lhs_node); |
| 6081 | | 6110 | |
| 6082 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); | 6111 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 6083 | | 6112 | |
| ... | @@ -7092,11 +7121,15 @@ fn switchExpr( | ... | @@ -7092,11 +7121,15 @@ fn switchExpr( |
| 7092 | | 7121 | |
| 7093 | const catch_or_if_node = if (needs_non_err_handling) node else undefined; | 7122 | const catch_or_if_node = if (needs_non_err_handling) node else undefined; |
| 7094 | const do_err_trace = needs_non_err_handling and astgen.fn_block != null; | 7123 | const do_err_trace = needs_non_err_handling and astgen.fn_block != null; |
| 7095 | const non_err_is_ref: bool = switch (non_err) { | 7124 | const non_err_is_ref: enum { no, yes, yes_const } = switch (non_err) { |
| 7096 | .none, .peer_break_target => undefined, | 7125 | .none, .peer_break_target => undefined, |
| 7097 | .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty, | 7126 | .@"catch" => switch (ri.rl) { |
| 7098 | .@"if" => |if_full| if_full.payload_token != null and | 7127 | .ref, .ref_coerced_ty => .yes, |
| 7099 | tree.tokenTag(if_full.payload_token.?) == .asterisk, | 7128 | .ref_const => .yes_const, |
| | 7129 | else => .no, |
| | 7130 | }, |
| | 7131 | .@"if" => |if_full| if (if_full.payload_token != null and |
| | 7132 | tree.tokenTag(if_full.payload_token.?) == .asterisk) .yes else .no, |
| 7100 | }; | 7133 | }; |
| 7101 | | 7134 | |
| 7102 | if (switch_full.label_token) |label_token| { | 7135 | if (switch_full.label_token) |label_token| { |
| ... | @@ -7285,8 +7318,12 @@ fn switchExpr( | ... | @@ -7285,8 +7318,12 @@ fn switchExpr( |
| 7285 | block_scope.instructions_top = GenZir.unstacked_top; | 7318 | block_scope.instructions_top = GenZir.unstacked_top; |
| 7286 | | 7319 | |
| 7287 | const operand_ri: ResultInfo = .{ | 7320 | const operand_ri: ResultInfo = .{ |
| 7288 | .rl = if (any_payload_is_ref or | 7321 | .rl = loc: { |
| 7289 | (needs_non_err_handling and non_err_is_ref)) .ref else .none, | 7322 | if (any_payload_is_ref) break :loc .ref; |
| | 7323 | if (needs_non_err_handling and non_err_is_ref == .yes) break :loc .ref; |
| | 7324 | if (needs_non_err_handling and non_err_is_ref == .yes_const) break :loc .ref_const; |
| | 7325 | break :loc .none; |
| | 7326 | }, |
| 7290 | .ctx = if (do_err_trace) .error_handling_expr else .none, | 7327 | .ctx = if (do_err_trace) .error_handling_expr else .none, |
| 7291 | }; | 7328 | }; |
| 7292 | | 7329 | |
| ... | @@ -7454,10 +7491,10 @@ fn switchExpr( | ... | @@ -7454,10 +7491,10 @@ fn switchExpr( |
| 7454 | .@"catch" => { | 7491 | .@"catch" => { |
| 7455 | // We always effectively capture the error union payload; we use | 7492 | // We always effectively capture the error union payload; we use |
| 7456 | // it to `break` from the entire `switch_block_err_union`. | 7493 | // it to `break` from the entire `switch_block_err_union`. |
| 7457 | non_err_capture = if (non_err_is_ref) .by_ref else .by_val; | 7494 | non_err_capture = if (non_err_is_ref != .no) .by_ref else .by_val; |
| 7458 | | 7495 | |
| 7459 | const then_result = switch (ri.rl) { | 7496 | const then_result = switch (ri.rl) { |
| 7460 | .ref, .ref_coerced_ty => non_err_payload_inst.toRef(), | 7497 | .ref, .ref_const, .ref_coerced_ty => non_err_payload_inst.toRef(), |
| 7461 | else => try rvalue( | 7498 | else => try rvalue( |
| 7462 | &scratch_scope, | 7499 | &scratch_scope, |
| 7463 | block_scope.break_result_info, | 7500 | block_scope.break_result_info, |
| ... | @@ -7478,13 +7515,13 @@ fn switchExpr( | ... | @@ -7478,13 +7515,13 @@ fn switchExpr( |
| 7478 | const then_node = if_full.ast.then_expr; | 7515 | const then_node = if_full.ast.then_expr; |
| 7479 | const then_sub_scope: *Scope = scope: { | 7516 | const then_sub_scope: *Scope = scope: { |
| 7480 | if (if_full.payload_token) |payload_token| { | 7517 | if (if_full.payload_token) |payload_token| { |
| 7481 | const ident_token = payload_token + @intFromBool(non_err_is_ref); | 7518 | const ident_token = payload_token + @intFromBool(non_err_is_ref != .no); |
| 7482 | const ident_name = try astgen.identAsString(ident_token); | 7519 | const ident_name = try astgen.identAsString(ident_token); |
| 7483 | const ident_name_str = tree.tokenSlice(ident_token); | 7520 | const ident_name_str = tree.tokenSlice(ident_token); |
| 7484 | if (mem.eql(u8, "_", ident_name_str)) { | 7521 | if (mem.eql(u8, "_", ident_name_str)) { |
| 7485 | break :scope &scratch_scope.base; | 7522 | break :scope &scratch_scope.base; |
| 7486 | } | 7523 | } |
| 7487 | non_err_capture = if (non_err_is_ref) .by_ref else .by_val; | 7524 | non_err_capture = if (non_err_is_ref != .no) .by_ref else .by_val; |
| 7488 | try astgen.detectLocalShadowing(&scratch_scope.base, ident_name, ident_token, ident_name_str, .capture); | 7525 | try astgen.detectLocalShadowing(&scratch_scope.base, ident_name, ident_token, ident_name_str, .capture); |
| 7489 | payload_val_scope = .{ | 7526 | payload_val_scope = .{ |
| 7490 | .parent = &scratch_scope.base, | 7527 | .parent = &scratch_scope.base, |
| ... | @@ -7522,7 +7559,7 @@ fn switchExpr( | ... | @@ -7522,7 +7559,7 @@ fn switchExpr( |
| 7522 | non_err_info = .{ | 7559 | non_err_info = .{ |
| 7523 | .body_len = @intCast(body_len), | 7560 | .body_len = @intCast(body_len), |
| 7524 | .capture = non_err_capture, | 7561 | .capture = non_err_capture, |
| 7525 | .operand_is_ref = non_err_is_ref, | 7562 | .operand_is_ref = non_err_is_ref != .no, |
| 7526 | }; | 7563 | }; |
| 7527 | } | 7564 | } |
| 7528 | | 7565 | |
| ... | @@ -8245,7 +8282,7 @@ fn localVarRef( | ... | @@ -8245,7 +8282,7 @@ fn localVarRef( |
| 8245 | } | 8282 | } |
| 8246 | | 8283 | |
| 8247 | switch (ri.rl) { | 8284 | switch (ri.rl) { |
| 8248 | .ref, .ref_coerced_ty => { | 8285 | .ref, .ref_const, .ref_coerced_ty => { |
| 8249 | const ptr_inst = if (num_namespaces_out != 0) try tunnelThroughClosure( | 8286 | const ptr_inst = if (num_namespaces_out != 0) try tunnelThroughClosure( |
| 8250 | gz, | 8287 | gz, |
| 8251 | ident, | 8288 | ident, |
| ... | @@ -8254,7 +8291,7 @@ fn localVarRef( | ... | @@ -8254,7 +8291,7 @@ fn localVarRef( |
| 8254 | .{ .token = local_ptr.token_src }, | 8291 | .{ .token = local_ptr.token_src }, |
| 8255 | name_str_index, | 8292 | name_str_index, |
| 8256 | ) else local_ptr.ptr; | 8293 | ) else local_ptr.ptr; |
| 8257 | local_ptr.used_as_lvalue = true; | 8294 | if (ri.rl != .ref_const) local_ptr.used_as_lvalue = true; |
| 8258 | return ptr_inst; | 8295 | return ptr_inst; |
| 8259 | }, | 8296 | }, |
| 8260 | else => { | 8297 | else => { |
| ... | @@ -8303,7 +8340,7 @@ fn localVarRef( | ... | @@ -8303,7 +8340,7 @@ fn localVarRef( |
| 8303 | | 8340 | |
| 8304 | if (found_namespaces_out > 0 and found_needs_tunnel) { | 8341 | if (found_namespaces_out > 0 and found_needs_tunnel) { |
| 8305 | switch (ri.rl) { | 8342 | switch (ri.rl) { |
| 8306 | .ref, .ref_coerced_ty => return tunnelThroughClosure( | 8343 | .ref, .ref_const, .ref_coerced_ty => return tunnelThroughClosure( |
| 8307 | gz, | 8344 | gz, |
| 8308 | ident, | 8345 | ident, |
| 8309 | found_namespaces_out, | 8346 | found_namespaces_out, |
| ... | @@ -8326,7 +8363,7 @@ fn localVarRef( | ... | @@ -8326,7 +8363,7 @@ fn localVarRef( |
| 8326 | } | 8363 | } |
| 8327 | | 8364 | |
| 8328 | switch (ri.rl) { | 8365 | switch (ri.rl) { |
| 8329 | .ref, .ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token), | 8366 | .ref, .ref_const, .ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token), |
| 8330 | else => { | 8367 | else => { |
| 8331 | const result = try gz.addStrTok(.decl_val, name_str_index, ident_token); | 8368 | const result = try gz.addStrTok(.decl_val, name_str_index, ident_token); |
| 8332 | return rvalueNoCoercePreRef(gz, ri, result, ident); | 8369 | return rvalueNoCoercePreRef(gz, ri, result, ident); |
| ... | @@ -9108,9 +9145,15 @@ fn builtinCall( | ... | @@ -9108,9 +9145,15 @@ fn builtinCall( |
| 9108 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), | 9145 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), |
| 9109 | }); | 9146 | }); |
| 9110 | }, | 9147 | }, |
| | 9148 | .ref_const => { |
| | 9149 | return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{ |
| | 9150 | .lhs = try expr(gz, scope, .{ .rl = .ref_const }, params[0]), |
| | 9151 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), |
| | 9152 | }); |
| | 9153 | }, |
| 9111 | else => { | 9154 | else => { |
| 9112 | const result = try gz.addPlNode(.field_ptr_named_load, node, Zir.Inst.FieldNamed{ | 9155 | const result = try gz.addPlNode(.field_ptr_named_load, node, Zir.Inst.FieldNamed{ |
| 9113 | .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), | 9156 | .lhs = try expr(gz, scope, .{ .rl = .ref_const }, params[0]), |
| 9114 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), | 9157 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), |
| 9115 | }); | 9158 | }); |
| 9116 | return rvalue(gz, ri, result, node); | 9159 | return rvalue(gz, ri, result, node); |
| ... | @@ -10530,7 +10573,7 @@ fn rvalueInner( | ... | @@ -10530,7 +10573,7 @@ fn rvalueInner( |
| 10530 | _ = try gz.addUnNode(.ensure_result_non_error, result, src_node); | 10573 | _ = try gz.addUnNode(.ensure_result_non_error, result, src_node); |
| 10531 | return .void_value; | 10574 | return .void_value; |
| 10532 | }, | 10575 | }, |
| 10533 | .ref, .ref_coerced_ty => { | 10576 | .ref, .ref_const, .ref_coerced_ty => { |
| 10534 | const coerced_result = if (allow_coerce_pre_ref and ri.rl == .ref_coerced_ty) res: { | 10577 | const coerced_result = if (allow_coerce_pre_ref and ri.rl == .ref_coerced_ty) res: { |
| 10535 | const ptr_ty = ri.rl.ref_coerced_ty; | 10578 | const ptr_ty = ri.rl.ref_coerced_ty; |
| 10536 | break :res try gz.addPlNode(.coerce_ptr_elem_ty, src_node, Zir.Inst.Bin{ | 10579 | break :res try gz.addPlNode(.coerce_ptr_elem_ty, src_node, Zir.Inst.Bin{ |