@@ -285,6 +285,8 @@ const ResultInfo = struct {
285
285
/// The expression must generate a pointer rather than a value. For example, the left hand side
286
286
/// of an assignment uses this kind of result location.
287
287
ref,
288
+ /// Same as `ty` but will not mark variables as being used as an lvalue.
289
+ pseudo_ref,
288
290
/// The expression must generate a pointer rather than a value, and the pointer will be coerced
289
291
/// by other code to this type, which is guaranteed by earlier instructions to be a pointer type.
290
292
ref_coerced_ty: Zir.Inst.Ref,
@@ -320,7 +322,7 @@ const ResultInfo = struct {
320
322
/// the given node.
321
323
fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {
322
324
return switch (rl) {
323
- .discard, .none, .ref, .inferred_ptr, .destructure => null,
325
+ .discard, .none, .ref, .pseudo_ref, . inferred_ptr, .destructure => null,
324
326
.ty, .coerced_ty => |ty_ref| ty_ref,
325
327
.ref_coerced_ty => |ptr_ty| try gz.addUnNode(.elem_type, ptr_ty, node),
326
328
.ptr => |ptr| {
@@ -970,7 +972,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
970
972
const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
971
973
_ = try gz.addUnNode(.validate_deref, lhs, node);
972
974
switch (ri.rl) {
973
- .ref, .ref_coerced_ty => return lhs,
975
+ .ref, .pseudo_ref, . ref_coerced_ty => return lhs,
974
976
else => {
975
977
const result = try gz.addUnNode(.load, lhs, node);
976
978
return rvalue(gz, ri, result, node);
@@ -991,7 +993,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
991
993
return rvalue(gz, ri, result, node);
992
994
},
993
995
.unwrap_optional => switch (ri.rl) {
994
- .ref, .ref_coerced_ty => {
996
+ .ref, .pseudo_ref, . ref_coerced_ty => {
995
997
const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
996
998
997
999
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
@@ -1053,7 +1055,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1053
1055
return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");
1054
1056
}
1055
1057
switch (ri.rl) {
1056
- .ref, .ref_coerced_ty => return orelseCatchExpr(
1058
+ .ref, .pseudo_ref, . ref_coerced_ty => return orelseCatchExpr(
1057
1059
gz,
1058
1060
scope,
1059
1061
ri,
@@ -1080,7 +1082,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1080
1082
}
1081
1083
},
1082
1084
.@"orelse" => switch (ri.rl) {
1083
- .ref, .ref_coerced_ty => return orelseCatchExpr(
1085
+ .ref, .pseudo_ref, . ref_coerced_ty => return orelseCatchExpr(
1084
1086
gz,
1085
1087
scope,
1086
1088
ri,
@@ -1523,7 +1525,7 @@ fn arrayInitExpr(
1523
1525
}
1524
1526
return Zir.Inst.Ref.void_value;
1525
1527
},
1526
- .ref => {
1528
+ .ref, .pseudo_ref => {
1527
1529
const result = try arrayInitExprAnon(gz, scope, node, array_init.ast.elements);
1528
1530
return gz.addUnTok(.ref, result, tree.firstToken(node));
1529
1531
},
@@ -1697,7 +1699,7 @@ fn structInitExpr(
1697
1699
const val = try gz.addUnNode(.struct_init_empty_result, ty_inst, node);
1698
1700
return rvalue(gz, ri, val, node);
1699
1701
},
1700
- .none, .ref, .inferred_ptr => {
1702
+ .none, .ref, .pseudo_ref, . inferred_ptr => {
1701
1703
return rvalue(gz, ri, .empty_struct, node);
1702
1704
},
1703
1705
.destructure => |destructure| {
@@ -1830,7 +1832,7 @@ fn structInitExpr(
1830
1832
}
1831
1833
return .void_value;
1832
1834
},
1833
- .ref => {
1835
+ .ref, .pseudo_ref => {
1834
1836
const result = try structInitExprAnon(gz, scope, node, struct_init);
1835
1837
return gz.addUnTok(.ref, result, tree.firstToken(node));
1836
1838
},
@@ -5912,21 +5914,25 @@ fn tryExpr(
5912
5914
const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
5913
5915
5914
5916
const operand_ri: ResultInfo = switch (ri.rl) {
5917
+ .pseudo_ref => .{ .rl = .pseudo_ref, .ctx = .error_handling_expr },
5915
5918
.ref, .ref_coerced_ty => .{ .rl = .ref, .ctx = .error_handling_expr },
5916
5919
else => .{ .rl = .none, .ctx = .error_handling_expr },
5917
5920
};
5918
5921
// This could be a pointer or value depending on the `ri` parameter.
5919
5922
const operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node);
5920
- const block_tag: Zir.Inst.Tag = if (operand_ri.rl == .ref) .try_ptr else .@"try";
5923
+ const block_tag: Zir.Inst.Tag = switch (ri.rl) {
5924
+ .ref, .pseudo_ref, .ref_coerced_ty => .try_ptr,
5925
+ else => .@"try",
5926
+ };
5921
5927
const try_inst = try parent_gz.makeBlockInst(block_tag, node);
5922
5928
try parent_gz.instructions.append(astgen.gpa, try_inst);
5923
5929
5924
5930
var else_scope = parent_gz.makeSubBlock(scope);
5925
5931
defer else_scope.unstack();
5926
5932
5927
- const err_tag = switch (ri.rl) {
5928
- .ref, .ref_coerced_ty => Zir.Inst.Tag .err_union_code_ptr,
5929
- else => Zir.Inst.Tag .err_union_code,
5933
+ const err_tag: Zir.Inst.Tag = switch (ri.rl) {
5934
+ .ref, .pseudo_ref, . ref_coerced_ty => .err_union_code_ptr,
5935
+ else => .err_union_code,
5930
5936
};
5931
5937
const err_code = try else_scope.addUnNode(err_tag, operand, node);
5932
5938
try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
@@ -5936,7 +5942,7 @@ fn tryExpr(
5936
5942
try else_scope.setTryBody(try_inst, operand);
5937
5943
const result = try_inst.toRef();
5938
5944
switch (ri.rl) {
5939
- .ref, .ref_coerced_ty => return result,
5945
+ .ref, .pseudo_ref, . ref_coerced_ty => return result,
5940
5946
else => return rvalue(parent_gz, ri, result, node),
5941
5947
}
5942
5948
}
@@ -5977,6 +5983,7 @@ fn orelseCatchExpr(
5977
5983
defer block_scope.unstack();
5978
5984
5979
5985
const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) {
5986
+ .pseudo_ref => .{ .rl = .pseudo_ref, .ctx = if (do_err_trace) .error_handling_expr else .none },
5980
5987
.ref, .ref_coerced_ty => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none },
5981
5988
else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none },
5982
5989
};
@@ -5999,7 +6006,7 @@ fn orelseCatchExpr(
5999
6006
// This could be a pointer or value depending on `unwrap_op`.
6000
6007
const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
6001
6008
const then_result = switch (ri.rl) {
6002
- .ref, .ref_coerced_ty => unwrapped_payload,
6009
+ .ref, .pseudo_ref, . ref_coerced_ty => unwrapped_payload,
6003
6010
else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node),
6004
6011
};
6005
6012
_ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, node);
@@ -6071,8 +6078,9 @@ fn fieldAccess(
6071
6078
) InnerError!Zir.Inst.Ref {
6072
6079
switch (ri.rl) {
6073
6080
.ref, .ref_coerced_ty => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node),
6081
+ .pseudo_ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .pseudo_ref }, node),
6074
6082
else => {
6075
- const ptr = try addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node);
6083
+ const ptr = try addFieldAccess(.field_ptr, gz, scope, .{ .rl = .pseudo_ref }, node);
6076
6084
const result = try gz.addUnNode(.load, ptr, node);
6077
6085
return rvalue(gz, ri, result, node);
6078
6086
},
@@ -6125,8 +6133,18 @@ fn arrayAccess(
6125
6133
6126
6134
return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6127
6135
},
6136
+ .pseudo_ref => {
6137
+ const lhs = try expr(gz, scope, .{ .rl = .pseudo_ref }, node_datas[node].lhs);
6138
+
6139
+ const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
6140
+
6141
+ const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6142
+ try emitDbgStmt(gz, cursor);
6143
+
6144
+ return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6145
+ },
6128
6146
else => {
6129
- const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
6147
+ const lhs = try expr(gz, scope, .{ .rl = .pseudo_ref }, node_datas[node].lhs);
6130
6148
6131
6149
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
6132
6150
@@ -7204,7 +7222,7 @@ fn switchExprErrUnion(
7204
7222
switch (node_ty) {
7205
7223
.@"catch" => {
7206
7224
const case_result = switch (ri.rl) {
7207
- .ref, .ref_coerced_ty => unwrapped_payload,
7225
+ .ref, .pseudo_ref, . ref_coerced_ty => unwrapped_payload,
7208
7226
else => try rvalue(
7209
7227
&case_scope,
7210
7228
block_scope.break_result_info,
@@ -8308,6 +8326,7 @@ fn localVarRef(
8308
8326
) else local_ptr.ptr;
8309
8327
8310
8328
switch (ri.rl) {
8329
+ .pseudo_ref => return ptr_inst,
8311
8330
.ref, .ref_coerced_ty => {
8312
8331
local_ptr.used_as_lvalue = true;
8313
8332
return ptr_inst;
@@ -8352,7 +8371,7 @@ fn localVarRef(
8352
8371
8353
8372
if (found_namespaces_out > 0 and found_needs_tunnel) {
8354
8373
switch (ri.rl) {
8355
- .ref, .ref_coerced_ty => return tunnelThroughClosure(
8374
+ .ref, .pseudo_ref, . ref_coerced_ty => return tunnelThroughClosure(
8356
8375
gz,
8357
8376
ident,
8358
8377
found_namespaces_out,
@@ -8373,7 +8392,7 @@ fn localVarRef(
8373
8392
}
8374
8393
8375
8394
switch (ri.rl) {
8376
- .ref, .ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
8395
+ .ref, .pseudo_ref, . ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
8377
8396
else => {
8378
8397
const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);
8379
8398
return rvalueNoCoercePreRef(gz, ri, result, ident);
@@ -9106,18 +9125,20 @@ fn builtinCall(
9106
9125
const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len);
9107
9126
return rvalue(gz, ri, result, node);
9108
9127
},
9109
- .field => {
9110
- if (ri.rl == . ref or ri.rl == .ref_coerced_ty) {
9128
+ .field => switch (ri.rl) {
9129
+ . ref, .pseudo_ref, .ref_coerced_ty => {
9111
9130
return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
9112
9131
.lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
9113
9132
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
9114
9133
});
9115
- }
9116
- const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
9117
- .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
9118
- .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
9119
- });
9120
- return rvalue(gz, ri, result, node);
9134
+ },
9135
+ else => {
9136
+ const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
9137
+ .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
9138
+ .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
9139
+ });
9140
+ return rvalue(gz, ri, result, node);
9141
+ },
9121
9142
},
9122
9143
9123
9144
// zig fmt: off
@@ -10984,7 +11005,7 @@ fn rvalueInner(
10984
11005
_ = try gz.addUnNode(.ensure_result_non_error, result, src_node);
10985
11006
return .void_value;
10986
11007
},
10987
- .ref, .ref_coerced_ty => {
11008
+ .ref, .pseudo_ref, . ref_coerced_ty => {
10988
11009
const coerced_result = if (allow_coerce_pre_ref and ri.rl == .ref_coerced_ty) res: {
10989
11010
const ptr_ty = ri.rl.ref_coerced_ty;
10990
11011
break :res try gz.addPlNode(.coerce_ptr_elem_ty, src_node, Zir.Inst.Bin{
0 commit comments