authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-10 11:50:01-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-08-10 11:50:01-07:00
log275e926cf851144ef6a4c64963e47f3b955870cc
treeed1717db1a7f6c8c931d5c08e244a11a2334ff93
parent0461a64a93f0596e98b62d596bb547e5455577d2
parentf32b9bc776bfffe0a1adadc013ff3fa3e5d6d34b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16604 from mlugg/result-type-shenanigans

Fix RLS issues, fix crash on invalid result type for `@splat`, refactor some bits of generic instantiations

18 files changed, 858 insertions(+), 491 deletions(-)

src/Air.zig+4-2
...@@ -1528,11 +1528,13 @@ pub fn refToInterned(ref: Inst.Ref) ?InternPool.Index {...@@ -1528,11 +1528,13 @@ pub fn refToInterned(ref: Inst.Ref) ?InternPool.Index {
1528}1528}
15291529
1530pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {1530pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {
1531 assert(@intFromEnum(ip_index) >> 31 == 0);
1532 return switch (ip_index) {1531 return switch (ip_index) {
1533 .var_args_param_type => .var_args_param_type,1532 .var_args_param_type => .var_args_param_type,
1534 .none => .none,1533 .none => .none,
1535 else => @enumFromInt(@as(u31, @intCast(@intFromEnum(ip_index)))),1534 else => {
1535 assert(@intFromEnum(ip_index) >> 31 == 0);
1536 return @enumFromInt(@as(u31, @intCast(@intFromEnum(ip_index))));
1537 },
1536 };1538 };
1537}1539}
15381540
src/AstGen.zig+35-17
...@@ -1509,9 +1509,11 @@ fn arrayInitExpr(...@@ -1509,9 +1509,11 @@ fn arrayInitExpr(
1509 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;1509 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1510 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1510 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1511 },1511 },
1512 .ty, .coerced_ty => {1512 .ty, .coerced_ty => |ty_inst| {
1513 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;1513 const arr_ty = if (types.array != .none) types.array else blk: {
1514 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1514 break :blk try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);
1515 };
1516 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, arr_ty, types.elem, .array_init);
1515 return rvalue(gz, ri, result, node);1517 return rvalue(gz, ri, result, node);
1516 },1518 },
1517 .ptr => |ptr_res| {1519 .ptr => |ptr_res| {
...@@ -1748,7 +1750,9 @@ fn structInitExpr(...@@ -1748,7 +1750,9 @@ fn structInitExpr(
1748 },1750 },
1749 .ty, .coerced_ty => |ty_inst| {1751 .ty, .coerced_ty => |ty_inst| {
1750 if (struct_init.ast.type_expr == 0) {1752 if (struct_init.ast.type_expr == 0) {
1751 const result = try structInitExprRlNone(gz, scope, node, struct_init, ty_inst, .struct_init_anon);1753 const struct_ty_inst = try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);
1754 _ = try gz.addUnNode(.validate_struct_init_ty, struct_ty_inst, node);
1755 const result = try structInitExprRlTy(gz, scope, node, struct_init, struct_ty_inst, .struct_init);
1752 return rvalue(gz, ri, result, node);1756 return rvalue(gz, ri, result, node);
1753 }1757 }
1754 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1758 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
...@@ -2565,6 +2569,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2565,6 +2569,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2565 .array_type_sentinel,2569 .array_type_sentinel,
2566 .elem_type_index,2570 .elem_type_index,
2567 .elem_type,2571 .elem_type,
2572 .vector_elem_type,
2568 .vector_type,2573 .vector_type,
2569 .indexable_ptr_len,2574 .indexable_ptr_len,
2570 .anyframe_type,2575 .anyframe_type,
...@@ -2743,6 +2748,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2743,6 +2748,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2743 .for_len,2748 .for_len,
2744 .@"try",2749 .@"try",
2745 .try_ptr,2750 .try_ptr,
2751 .opt_eu_base_ty,
2746 => break :b false,2752 => break :b false,
27472753
2748 .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {2754 .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {
...@@ -8314,7 +8320,10 @@ fn builtinCall(...@@ -8314,7 +8320,10 @@ fn builtinCall(
8314 local_val.used = ident_token;8320 local_val.used = ident_token;
8315 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{8321 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
8316 .operand = local_val.inst,8322 .operand = local_val.inst,
8317 .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]),8323 // TODO: the result location here should be `.{ .coerced_ty = .export_options_type }`, but
8324 // that currently hits assertions in Sema due to type resolution issues.
8325 // See #16603
8326 .options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]),
8318 });8327 });
8319 return rvalue(gz, ri, .void_value, node);8328 return rvalue(gz, ri, .void_value, node);
8320 }8329 }
...@@ -8329,7 +8338,10 @@ fn builtinCall(...@@ -8329,7 +8338,10 @@ fn builtinCall(
8329 const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);8338 const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);
8330 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{8339 _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
8331 .operand = loaded,8340 .operand = loaded,
8332 .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]),8341 // TODO: the result location here should be `.{ .coerced_ty = .export_options_type }`, but
8342 // that currently hits assertions in Sema due to type resolution issues.
8343 // See #16603
8344 .options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]),
8333 });8345 });
8334 return rvalue(gz, ri, .void_value, node);8346 return rvalue(gz, ri, .void_value, node);
8335 }8347 }
...@@ -8363,7 +8375,10 @@ fn builtinCall(...@@ -8363,7 +8375,10 @@ fn builtinCall(
8363 },8375 },
8364 else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),8376 else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),
8365 }8377 }
8366 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .export_options_type } }, params[1]);8378 // TODO: the result location here should be `.{ .coerced_ty = .export_options_type }`, but
8379 // that currently hits assertions in Sema due to type resolution issues.
8380 // See #16603
8381 const options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
8367 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{8382 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
8368 .namespace = namespace,8383 .namespace = namespace,
8369 .decl_name = decl_name,8384 .decl_name = decl_name,
...@@ -8373,7 +8388,10 @@ fn builtinCall(...@@ -8373,7 +8388,10 @@ fn builtinCall(
8373 },8388 },
8374 .@"extern" => {8389 .@"extern" => {
8375 const type_inst = try typeExpr(gz, scope, params[0]);8390 const type_inst = try typeExpr(gz, scope, params[0]);
8376 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .extern_options_type } }, params[1]);8391 // TODO: the result location here should be `.{ .coerced_ty = .extern_options_type }`, but
8392 // that currently hits assertions in Sema due to type resolution issues.
8393 // See #16603
8394 const options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
8377 const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{8395 const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
8378 .node = gz.nodeIndexToRelative(node),8396 .node = gz.nodeIndexToRelative(node),
8379 .lhs = type_inst,8397 .lhs = type_inst,
...@@ -8477,7 +8495,10 @@ fn builtinCall(...@@ -8477,7 +8495,10 @@ fn builtinCall(
8477 // zig fmt: on8495 // zig fmt: on
84788496
8479 .Type => {8497 .Type => {
8480 const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .type_info_type } }, params[0]);8498 // TODO: the result location here should be `.{ .coerced_ty = .type_info_type }`, but
8499 // that currently hits assertions in Sema due to type resolution issues.
8500 // See #16603
8501 const operand = try expr(gz, scope, .{ .rl = .none }, params[0]);
84818502
8482 const gpa = gz.astgen.gpa;8503 const gpa = gz.astgen.gpa;
84838504
...@@ -8604,13 +8625,7 @@ fn builtinCall(...@@ -8604,13 +8625,7 @@ fn builtinCall(
86048625
8605 .splat => {8626 .splat => {
8606 const result_type = try ri.rl.resultType(gz, node, "@splat");8627 const result_type = try ri.rl.resultType(gz, node, "@splat");
8607 const elem_type = try gz.add(.{8628 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
8608 .tag = .elem_type_index,
8609 .data = .{ .bin = .{
8610 .lhs = result_type,
8611 .rhs = @as(Zir.Inst.Ref, @enumFromInt(0)),
8612 } },
8613 });
8614 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);8629 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
8615 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{8630 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
8616 .lhs = result_type,8631 .lhs = result_type,
...@@ -8755,7 +8770,10 @@ fn builtinCall(...@@ -8755,7 +8770,10 @@ fn builtinCall(
8755 },8770 },
8756 .prefetch => {8771 .prefetch => {
8757 const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);8772 const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);
8758 const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .prefetch_options_type } }, params[1]);8773 // TODO: the result location here should be `.{ .coerced_ty = .preftech_options_type }`, but
8774 // that currently hits assertions in Sema due to type resolution issues.
8775 // See #16603
8776 const options = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
8759 _ = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{8777 _ = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
8760 .node = gz.nodeIndexToRelative(node),8778 .node = gz.nodeIndexToRelative(node),
8761 .lhs = ptr,8779 .lhs = ptr,
src/Module.zig-29
...@@ -5938,35 +5938,6 @@ pub fn paramSrc(...@@ -5938,35 +5938,6 @@ pub fn paramSrc(
5938 unreachable;5938 unreachable;
5939}5939}
59405940
5941pub fn argSrc(
5942 mod: *Module,
5943 call_node_offset: i32,
5944 decl: *Decl,
5945 start_arg_i: usize,
5946 bound_arg_src: ?LazySrcLoc,
5947) LazySrcLoc {
5948 @setCold(true);
5949 const gpa = mod.gpa;
5950 if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;
5951 const arg_i = start_arg_i - @intFromBool(bound_arg_src != null);
5952 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
5953 // In this case we emit a warning + a less precise source location.
5954 log.warn("unable to load {s}: {s}", .{
5955 decl.getFileScope(mod).sub_file_path, @errorName(err),
5956 });
5957 return LazySrcLoc.nodeOffset(0);
5958 };
5959 const node = decl.relativeToNodeIndex(call_node_offset);
5960 var args: [1]Ast.Node.Index = undefined;
5961 const call_full = tree.fullCall(&args, node) orelse {
5962 assert(tree.nodes.items(.tag)[node] == .builtin_call);
5963 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
5964 const call_args_offset = decl.nodeIndexToRelative(call_args_node);
5965 return mod.initSrc(call_args_offset, decl, arg_i);
5966 };
5967 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(call_full.ast.params[arg_i]));
5968}
5969
5970pub fn initSrc(5941pub fn initSrc(
5971 mod: *Module,5942 mod: *Module,
5972 init_node_offset: i32,5943 init_node_offset: i32,
src/Sema.zig+693-437
...@@ -70,7 +70,6 @@ generic_owner: InternPool.Index = .none,...@@ -70,7 +70,6 @@ generic_owner: InternPool.Index = .none,
70/// instantiation can point back to the instantiation site in addition to the70/// instantiation can point back to the instantiation site in addition to the
71/// declaration site.71/// declaration site.
72generic_call_src: LazySrcLoc = .unneeded,72generic_call_src: LazySrcLoc = .unneeded,
73generic_bound_arg_src: ?LazySrcLoc = null,
74/// Corresponds to `generic_call_src`.73/// Corresponds to `generic_call_src`.
75generic_call_decl: Decl.OptionalIndex = .none,74generic_call_decl: Decl.OptionalIndex = .none,
76/// The key is types that must be fully resolved prior to machine code75/// The key is types that must be fully resolved prior to machine code
...@@ -1022,6 +1021,7 @@ fn analyzeBodyInner(...@@ -1022,6 +1021,7 @@ fn analyzeBodyInner(
1022 .elem_val_node => try sema.zirElemValNode(block, inst),1021 .elem_val_node => try sema.zirElemValNode(block, inst),
1023 .elem_type_index => try sema.zirElemTypeIndex(block, inst),1022 .elem_type_index => try sema.zirElemTypeIndex(block, inst),
1024 .elem_type => try sema.zirElemType(block, inst),1023 .elem_type => try sema.zirElemType(block, inst),
1024 .vector_elem_type => try sema.zirVectorElemType(block, inst),
1025 .enum_literal => try sema.zirEnumLiteral(block, inst),1025 .enum_literal => try sema.zirEnumLiteral(block, inst),
1026 .int_from_enum => try sema.zirIntFromEnum(block, inst),1026 .int_from_enum => try sema.zirIntFromEnum(block, inst),
1027 .enum_from_int => try sema.zirEnumFromInt(block, inst),1027 .enum_from_int => try sema.zirEnumFromInt(block, inst),
...@@ -1125,6 +1125,7 @@ fn analyzeBodyInner(...@@ -1125,6 +1125,7 @@ fn analyzeBodyInner(
1125 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),1125 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),
1126 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),1126 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),
1127 .for_len => try sema.zirForLen(block, inst),1127 .for_len => try sema.zirForLen(block, inst),
1128 .opt_eu_base_ty => try sema.zirOptEuBaseTy(block, inst),
11281129
1129 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),1130 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),
1130 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),1131 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),
...@@ -1359,12 +1360,12 @@ fn analyzeBodyInner(...@@ -1359,12 +1360,12 @@ fn analyzeBodyInner(
1359 continue;1360 continue;
1360 },1361 },
1361 .validate_array_init_ty => {1362 .validate_array_init_ty => {
1362 try sema.validateArrayInitTy(block, inst);1363 try sema.zirValidateArrayInitTy(block, inst);
1363 i += 1;1364 i += 1;
1364 continue;1365 continue;
1365 },1366 },
1366 .validate_struct_init_ty => {1367 .validate_struct_init_ty => {
1367 try sema.validateStructInitTy(block, inst);1368 try sema.zirValidateStructInitTy(block, inst);
1368 i += 1;1369 i += 1;
1369 continue;1370 continue;
1370 },1371 },
...@@ -1399,22 +1400,22 @@ fn analyzeBodyInner(...@@ -1399,22 +1400,22 @@ fn analyzeBodyInner(
1399 continue;1400 continue;
1400 },1401 },
1401 .param => {1402 .param => {
1402 try sema.zirParam(block, inst, i, false);1403 try sema.zirParam(block, inst, false);
1403 i += 1;1404 i += 1;
1404 continue;1405 continue;
1405 },1406 },
1406 .param_comptime => {1407 .param_comptime => {
1407 try sema.zirParam(block, inst, i, true);1408 try sema.zirParam(block, inst, true);
1408 i += 1;1409 i += 1;
1409 continue;1410 continue;
1410 },1411 },
1411 .param_anytype => {1412 .param_anytype => {
1412 try sema.zirParamAnytype(block, inst, i, false);1413 try sema.zirParamAnytype(block, inst, false);
1413 i += 1;1414 i += 1;
1414 continue;1415 continue;
1415 },1416 },
1416 .param_anytype_comptime => {1417 .param_anytype_comptime => {
1417 try sema.zirParamAnytype(block, inst, i, true);1418 try sema.zirParamAnytype(block, inst, true);
1418 i += 1;1419 i += 1;
1419 continue;1420 continue;
1420 },1421 },
...@@ -4312,7 +4313,31 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4312,7 +4313,31 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4312 return len;4313 return len;
4313}4314}
43144315
4315fn validateArrayInitTy(4316fn zirOptEuBaseTy(
4317 sema: *Sema,
4318 block: *Block,
4319 inst: Zir.Inst.Index,
4320) CompileError!Air.Inst.Ref {
4321 const mod = sema.mod;
4322 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4323 var ty = sema.resolveType(block, .unneeded, inst_data.operand) catch |err| switch (err) {
4324 // Since this is a ZIR instruction that returns a type, encountering
4325 // generic poison should not result in a failed compilation, but the
4326 // generic poison type. This prevents unnecessary failures when
4327 // constructing types at compile-time.
4328 error.GenericPoison => return .generic_poison_type,
4329 else => |e| return e,
4330 };
4331 while (true) {
4332 switch (ty.zigTypeTag(mod)) {
4333 .Optional => ty = ty.optionalChild(mod),
4334 .ErrorUnion => ty = ty.errorUnionPayload(mod),
4335 else => return sema.addType(ty),
4336 }
4337 }
4338}
4339
4340fn zirValidateArrayInitTy(
4316 sema: *Sema,4341 sema: *Sema,
4317 block: *Block,4342 block: *Block,
4318 inst: Zir.Inst.Index,4343 inst: Zir.Inst.Index,
...@@ -4322,7 +4347,11 @@ fn validateArrayInitTy(...@@ -4322,7 +4347,11 @@ fn validateArrayInitTy(
4322 const src = inst_data.src();4347 const src = inst_data.src();
4323 const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node };4348 const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node };
4324 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;4349 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
4325 const ty = try sema.resolveType(block, ty_src, extra.ty);4350 const ty = sema.resolveType(block, ty_src, extra.ty) catch |err| switch (err) {
4351 // It's okay for the type to be unknown: this will result in an anonymous array init.
4352 error.GenericPoison => return,
4353 else => |e| return e,
4354 };
43264355
4327 switch (ty.zigTypeTag(mod)) {4356 switch (ty.zigTypeTag(mod)) {
4328 .Array => {4357 .Array => {
...@@ -4358,7 +4387,7 @@ fn validateArrayInitTy(...@@ -4358,7 +4387,7 @@ fn validateArrayInitTy(
4358 return sema.failWithArrayInitNotSupported(block, ty_src, ty);4387 return sema.failWithArrayInitNotSupported(block, ty_src, ty);
4359}4388}
43604389
4361fn validateStructInitTy(4390fn zirValidateStructInitTy(
4362 sema: *Sema,4391 sema: *Sema,
4363 block: *Block,4392 block: *Block,
4364 inst: Zir.Inst.Index,4393 inst: Zir.Inst.Index,
...@@ -4366,7 +4395,11 @@ fn validateStructInitTy(...@@ -4366,7 +4395,11 @@ fn validateStructInitTy(
4366 const mod = sema.mod;4395 const mod = sema.mod;
4367 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4396 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4368 const src = inst_data.src();4397 const src = inst_data.src();
4369 const ty = try sema.resolveType(block, src, inst_data.operand);4398 const ty = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {
4399 // It's okay for the type to be unknown: this will result in an anonymous struct init.
4400 error.GenericPoison => return,
4401 else => |e| return e,
4402 };
43704403
4371 switch (ty.zigTypeTag(mod)) {4404 switch (ty.zigTypeTag(mod)) {
4372 .Struct, .Union => return,4405 .Struct, .Union => return,
...@@ -6502,7 +6535,6 @@ fn zirCall(...@@ -6502,7 +6535,6 @@ fn zirCall(
6502 defer tracy.end();6535 defer tracy.end();
65036536
6504 const mod = sema.mod;6537 const mod = sema.mod;
6505 const ip = &mod.intern_pool;
6506 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6538 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6507 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };6539 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
6508 const call_src = inst_data.src();6540 const call_src = inst_data.src();
...@@ -6526,96 +6558,62 @@ fn zirCall(...@@ -6526,96 +6558,62 @@ fn zirCall(
6526 break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src);6558 break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src);
6527 },6559 },
6528 };6560 };
6529 var resolved_args: []Air.Inst.Ref = undefined;6561 const func: Air.Inst.Ref = switch (callee) {
6530 var bound_arg_src: ?LazySrcLoc = null;6562 .direct => |func_inst| func_inst,
6531 var func: Air.Inst.Ref = undefined;6563 .method => |method| method.func_inst,
6532 var arg_index: u32 = 0;6564 };
6533 switch (callee) {
6534 .direct => |func_inst| {
6535 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len);
6536 func = func_inst;
6537 },
6538 .method => |method| {
6539 resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1);
6540 func = method.func_inst;
6541 resolved_args[0] = method.arg0_inst;
6542 arg_index += 1;
6543 bound_arg_src = callee_src;
6544 },
6545 }
65466565
6547 const callee_ty = sema.typeOf(func);6566 const callee_ty = sema.typeOf(func);
6548 const total_args = args_len + @intFromBool(bound_arg_src != null);6567 const total_args = args_len + @intFromBool(callee == .method);
6549 const func_ty = try sema.checkCallArgumentCount(block, func, callee_src, callee_ty, total_args, bound_arg_src != null);6568 const func_ty = try sema.checkCallArgumentCount(block, func, callee_src, callee_ty, total_args, callee == .method);
6550
6551 const args_body = sema.code.extra[extra.end..];
65526569
6553 var input_is_error = false;6570 // The block index before the call, so we can potentially insert an error trace save here later.
6554 const block_index: Air.Inst.Index = @intCast(block.instructions.items.len);6571 const block_index: Air.Inst.Index = @intCast(block.instructions.items.len);
65556572
6556 const func_ty_info = mod.typeToFunc(func_ty).?;6573 // This will be set by `analyzeCall` to indicate whether any parameter was an error (making the
6557 const fn_params_len = func_ty_info.param_types.len;6574 // error trace potentially dirty).
6558 const parent_comptime = block.is_comptime;6575 var input_is_error = false;
6559 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
6560 var extra_index: usize = 0;
6561 var arg_start: u32 = args_len;
6562 while (extra_index < args_len) : ({
6563 extra_index += 1;
6564 arg_index += 1;
6565 }) {
6566 const arg_end = sema.code.extra[extra.end + extra_index];
6567 defer arg_start = arg_end;
6568
6569 // Generate args to comptime params in comptime block.
6570 defer block.is_comptime = parent_comptime;
6571 if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) {
6572 block.is_comptime = true;
6573 // TODO set comptime_reason
6574 }
6575
6576 sema.inst_map.putAssumeCapacity(inst, inst: {
6577 if (arg_index >= fn_params_len)
6578 break :inst Air.Inst.Ref.var_args_param_type;
65796576
6580 if (func_ty_info.param_types.get(ip)[arg_index] == .generic_poison_type)6577 const args_info: CallArgsInfo = .{ .zir_call = .{
6581 break :inst Air.Inst.Ref.generic_poison_type;6578 .bound_arg = switch (callee) {
6579 .direct => .none,
6580 .method => |method| method.arg0_inst,
6581 },
6582 .bound_arg_src = callee_src,
6583 .call_inst = inst,
6584 .call_node_offset = inst_data.src_node,
6585 .num_args = args_len,
6586 .args_body = sema.code.extra[extra.end..],
6587 .any_arg_is_error = &input_is_error,
6588 } };
65826589
6583 break :inst try sema.addType(func_ty_info.param_types.get(ip)[arg_index].toType());6590 // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction.
6584 });6591 const call_dbg_node = inst - 1;
6592 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
65856593
6586 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
6587 const resolved_ty = sema.typeOf(resolved);
6588 if (resolved_ty.zigTypeTag(mod) == .NoReturn) {
6589 return resolved;
6590 }
6591 if (resolved_ty.isError(mod)) {
6592 input_is_error = true;
6593 }
6594 resolved_args[arg_index] = resolved;
6595 }
6596 if (sema.owner_func_index == .none or6594 if (sema.owner_func_index == .none or
6597 !ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn)6595 !mod.intern_pool.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn)
6598 {6596 {
6599 input_is_error = false; // input was an error type, but no errorable fn's were actually called6597 // No errorable fn actually called; we have no error return trace
6598 input_is_error = false;
6600 }6599 }
66016600
6602 // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction.
6603 const call_dbg_node = inst - 1;
6604
6605 if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and6601 if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and
6606 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))6602 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))
6607 {6603 {
6608 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
6609 break :b try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node, .call);
6610 };
6611
6612 const return_ty = sema.typeOf(call_inst);6604 const return_ty = sema.typeOf(call_inst);
6613 if (modifier != .always_tail and return_ty.isNoReturn(mod))6605 if (modifier != .always_tail and return_ty.isNoReturn(mod))
6614 return call_inst; // call to "fn(...) noreturn", don't pop6606 return call_inst; // call to "fn(...) noreturn", don't pop
66156607
6608 // TODO: we don't fix up the error trace for always_tail correctly, we should be doing it
6609 // *before* the recursive call. This will be a bit tricky to do and probably requires
6610 // moving this logic into analyzeCall. But that's probably a good idea anyway.
6611 if (modifier == .always_tail)
6612 return call_inst;
6613
6616 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only6614 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
6617 // need to clean-up our own trace if we were passed to a non-error-handling expression.6615 // need to clean-up our own trace if we were passed to a non-error-handling expression.
6618 if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError(mod))) {6616 if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) {
6619 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");6617 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
6620 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);6618 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
6621 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index");6619 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index");
...@@ -6635,12 +6633,9 @@ fn zirCall(...@@ -6635,12 +6633,9 @@ fn zirCall(
6635 try sema.popErrorReturnTrace(block, call_src, operand, save_inst);6633 try sema.popErrorReturnTrace(block, call_src, operand, save_inst);
6636 }6634 }
66376635
6638 if (modifier == .always_tail) // Perform the call *after* the restore, so that a tail call is possible.
6639 return sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node, .call);
6640
6641 return call_inst;6636 return call_inst;
6642 } else {6637 } else {
6643 return sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node, .call);6638 return call_inst;
6644 }6639 }
6645}6640}
66466641
...@@ -6747,7 +6742,19 @@ fn callBuiltin(...@@ -6747,7 +6742,19 @@ fn callBuiltin(
6747 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {6742 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {
6748 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });6743 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });
6749 }6744 }
6750 _ = try sema.analyzeCall(block, builtin_fn, func_ty, call_src, call_src, modifier, false, args, null, null, operation);6745
6746 _ = try sema.analyzeCall(
6747 block,
6748 builtin_fn,
6749 func_ty,
6750 call_src,
6751 call_src,
6752 modifier,
6753 false,
6754 .{ .resolved = .{ .src = call_src, .args = args } },
6755 null,
6756 operation,
6757 );
6751}6758}
67526759
6753const CallOperation = enum {6760const CallOperation = enum {
...@@ -6758,6 +6765,251 @@ const CallOperation = enum {...@@ -6758,6 +6765,251 @@ const CallOperation = enum {
6758 @"error return",6765 @"error return",
6759};6766};
67606767
6768const CallArgsInfo = union(enum) {
6769 /// The full list of resolved (but uncoerced) arguments is known ahead of time.
6770 resolved: struct {
6771 src: LazySrcLoc,
6772 args: []const Air.Inst.Ref,
6773 },
6774
6775 /// The list of resolved (but uncoerced) arguments is known ahead of time, but
6776 /// originated from a usage of the @call builtin at the given node offset.
6777 call_builtin: struct {
6778 call_node_offset: i32,
6779 args: []const Air.Inst.Ref,
6780 },
6781
6782 /// This call corresponds to a ZIR call instruction. The arguments have not yet been
6783 /// resolved. They must be resolved by `analyzeCall` so that argument resolution and
6784 /// generic instantiation may be interleaved. This is required for RLS to work on
6785 /// generic parameters.
6786 zir_call: struct {
6787 /// This may be `none`, in which case it is ignored. Otherwise, it is the
6788 /// already-resolved value of the first argument, from method call syntax.
6789 bound_arg: Air.Inst.Ref,
6790 /// The source location of `bound_arg` if it is not `null`. Otherwise `undefined`.
6791 bound_arg_src: LazySrcLoc,
6792 /// The ZIR call instruction. The parameter type is placed at this index while
6793 /// analyzing arguments.
6794 call_inst: Zir.Inst.Index,
6795 /// The node offset of `call_inst`.
6796 call_node_offset: i32,
6797 /// The number of arguments to this call, not including `bound_arg`.
6798 num_args: u32,
6799 /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it
6800 /// is not `none`). Format is precisely the same as trailing data of ZIR `call`.
6801 args_body: []const Zir.Inst.Index,
6802 /// This bool will be set to true if any argument evaluated turns out to have an error set or error union type.
6803 /// This is used by the caller to restore the error return trace when necessary.
6804 any_arg_is_error: *bool,
6805 },
6806
6807 fn count(cai: CallArgsInfo) usize {
6808 return switch (cai) {
6809 inline .resolved, .call_builtin => |resolved| resolved.args.len,
6810 .zir_call => |zir_call| zir_call.num_args + @intFromBool(zir_call.bound_arg != .none),
6811 };
6812 }
6813
6814 fn argSrc(cai: CallArgsInfo, block: *Block, arg_index: usize) LazySrcLoc {
6815 return switch (cai) {
6816 .resolved => |resolved| resolved.src,
6817 .call_builtin => |call_builtin| .{ .call_arg = .{
6818 .decl = block.src_decl,
6819 .call_node_offset = call_builtin.call_node_offset,
6820 .arg_index = @intCast(arg_index),
6821 } },
6822 .zir_call => |zir_call| if (arg_index == 0 and zir_call.bound_arg != .none) {
6823 return zir_call.bound_arg_src;
6824 } else .{ .call_arg = .{
6825 .decl = block.src_decl,
6826 .call_node_offset = zir_call.call_node_offset,
6827 .arg_index = @intCast(arg_index - @intFromBool(zir_call.bound_arg != .none)),
6828 } },
6829 };
6830 }
6831
6832 /// Analyzes the arg at `arg_index` and coerces it to `param_ty`.
6833 /// `param_ty` may be `generic_poison` or `var_args_param`.
6834 /// `func_ty_info` may be the type before instantiation, even if a generic
6835 /// instantiation has been partially completed.
6836 fn analyzeArg(
6837 cai: CallArgsInfo,
6838 sema: *Sema,
6839 block: *Block,
6840 arg_index: usize,
6841 param_ty: Type,
6842 func_ty_info: InternPool.Key.FuncType,
6843 func_inst: Air.Inst.Ref,
6844 ) CompileError!Air.Inst.Ref {
6845 const mod = sema.mod;
6846 const param_count = func_ty_info.param_types.len;
6847 switch (param_ty.toIntern()) {
6848 .generic_poison_type, .var_args_param_type => {},
6849 else => try sema.queueFullTypeResolution(param_ty),
6850 }
6851 const uncoerced_arg: Air.Inst.Ref = switch (cai) {
6852 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],
6853 .zir_call => |zir_call| arg_val: {
6854 const has_bound_arg = zir_call.bound_arg != .none;
6855 if (arg_index == 0 and has_bound_arg) {
6856 break :arg_val zir_call.bound_arg;
6857 }
6858 const real_arg_idx = arg_index - @intFromBool(has_bound_arg);
6859
6860 const arg_body = if (real_arg_idx == 0) blk: {
6861 const start = zir_call.num_args;
6862 const end = zir_call.args_body[0];
6863 break :blk zir_call.args_body[start..end];
6864 } else blk: {
6865 const start = zir_call.args_body[real_arg_idx - 1];
6866 const end = zir_call.args_body[real_arg_idx];
6867 break :blk zir_call.args_body[start..end];
6868 };
6869
6870 // Generate args to comptime params in comptime block
6871 const parent_comptime = block.is_comptime;
6872 defer block.is_comptime = parent_comptime;
6873 // Note that we are indexing into parameters, not arguments, so use `arg_index` instead of `real_arg_idx`
6874 if (arg_index < @min(param_count, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) {
6875 block.is_comptime = true;
6876 // TODO set comptime_reason
6877 }
6878 // Give the arg its result type
6879 sema.inst_map.putAssumeCapacity(zir_call.call_inst, try sema.addType(param_ty));
6880 // Resolve the arg!
6881 const uncoerced_arg = try sema.resolveBody(block, arg_body, zir_call.call_inst);
6882
6883 if (sema.typeOf(uncoerced_arg).zigTypeTag(mod) == .NoReturn) {
6884 // This terminates resolution of arguments. The caller should
6885 // propagate this.
6886 return uncoerced_arg;
6887 }
6888
6889 if (sema.typeOf(uncoerced_arg).isError(mod)) {
6890 zir_call.any_arg_is_error.* = true;
6891 }
6892
6893 break :arg_val uncoerced_arg;
6894 },
6895 };
6896 switch (param_ty.toIntern()) {
6897 .generic_poison_type => return uncoerced_arg,
6898 .var_args_param_type => return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index)),
6899 else => return sema.coerceExtra(
6900 block,
6901 param_ty,
6902 uncoerced_arg,
6903 cai.argSrc(block, arg_index),
6904 .{ .param_src = .{
6905 .func_inst = func_inst,
6906 .param_i = @intCast(arg_index),
6907 } },
6908 ) catch |err| switch (err) {
6909 error.NotCoercible => unreachable,
6910 else => |e| return e,
6911 },
6912 }
6913 }
6914};
6915
6916/// While performing an inline call, we need to switch between two Sema states a few times: the
6917/// state for the caller (with the callee's `code`, `fn_ret_ty`, etc), and the state for the callee.
6918/// These cannot be two separate Sema instances as they must share AIR.
6919/// Therefore, this struct acts as a helper to switch between the two.
6920/// This switching is required during argument evaluation, where function argument analysis must be
6921/// interleaved with resolving generic parameter types.
6922const InlineCallSema = struct {
6923 sema: *Sema,
6924 cur: enum {
6925 caller,
6926 callee,
6927 },
6928
6929 other_code: Zir,
6930 other_func_index: InternPool.Index,
6931 other_fn_ret_ty: Type,
6932 other_fn_ret_ty_ies: ?*InferredErrorSet,
6933 other_inst_map: InstMap,
6934 other_error_return_trace_index_on_fn_entry: Air.Inst.Ref,
6935 other_generic_owner: InternPool.Index,
6936 other_generic_call_src: LazySrcLoc,
6937 other_generic_call_decl: Decl.OptionalIndex,
6938
6939 /// Sema should currently be set up for the caller (i.e. unchanged yet). This init will not
6940 /// change that. The other parameters contain data for the callee Sema. The other modified
6941 /// Sema fields are all initialized to default values for the callee.
6942 /// Must call deinit on the result.
6943 fn init(
6944 sema: *Sema,
6945 callee_code: Zir,
6946 callee_func_index: InternPool.Index,
6947 callee_error_return_trace_index_on_fn_entry: Air.Inst.Ref,
6948 ) InlineCallSema {
6949 return .{
6950 .sema = sema,
6951 .cur = .caller,
6952 .other_code = callee_code,
6953 .other_func_index = callee_func_index,
6954 .other_fn_ret_ty = Type.void,
6955 .other_fn_ret_ty_ies = null,
6956 .other_inst_map = .{},
6957 .other_error_return_trace_index_on_fn_entry = callee_error_return_trace_index_on_fn_entry,
6958 .other_generic_owner = .none,
6959 .other_generic_call_src = .unneeded,
6960 .other_generic_call_decl = .none,
6961 };
6962 }
6963
6964 /// Switch back to the caller Sema if necessary and free all temporary state of the callee Sema.
6965 fn deinit(ics: *InlineCallSema) void {
6966 switch (ics.cur) {
6967 .caller => {},
6968 .callee => ics.swap(),
6969 }
6970 // Callee Sema owns the inst_map memory
6971 ics.other_inst_map.deinit(ics.sema.gpa);
6972 ics.* = undefined;
6973 }
6974
6975 /// Returns a Sema instance suitable for usage from the caller context.
6976 fn caller(ics: *InlineCallSema) *Sema {
6977 switch (ics.cur) {
6978 .caller => {},
6979 .callee => ics.swap(),
6980 }
6981 return ics.sema;
6982 }
6983
6984 /// Returns a Sema instance suitable for usage from the callee context.
6985 fn callee(ics: *InlineCallSema) *Sema {
6986 switch (ics.cur) {
6987 .caller => ics.swap(),
6988 .callee => {},
6989 }
6990 return ics.sema;
6991 }
6992
6993 /// Internal use only. Swaps to the other Sema state.
6994 fn swap(ics: *InlineCallSema) void {
6995 ics.cur = switch (ics.cur) {
6996 .caller => .callee,
6997 .callee => .caller,
6998 };
6999 // zig fmt: off
7000 std.mem.swap(Zir, &ics.sema.code, &ics.other_code);
7001 std.mem.swap(InternPool.Index, &ics.sema.func_index, &ics.other_func_index);
7002 std.mem.swap(Type, &ics.sema.fn_ret_ty, &ics.other_fn_ret_ty);
7003 std.mem.swap(?*InferredErrorSet, &ics.sema.fn_ret_ty_ies, &ics.other_fn_ret_ty_ies);
7004 std.mem.swap(InstMap, &ics.sema.inst_map, &ics.other_inst_map);
7005 std.mem.swap(InternPool.Index, &ics.sema.generic_owner, &ics.other_generic_owner);
7006 std.mem.swap(LazySrcLoc, &ics.sema.generic_call_src, &ics.other_generic_call_src);
7007 std.mem.swap(Decl.OptionalIndex, &ics.sema.generic_call_decl, &ics.other_generic_call_decl);
7008 std.mem.swap(Air.Inst.Ref, &ics.sema.error_return_trace_index_on_fn_entry, &ics.other_error_return_trace_index_on_fn_entry);
7009 // zig fmt: on
7010 }
7011};
7012
6761fn analyzeCall(7013fn analyzeCall(
6762 sema: *Sema,7014 sema: *Sema,
6763 block: *Block,7015 block: *Block,
...@@ -6767,8 +7019,7 @@ fn analyzeCall(...@@ -6767,8 +7019,7 @@ fn analyzeCall(
6767 call_src: LazySrcLoc,7019 call_src: LazySrcLoc,
6768 modifier: std.builtin.CallModifier,7020 modifier: std.builtin.CallModifier,
6769 ensure_result_used: bool,7021 ensure_result_used: bool,
6770 uncasted_args: []const Air.Inst.Ref,7022 args_info: CallArgsInfo,
6771 bound_arg_src: ?LazySrcLoc,
6772 call_dbg_node: ?Zir.Inst.Index,7023 call_dbg_node: ?Zir.Inst.Index,
6773 operation: CallOperation,7024 operation: CallOperation,
6774) CompileError!Air.Inst.Ref {7025) CompileError!Air.Inst.Ref {
...@@ -6777,7 +7028,6 @@ fn analyzeCall(...@@ -6777,7 +7028,6 @@ fn analyzeCall(
67777028
6778 const callee_ty = sema.typeOf(func);7029 const callee_ty = sema.typeOf(func);
6779 const func_ty_info = mod.typeToFunc(func_ty).?;7030 const func_ty_info = mod.typeToFunc(func_ty).?;
6780 const fn_params_len = func_ty_info.param_types.len;
6781 const cc = func_ty_info.cc;7031 const cc = func_ty_info.cc;
6782 if (cc == .Naked) {7032 if (cc == .Naked) {
6783 const maybe_decl = try sema.funcDeclSrc(func);7033 const maybe_decl = try sema.funcDeclSrc(func);
...@@ -6862,9 +7112,8 @@ fn analyzeCall(...@@ -6862,9 +7112,8 @@ fn analyzeCall(
6862 func_src,7112 func_src,
6863 call_src,7113 call_src,
6864 ensure_result_used,7114 ensure_result_used,
6865 uncasted_args,7115 args_info,
6866 call_tag,7116 call_tag,
6867 bound_arg_src,
6868 call_dbg_node,7117 call_dbg_node,
6869 )) |some| {7118 )) |some| {
6870 return some;7119 return some;
...@@ -6939,31 +7188,23 @@ fn analyzeCall(...@@ -6939,31 +7188,23 @@ fn analyzeCall(
6939 .block_inst = block_inst,7188 .block_inst = block_inst,
6940 },7189 },
6941 };7190 };
6942 // In order to save a bit of stack space, directly modify Sema rather7191
6943 // than create a child one.
6944 const parent_zir = sema.code;
6945 const module_fn = mod.funcInfo(module_fn_index);7192 const module_fn = mod.funcInfo(module_fn_index);
6946 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);7193 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
6947 sema.code = fn_owner_decl.getFileScope(mod).zir;
6948 defer sema.code = parent_zir;
6949
6950 try mod.declareDeclDependencyType(sema.owner_decl_index, module_fn.owner_decl, .function_body);
69517194
6952 const parent_inst_map = sema.inst_map;7195 // We effectively want a child Sema here, but can't literally do that, because we need AIR
6953 sema.inst_map = .{};7196 // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in
6954 defer {7197 // scope, we should use its `caller`/`callee` methods rather than using `sema` directly
6955 sema.src = call_src;7198 // whenever performing an operation where the difference matters.
6956 sema.inst_map.deinit(gpa);7199 var ics = InlineCallSema.init(
6957 sema.inst_map = parent_inst_map;7200 sema,
6958 }7201 fn_owner_decl.getFileScope(mod).zir,
69597202 module_fn_index,
6960 const parent_func_index = sema.func_index;7203 block.error_return_trace_index,
6961 sema.func_index = module_fn_index;7204 );
6962 defer sema.func_index = parent_func_index;7205 defer ics.deinit();
69637206
6964 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;7207 try mod.declareDeclDependencyType(ics.callee().owner_decl_index, module_fn.owner_decl, .function_body);
6965 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
6966 defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index;
69677208
6968 var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope);7209 var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope);
6969 defer wip_captures.deinit();7210 defer wip_captures.deinit();
...@@ -7019,37 +7260,37 @@ fn analyzeCall(...@@ -7019,37 +7260,37 @@ fn analyzeCall(
7019 // the AIR instructions of the callsite. The callee could be a generic function7260 // the AIR instructions of the callsite. The callee could be a generic function
7020 // which means its parameter type expressions must be resolved in order and used7261 // which means its parameter type expressions must be resolved in order and used
7021 // to successively coerce the arguments.7262 // to successively coerce the arguments.
7022 const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);7263 const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst);
7023 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);7264 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
70247265
7025 var has_comptime_args = false;7266 var has_comptime_args = false;
7026 var arg_i: u32 = 0;7267 var arg_i: u32 = 0;
7027 for (fn_info.param_body) |inst| {7268 for (fn_info.param_body) |inst| {
7028 const arg_src: LazySrcLoc = if (arg_i == 0 and bound_arg_src != null)7269 const opt_noreturn_ref = try analyzeInlineCallArg(
7029 bound_arg_src.?7270 &ics,
7030 else
7031 .{ .call_arg = .{
7032 .decl = block.src_decl,
7033 .call_node_offset = call_src.node_offset.x,
7034 .arg_index = arg_i - @intFromBool(bound_arg_src != null),
7035 } };
7036 try sema.analyzeInlineCallArg(
7037 block,7271 block,
7038 &child_block,7272 &child_block,
7039 arg_src,
7040 inst,7273 inst,
7041 new_fn_info.param_types,7274 new_fn_info.param_types,
7042 &arg_i,7275 &arg_i,
7043 uncasted_args,7276 args_info,
7044 is_comptime_call,7277 is_comptime_call,
7045 &should_memoize,7278 &should_memoize,
7046 memoized_arg_values,7279 memoized_arg_values,
7047 func_ty_info.param_types,7280 func_ty_info,
7048 func,7281 func,
7049 &has_comptime_args,7282 &has_comptime_args,
7050 );7283 );
7284 if (opt_noreturn_ref) |ref| {
7285 // Analyzing this argument gave a ref of a noreturn type. Terminate argument analysis here.
7286 return ref;
7287 }
7051 }7288 }
70527289
7290 // From here, we only really need to use the callee Sema. Make it the active one, then we
7291 // can just use `sema` directly.
7292 _ = ics.callee();
7293
7053 if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure)7294 if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure)
7054 return error.AnalysisFail;7295 return error.AnalysisFail;
70557296
...@@ -7073,26 +7314,7 @@ fn analyzeCall(...@@ -7073,26 +7314,7 @@ fn analyzeCall(
7073 else7314 else
7074 try sema.resolveInst(fn_info.ret_ty_ref);7315 try sema.resolveInst(fn_info.ret_ty_ref);
7075 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };7316 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
7076 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);7317 sema.fn_ret_ty = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
7077 const parent_fn_ret_ty = sema.fn_ret_ty;
7078 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;
7079 const parent_generic_owner = sema.generic_owner;
7080 const parent_generic_call_src = sema.generic_call_src;
7081 const parent_generic_bound_arg_src = sema.generic_bound_arg_src;
7082 const parent_generic_call_decl = sema.generic_call_decl;
7083 sema.fn_ret_ty = bare_return_type;
7084 sema.fn_ret_ty_ies = null;
7085 sema.generic_owner = .none;
7086 sema.generic_call_src = .unneeded;
7087 sema.generic_bound_arg_src = null;
7088 sema.generic_call_decl = .none;
7089 defer sema.fn_ret_ty = parent_fn_ret_ty;
7090 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;
7091 defer sema.generic_owner = parent_generic_owner;
7092 defer sema.generic_call_src = parent_generic_call_src;
7093 defer sema.generic_bound_arg_src = parent_generic_bound_arg_src;
7094 defer sema.generic_call_decl = parent_generic_call_decl;
7095
7096 if (module_fn.analysis(ip).inferred_error_set) {7318 if (module_fn.analysis(ip).inferred_error_set) {
7097 // Create a fresh inferred error set type for inline/comptime calls.7319 // Create a fresh inferred error set type for inline/comptime calls.
7098 const ies = try sema.arena.create(InferredErrorSet);7320 const ies = try sema.arena.create(InferredErrorSet);
...@@ -7100,7 +7322,7 @@ fn analyzeCall(...@@ -7100,7 +7322,7 @@ fn analyzeCall(
7100 sema.fn_ret_ty_ies = ies;7322 sema.fn_ret_ty_ies = ies;
7101 sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{7323 sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{
7102 .error_set_type = .adhoc_inferred_error_set_type,7324 .error_set_type = .adhoc_inferred_error_set_type,
7103 .payload_type = bare_return_type.toIntern(),7325 .payload_type = sema.fn_ret_ty.toIntern(),
7104 } })).toType();7326 } })).toType();
7105 }7327 }
71067328
...@@ -7123,7 +7345,7 @@ fn analyzeCall(...@@ -7123,7 +7345,7 @@ fn analyzeCall(
7123 new_fn_info.return_type = sema.fn_ret_ty.toIntern();7345 new_fn_info.return_type = sema.fn_ret_ty.toIntern();
7124 const new_func_resolved_ty = try mod.funcType(new_fn_info);7346 const new_func_resolved_ty = try mod.funcType(new_fn_info);
7125 if (!is_comptime_call and !block.is_typeof) {7347 if (!is_comptime_call and !block.is_typeof) {
7126 try sema.emitDbgInline(block, parent_func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);7348 try sema.emitDbgInline(block, sema.func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
71277349
7128 const zir_tags = sema.code.instructions.items(.tag);7350 const zir_tags = sema.code.instructions.items(.tag);
7129 for (fn_info.param_body) |param| switch (zir_tags[param]) {7351 for (fn_info.param_body) |param| switch (zir_tags[param]) {
...@@ -7157,7 +7379,7 @@ fn analyzeCall(...@@ -7157,7 +7379,7 @@ fn analyzeCall(
7157 const err_msg = sema.err orelse return err;7379 const err_msg = sema.err orelse return err;
7158 if (mem.eql(u8, err_msg.msg, recursive_msg)) return err;7380 if (mem.eql(u8, err_msg.msg, recursive_msg)) return err;
7159 try sema.errNote(block, call_src, err_msg, "called from here", .{});7381 try sema.errNote(block, call_src, err_msg, "called from here", .{});
7160 err_msg.clearTrace(sema.gpa);7382 err_msg.clearTrace(gpa);
7161 return err;7383 return err;
7162 },7384 },
7163 else => |e| return e,7385 else => |e| return e,
...@@ -7171,8 +7393,8 @@ fn analyzeCall(...@@ -7171,8 +7393,8 @@ fn analyzeCall(
7171 try sema.emitDbgInline(7393 try sema.emitDbgInline(
7172 block,7394 block,
7173 module_fn_index,7395 module_fn_index,
7174 parent_func_index,7396 sema.func_index,
7175 mod.funcOwnerDeclPtr(parent_func_index).ty,7397 mod.funcOwnerDeclPtr(sema.func_index).ty,
7176 .dbg_inline_end,7398 .dbg_inline_end,
7177 );7399 );
7178 }7400 }
...@@ -7217,47 +7439,16 @@ fn analyzeCall(...@@ -7217,47 +7439,16 @@ fn analyzeCall(
7217 } else res: {7439 } else res: {
7218 assert(!func_ty_info.is_generic);7440 assert(!func_ty_info.is_generic);
72197441
7220 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);7442 const args = try sema.arena.alloc(Air.Inst.Ref, args_info.count());
7221 for (uncasted_args, 0..) |uncasted_arg, i| {7443 for (args, 0..) |*arg_out, arg_idx| {
7222 if (i < fn_params_len) {7444 // Non-generic, so param types are already resolved
7223 const opts: CoerceOpts = .{ .param_src = .{7445 const param_ty = if (arg_idx < func_ty_info.param_types.len) ty: {
7224 .func_inst = func,7446 break :ty func_ty_info.param_types.get(ip)[arg_idx].toType();
7225 .param_i = @intCast(i),7447 } else InternPool.Index.var_args_param_type.toType();
7226 } };7448 assert(!param_ty.isGenericPoison());
7227 const param_ty = func_ty_info.param_types.get(ip)[i].toType();7449 arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func);
7228 args[i] = sema.analyzeCallArg(7450 if (sema.typeOf(arg_out.*).zigTypeTag(mod) == .NoReturn) {
7229 block,7451 return arg_out.*;
7230 .unneeded,
7231 param_ty,
7232 uncasted_arg,
7233 opts,
7234 ) catch |err| switch (err) {
7235 error.NeededSourceLocation => {
7236 const decl = mod.declPtr(block.src_decl);
7237 _ = try sema.analyzeCallArg(
7238 block,
7239 mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src),
7240 param_ty,
7241 uncasted_arg,
7242 opts,
7243 );
7244 unreachable;
7245 },
7246 else => |e| return e,
7247 };
7248 } else {
7249 args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) {
7250 error.NeededSourceLocation => {
7251 const decl = mod.declPtr(block.src_decl);
7252 _ = try sema.coerceVarArgParam(
7253 block,
7254 uncasted_arg,
7255 mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src),
7256 );
7257 unreachable;
7258 },
7259 else => |e| return e,
7260 };
7261 }7452 }
7262 }7453 }
72637454
...@@ -7341,25 +7532,25 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -7341,25 +7532,25 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
7341 return Air.Inst.Ref.unreachable_value;7532 return Air.Inst.Ref.unreachable_value;
7342}7533}
73437534
7535/// Usually, returns null. If an argument was noreturn, returns that ref (which should become the call result).
7344fn analyzeInlineCallArg(7536fn analyzeInlineCallArg(
7345 sema: *Sema,7537 ics: *InlineCallSema,
7346 arg_block: *Block,7538 arg_block: *Block,
7347 param_block: *Block,7539 param_block: *Block,
7348 arg_src: LazySrcLoc,
7349 inst: Zir.Inst.Index,7540 inst: Zir.Inst.Index,
7350 new_param_types: []InternPool.Index,7541 new_param_types: []InternPool.Index,
7351 arg_i: *u32,7542 arg_i: *u32,
7352 uncasted_args: []const Air.Inst.Ref,7543 args_info: CallArgsInfo,
7353 is_comptime_call: bool,7544 is_comptime_call: bool,
7354 should_memoize: *bool,7545 should_memoize: *bool,
7355 memoized_arg_values: []InternPool.Index,7546 memoized_arg_values: []InternPool.Index,
7356 raw_param_types: InternPool.Index.Slice,7547 func_ty_info: InternPool.Key.FuncType,
7357 func_inst: Air.Inst.Ref,7548 func_inst: Air.Inst.Ref,
7358 has_comptime_args: *bool,7549 has_comptime_args: *bool,
7359) !void {7550) !?Air.Inst.Ref {
7360 const mod = sema.mod;7551 const mod = ics.sema.mod;
7361 const ip = &mod.intern_pool;7552 const ip = &mod.intern_pool;
7362 const zir_tags = sema.code.instructions.items(.tag);7553 const zir_tags = ics.callee().code.instructions.items(.tag);
7363 switch (zir_tags[inst]) {7554 switch (zir_tags[inst]) {
7364 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,7555 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
7365 else => {},7556 else => {},
...@@ -7368,39 +7559,36 @@ fn analyzeInlineCallArg(...@@ -7368,39 +7559,36 @@ fn analyzeInlineCallArg(
7368 .param, .param_comptime => {7559 .param, .param_comptime => {
7369 // Evaluate the parameter type expression now that previous ones have7560 // Evaluate the parameter type expression now that previous ones have
7370 // been mapped, and coerce the corresponding argument to it.7561 // been mapped, and coerce the corresponding argument to it.
7371 const pl_tok = sema.code.instructions.items(.data)[inst].pl_tok;7562 const pl_tok = ics.callee().code.instructions.items(.data)[inst].pl_tok;
7372 const param_src = pl_tok.src();7563 const param_src = pl_tok.src();
7373 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);7564 const extra = ics.callee().code.extraData(Zir.Inst.Param, pl_tok.payload_index);
7374 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];7565 const param_body = ics.callee().code.extra[extra.end..][0..extra.data.body_len];
7375 const param_ty = param_ty: {7566 const param_ty = param_ty: {
7376 const raw_param_ty = raw_param_types.get(ip)[arg_i.*];7567 const raw_param_ty = func_ty_info.param_types.get(ip)[arg_i.*];
7377 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;7568 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
7378 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);7569 const param_ty_inst = try ics.callee().resolveBody(param_block, param_body, inst);
7379 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);7570 const param_ty = try ics.callee().analyzeAsType(param_block, param_src, param_ty_inst);
7380 break :param_ty param_ty.toIntern();7571 break :param_ty param_ty.toIntern();
7381 };7572 };
7382 new_param_types[arg_i.*] = param_ty;7573 new_param_types[arg_i.*] = param_ty;
7383 const uncasted_arg = uncasted_args[arg_i.*];7574 const casted_arg = try args_info.analyzeArg(ics.caller(), arg_block, arg_i.*, param_ty.toType(), func_ty_info, func_inst);
7384 if (try sema.typeRequiresComptime(param_ty.toType())) {7575 if (ics.caller().typeOf(casted_arg).zigTypeTag(mod) == .NoReturn) {
7385 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {7576 return casted_arg;
7386 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7577 }
7578 const arg_src = args_info.argSrc(arg_block, arg_i.*);
7579 if (try ics.callee().typeRequiresComptime(param_ty.toType())) {
7580 _ = ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
7581 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(ics.caller(), ics.caller().err);
7387 return err;7582 return err;
7388 };7583 };
7389 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {7584 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {
7390 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7585 _ = try ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "parameter is comptime");
7391 }7586 }
7392 const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{
7393 .func_inst = func_inst,
7394 .param_i = @intCast(arg_i.*),
7395 } }) catch |err| switch (err) {
7396 error.NotCoercible => unreachable,
7397 else => |e| return e,
7398 };
73997587
7400 if (is_comptime_call) {7588 if (is_comptime_call) {
7401 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);7589 ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
7402 const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {7590 const arg_val = ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
7403 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7591 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(ics.caller(), ics.caller().err);
7404 return err;7592 return err;
7405 };7593 };
7406 switch (arg_val.toIntern()) {7594 switch (arg_val.toIntern()) {
...@@ -7414,14 +7602,14 @@ fn analyzeInlineCallArg(...@@ -7414,14 +7602,14 @@ fn analyzeInlineCallArg(
7414 // Needed so that lazy values do not trigger7602 // Needed so that lazy values do not trigger
7415 // assertion due to type not being resolved7603 // assertion due to type not being resolved
7416 // when the hash function is called.7604 // when the hash function is called.
7417 const resolved_arg_val = try sema.resolveLazyValue(arg_val);7605 const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val);
7418 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);7606 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);
7419 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(param_ty.toType(), mod);7607 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(param_ty.toType(), mod);
7420 } else {7608 } else {
7421 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);7609 ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
7422 }7610 }
74237611
7424 if (try sema.resolveMaybeUndefVal(casted_arg)) |_| {7612 if (try ics.caller().resolveMaybeUndefVal(casted_arg)) |_| {
7425 has_comptime_args.* = true;7613 has_comptime_args.* = true;
7426 }7614 }
74277615
...@@ -7429,13 +7617,17 @@ fn analyzeInlineCallArg(...@@ -7429,13 +7617,17 @@ fn analyzeInlineCallArg(
7429 },7617 },
7430 .param_anytype, .param_anytype_comptime => {7618 .param_anytype, .param_anytype_comptime => {
7431 // No coercion needed.7619 // No coercion needed.
7432 const uncasted_arg = uncasted_args[arg_i.*];7620 const uncasted_arg = try args_info.analyzeArg(ics.caller(), arg_block, arg_i.*, Type.generic_poison, func_ty_info, func_inst);
7433 new_param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();7621 if (ics.caller().typeOf(uncasted_arg).zigTypeTag(mod) == .NoReturn) {
7622 return uncasted_arg;
7623 }
7624 const arg_src = args_info.argSrc(arg_block, arg_i.*);
7625 new_param_types[arg_i.*] = ics.caller().typeOf(uncasted_arg).toIntern();
74347626
7435 if (is_comptime_call) {7627 if (is_comptime_call) {
7436 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);7628 ics.callee().inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
7437 const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {7629 const arg_val = ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
7438 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7630 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(ics.caller(), ics.caller().err);
7439 return err;7631 return err;
7440 };7632 };
7441 switch (arg_val.toIntern()) {7633 switch (arg_val.toIntern()) {
...@@ -7449,17 +7641,17 @@ fn analyzeInlineCallArg(...@@ -7449,17 +7641,17 @@ fn analyzeInlineCallArg(
7449 // Needed so that lazy values do not trigger7641 // Needed so that lazy values do not trigger
7450 // assertion due to type not being resolved7642 // assertion due to type not being resolved
7451 // when the hash function is called.7643 // when the hash function is called.
7452 const resolved_arg_val = try sema.resolveLazyValue(arg_val);7644 const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val);
7453 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);7645 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);
7454 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(sema.typeOf(uncasted_arg), mod);7646 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(ics.caller().typeOf(uncasted_arg), mod);
7455 } else {7647 } else {
7456 if (zir_tags[inst] == .param_anytype_comptime) {7648 if (zir_tags[inst] == .param_anytype_comptime) {
7457 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7649 _ = try ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
7458 }7650 }
7459 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);7651 ics.callee().inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
7460 }7652 }
74617653
7462 if (try sema.resolveMaybeUndefVal(uncasted_arg)) |_| {7654 if (try ics.caller().resolveMaybeUndefVal(uncasted_arg)) |_| {
7463 has_comptime_args.* = true;7655 has_comptime_args.* = true;
7464 }7656 }
74657657
...@@ -7467,6 +7659,8 @@ fn analyzeInlineCallArg(...@@ -7467,6 +7659,8 @@ fn analyzeInlineCallArg(
7467 },7659 },
7468 else => {},7660 else => {},
7469 }7661 }
7662
7663 return null;
7470}7664}
74717665
7472fn analyzeCallArg(7666fn analyzeCallArg(
...@@ -7491,9 +7685,8 @@ fn instantiateGenericCall(...@@ -7491,9 +7685,8 @@ fn instantiateGenericCall(
7491 func_src: LazySrcLoc,7685 func_src: LazySrcLoc,
7492 call_src: LazySrcLoc,7686 call_src: LazySrcLoc,
7493 ensure_result_used: bool,7687 ensure_result_used: bool,
7494 uncasted_args: []const Air.Inst.Ref,7688 args_info: CallArgsInfo,
7495 call_tag: Air.Inst.Tag,7689 call_tag: Air.Inst.Tag,
7496 bound_arg_src: ?LazySrcLoc,
7497 call_dbg_node: ?Zir.Inst.Index,7690 call_dbg_node: ?Zir.Inst.Index,
7498) CompileError!Air.Inst.Ref {7691) CompileError!Air.Inst.Ref {
7499 const mod = sema.mod;7692 const mod = sema.mod;
...@@ -7507,6 +7700,7 @@ fn instantiateGenericCall(...@@ -7507,6 +7700,7 @@ fn instantiateGenericCall(
7507 else => unreachable,7700 else => unreachable,
7508 };7701 };
7509 const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func;7702 const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func;
7703 const generic_owner_ty_info = mod.typeToFunc(generic_owner_func.ty.toType()).?;
75107704
7511 // Even though there may already be a generic instantiation corresponding7705 // Even though there may already be a generic instantiation corresponding
7512 // to this callsite, we must evaluate the expressions of the generic7706 // to this callsite, we must evaluate the expressions of the generic
...@@ -7522,9 +7716,13 @@ fn instantiateGenericCall(...@@ -7522,9 +7716,13 @@ fn instantiateGenericCall(
7522 const fn_zir = namespace.file_scope.zir;7716 const fn_zir = namespace.file_scope.zir;
7523 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst);7717 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst);
75247718
7525 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);7719 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
7526 @memset(comptime_args, .none);7720 @memset(comptime_args, .none);
75277721
7722 // We may overestimate the number of runtime args, but this will definitely be sufficient.
7723 const max_runtime_args = args_info.count() - @popCount(generic_owner_ty_info.comptime_bits);
7724 var runtime_args = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(sema.arena, max_runtime_args);
7725
7528 // Re-run the block that creates the function, with the comptime parameters7726 // Re-run the block that creates the function, with the comptime parameters
7529 // pre-populated inside `inst_map`. This causes `param_comptime` and7727 // pre-populated inside `inst_map`. This causes `param_comptime` and
7530 // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a7728 // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a
...@@ -7549,7 +7747,6 @@ fn instantiateGenericCall(...@@ -7549,7 +7747,6 @@ fn instantiateGenericCall(
7549 .comptime_args = comptime_args,7747 .comptime_args = comptime_args,
7550 .generic_owner = generic_owner,7748 .generic_owner = generic_owner,
7551 .generic_call_src = call_src,7749 .generic_call_src = call_src,
7552 .generic_bound_arg_src = bound_arg_src,
7553 .generic_call_decl = block.src_decl.toOptional(),7750 .generic_call_decl = block.src_decl.toOptional(),
7554 .branch_quota = sema.branch_quota,7751 .branch_quota = sema.branch_quota,
7555 .branch_count = sema.branch_count,7752 .branch_count = sema.branch_count,
...@@ -7574,30 +7771,145 @@ fn instantiateGenericCall(...@@ -7574,30 +7771,145 @@ fn instantiateGenericCall(
75747771
7575 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);7772 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
75767773
7577 for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| {7774 for (fn_info.param_body[0..args_info.count()], 0..) |param_inst, arg_index| {
7578 // `child_sema` will use a different `inst_map` which means we have to7775 const param_tag = fn_zir.instructions.items(.tag)[param_inst];
7579 // convert from parent-relative `Air.Inst.Ref` to child-relative here.7776
7580 // Constants are simple; runtime-known values need a new instruction.7777 const param_ty = switch (generic_owner_ty_info.param_types.get(ip)[arg_index]) {
7581 child_sema.inst_map.putAssumeCapacityNoClobber(inst, if (try sema.resolveMaybeUndefVal(arg)) |val|7778 else => |ty| ty.toType(), // parameter is not generic, so type is already resolved
7582 Air.internedToRef(val.toIntern())7779 .generic_poison_type => param_ty: {
7583 else7780 // We have every parameter before this one, so can resolve this parameter's type now.
7584 // We insert into the map an instruction which is runtime-known7781 // However, first check the param type, since it may be anytype.
7585 // but has the type of the argument.7782 switch (param_tag) {
7586 try child_block.addInst(.{7783 .param_anytype, .param_anytype_comptime => {
7784 // The parameter doesn't have a type.
7785 break :param_ty Type.generic_poison;
7786 },
7787 .param, .param_comptime => {
7788 // We now know every prior parameter, so can resolve this
7789 // parameter's type. The child sema has these types.
7790 const param_data = fn_zir.instructions.items(.data)[param_inst].pl_tok;
7791 const param_extra = fn_zir.extraData(Zir.Inst.Param, param_data.payload_index);
7792 const param_ty_body = fn_zir.extra[param_extra.end..][0..param_extra.data.body_len];
7793
7794 // Make sure any nested instructions don't clobber our work.
7795 const prev_params = child_block.params;
7796 const prev_no_partial_func_ty = child_sema.no_partial_func_ty;
7797 const prev_generic_owner = child_sema.generic_owner;
7798 const prev_generic_call_src = child_sema.generic_call_src;
7799 const prev_generic_call_decl = child_sema.generic_call_decl;
7800 child_block.params = .{};
7801 child_sema.no_partial_func_ty = true;
7802 child_sema.generic_owner = .none;
7803 child_sema.generic_call_src = .unneeded;
7804 child_sema.generic_call_decl = .none;
7805 defer {
7806 child_block.params = prev_params;
7807 child_sema.no_partial_func_ty = prev_no_partial_func_ty;
7808 child_sema.generic_owner = prev_generic_owner;
7809 child_sema.generic_call_src = prev_generic_call_src;
7810 child_sema.generic_call_decl = prev_generic_call_decl;
7811 }
7812
7813 const param_ty_inst = try child_sema.resolveBody(&child_block, param_ty_body, param_inst);
7814 break :param_ty try child_sema.analyzeAsType(&child_block, param_data.src(), param_ty_inst);
7815 },
7816 else => unreachable,
7817 }
7818 },
7819 };
7820 const arg_ref = try args_info.analyzeArg(sema, block, arg_index, param_ty, generic_owner_ty_info, func);
7821 const arg_ty = sema.typeOf(arg_ref);
7822 if (arg_ty.zigTypeTag(mod) == .NoReturn) {
7823 // This terminates argument analysis.
7824 return arg_ref;
7825 }
7826
7827 const arg_is_comptime = switch (param_tag) {
7828 .param_comptime, .param_anytype_comptime => true,
7829 .param, .param_anytype => try sema.typeRequiresComptime(arg_ty),
7830 else => unreachable,
7831 };
7832
7833 if (arg_is_comptime) {
7834 if (try sema.resolveMaybeUndefVal(arg_ref)) |arg_val| {
7835 comptime_args[arg_index] = arg_val.toIntern();
7836 child_sema.inst_map.putAssumeCapacityNoClobber(
7837 param_inst,
7838 Air.internedToRef(arg_val.toIntern()),
7839 );
7840 } else switch (param_tag) {
7841 .param_comptime,
7842 .param_anytype_comptime,
7843 => return sema.failWithOwnedErrorMsg(msg: {
7844 const arg_src = args_info.argSrc(block, arg_index);
7845 const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to comptime parameter", .{});
7846 errdefer msg.destroy(sema.gpa);
7847 const param_src = switch (param_tag) {
7848 .param_comptime => fn_zir.instructions.items(.data)[param_inst].pl_tok.src(),
7849 .param_anytype_comptime => fn_zir.instructions.items(.data)[param_inst].str_tok.src(),
7850 else => unreachable,
7851 };
7852 try child_sema.errNote(&child_block, param_src, msg, "declared comptime here", .{});
7853 break :msg msg;
7854 }),
7855
7856 .param,
7857 .param_anytype,
7858 => return sema.failWithOwnedErrorMsg(msg: {
7859 const arg_src = args_info.argSrc(block, arg_index);
7860 const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to parameter of comptime-only type", .{});
7861 errdefer msg.destroy(sema.gpa);
7862 const param_src = switch (param_tag) {
7863 .param => fn_zir.instructions.items(.data)[param_inst].pl_tok.src(),
7864 .param_anytype => fn_zir.instructions.items(.data)[param_inst].str_tok.src(),
7865 else => unreachable,
7866 };
7867 try child_sema.errNote(&child_block, param_src, msg, "declared here", .{});
7868 const src_decl = mod.declPtr(block.src_decl);
7869 try sema.explainWhyTypeIsComptime(msg, arg_src.toSrcLoc(src_decl, mod), arg_ty);
7870 break :msg msg;
7871 }),
7872
7873 else => unreachable,
7874 }
7875 } else {
7876 // The parameter is runtime-known.
7877 try sema.queueFullTypeResolution(arg_ty);
7878 child_sema.inst_map.putAssumeCapacityNoClobber(param_inst, try child_block.addInst(.{
7587 .tag = .arg,7879 .tag = .arg,
7588 .data = .{ .arg = .{7880 .data = .{ .arg = .{
7589 .ty = Air.internedToRef(sema.typeOf(arg).toIntern()),7881 .ty = Air.internedToRef(arg_ty.toIntern()),
7590 .src_index = @intCast(i),7882 .src_index = @intCast(arg_index),
7591 } },7883 } },
7592 }));7884 }));
7885 const param_name: Zir.NullTerminatedString = switch (param_tag) {
7886 .param_anytype => @enumFromInt(fn_zir.instructions.items(.data)[param_inst].str_tok.start),
7887 .param => name: {
7888 const inst_data = fn_zir.instructions.items(.data)[param_inst].pl_tok;
7889 const extra = fn_zir.extraData(Zir.Inst.Param, inst_data.payload_index);
7890 break :name @enumFromInt(extra.data.name);
7891 },
7892 else => unreachable,
7893 };
7894 try child_block.params.append(sema.arena, .{
7895 .ty = arg_ty.toIntern(), // This is the type after coercion
7896 .is_comptime = false, // We're adding only runtime args to the instantiation
7897 .name = param_name,
7898 });
7899 runtime_args.appendAssumeCapacity(arg_ref);
7900 }
7593 }7901 }
75947902
7595 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);7903 // We've already handled parameters, so don't resolve the whole body. Instead, just
7904 // do the instructions after the params (i.e. the func itself).
7905 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body[args_info.count()..], fn_info.param_body_inst);
7596 const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();7906 const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
75977907
7598 const callee = mod.funcInfo(callee_index);7908 const callee = mod.funcInfo(callee_index);
7599 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);7909 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
76007910
7911 try sema.addReferencedBy(block, call_src, callee.owner_decl);
7912
7601 // Make a runtime call to the new function, making sure to omit the comptime args.7913 // Make a runtime call to the new function, making sure to omit the comptime args.
7602 const func_ty = callee.ty.toType();7914 const func_ty = callee.ty.toType();
7603 const func_ty_info = mod.typeToFunc(func_ty).?;7915 const func_ty_info = mod.typeToFunc(func_ty).?;
...@@ -7615,33 +7927,7 @@ fn instantiateGenericCall(...@@ -7615,33 +7927,7 @@ fn instantiateGenericCall(
7615 return error.GenericPoison;7927 return error.GenericPoison;
7616 }7928 }
76177929
7618 const runtime_args_len: u32 = func_ty_info.param_types.len;7930 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7619 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7620 {
7621 var runtime_i: u32 = 0;
7622 for (uncasted_args, 0..) |uncasted_arg, total_i| {
7623 // In the case of a function call generated by the language, the LazySrcLoc
7624 // provided for `call_src` may not point to anything interesting.
7625 const arg_src: LazySrcLoc = if (total_i == 0 and bound_arg_src != null)
7626 bound_arg_src.?
7627 else if (call_src == .node_offset) .{ .call_arg = .{
7628 .decl = block.src_decl,
7629 .call_node_offset = call_src.node_offset.x,
7630 .arg_index = @intCast(total_i - @intFromBool(bound_arg_src != null)),
7631 } } else .unneeded;
7632
7633 const comptime_arg = callee.comptime_args.get(ip)[total_i];
7634 if (comptime_arg == .none) {
7635 const param_ty = func_ty_info.param_types.get(ip)[runtime_i].toType();
7636 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
7637 try sema.queueFullTypeResolution(param_ty);
7638 runtime_args[runtime_i] = casted_arg;
7639 runtime_i += 1;
7640 }
7641 }
7642
7643 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7644 }
76457931
7646 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7932 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
76477933
...@@ -7653,18 +7939,17 @@ fn instantiateGenericCall(...@@ -7653,18 +7939,17 @@ fn instantiateGenericCall(
76537939
7654 try mod.ensureFuncBodyAnalysisQueued(callee_index);7940 try mod.ensureFuncBodyAnalysisQueued(callee_index);
76557941
7656 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +7942 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + runtime_args.items.len);
7657 runtime_args_len);
7658 const result = try block.addInst(.{7943 const result = try block.addInst(.{
7659 .tag = call_tag,7944 .tag = call_tag,
7660 .data = .{ .pl_op = .{7945 .data = .{ .pl_op = .{
7661 .operand = Air.internedToRef(callee_index),7946 .operand = Air.internedToRef(callee_index),
7662 .payload = sema.addExtraAssumeCapacity(Air.Call{7947 .payload = sema.addExtraAssumeCapacity(Air.Call{
7663 .args_len = runtime_args_len,7948 .args_len = @intCast(runtime_args.items.len),
7664 }),7949 }),
7665 } },7950 } },
7666 });7951 });
7667 sema.appendRefsAssumeCapacity(runtime_args);7952 sema.appendRefsAssumeCapacity(runtime_args.items);
76687953
7669 if (ensure_result_used) {7954 if (ensure_result_used) {
7670 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);7955 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);
...@@ -7744,7 +8029,15 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -7744,7 +8029,15 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
7744fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8029fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7745 const mod = sema.mod;8030 const mod = sema.mod;
7746 const bin = sema.code.instructions.items(.data)[inst].bin;8031 const bin = sema.code.instructions.items(.data)[inst].bin;
7747 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);8032 const operand = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) {
8033 // Since this is a ZIR instruction that returns a type, encountering
8034 // generic poison should not result in a failed compilation, but the
8035 // generic poison type. This prevents unnecessary failures when
8036 // constructing types at compile-time.
8037 error.GenericPoison => return .generic_poison_type,
8038 else => |e| return e,
8039 };
8040 const indexable_ty = try sema.resolveTypeFields(operand);
7748 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction8041 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
7749 if (indexable_ty.zigTypeTag(mod) == .Struct) {8042 if (indexable_ty.zigTypeTag(mod) == .Struct) {
7750 const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod);8043 const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod);
...@@ -7763,6 +8056,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -7763,6 +8056,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
7763 return sema.addType(ptr_ty.childType(mod));8056 return sema.addType(ptr_ty.childType(mod));
7764}8057}
77658058
8059fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8060 const mod = sema.mod;
8061 const un_node = sema.code.instructions.items(.data)[inst].un_node;
8062 const vec_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) {
8063 // Since this is a ZIR instruction that returns a type, encountering
8064 // generic poison should not result in a failed compilation, but the
8065 // generic poison type. This prevents unnecessary failures when
8066 // constructing types at compile-time.
8067 error.GenericPoison => return .generic_poison_type,
8068 else => |e| return e,
8069 };
8070 if (!vec_ty.isVector(mod)) {
8071 return sema.fail(block, un_node.src(), "expected vector type, found '{}'", .{vec_ty.fmt(mod)});
8072 }
8073 return sema.addType(vec_ty.childType(mod));
8074}
8075
7766fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8076fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7767 const mod = sema.mod;8077 const mod = sema.mod;
7768 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8078 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
...@@ -8588,20 +8898,17 @@ fn resolveGenericBody(...@@ -8588,20 +8898,17 @@ fn resolveGenericBody(
8588 const prev_no_partial_func_type = sema.no_partial_func_ty;8898 const prev_no_partial_func_type = sema.no_partial_func_ty;
8589 const prev_generic_owner = sema.generic_owner;8899 const prev_generic_owner = sema.generic_owner;
8590 const prev_generic_call_src = sema.generic_call_src;8900 const prev_generic_call_src = sema.generic_call_src;
8591 const prev_generic_bound_arg_src = sema.generic_bound_arg_src;
8592 const prev_generic_call_decl = sema.generic_call_decl;8901 const prev_generic_call_decl = sema.generic_call_decl;
8593 block.params = .{};8902 block.params = .{};
8594 sema.no_partial_func_ty = true;8903 sema.no_partial_func_ty = true;
8595 sema.generic_owner = .none;8904 sema.generic_owner = .none;
8596 sema.generic_call_src = .unneeded;8905 sema.generic_call_src = .unneeded;
8597 sema.generic_bound_arg_src = null;
8598 sema.generic_call_decl = .none;8906 sema.generic_call_decl = .none;
8599 defer {8907 defer {
8600 block.params = prev_params;8908 block.params = prev_params;
8601 sema.no_partial_func_ty = prev_no_partial_func_type;8909 sema.no_partial_func_ty = prev_no_partial_func_type;
8602 sema.generic_owner = prev_generic_owner;8910 sema.generic_owner = prev_generic_owner;
8603 sema.generic_call_src = prev_generic_call_src;8911 sema.generic_call_src = prev_generic_call_src;
8604 sema.generic_bound_arg_src = prev_generic_bound_arg_src;
8605 sema.generic_call_decl = prev_generic_call_decl;8912 sema.generic_call_decl = prev_generic_call_decl;
8606 }8913 }
86078914
...@@ -9219,37 +9526,18 @@ fn finishFunc(...@@ -9219,37 +9526,18 @@ fn finishFunc(
9219 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);9526 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
9220}9527}
92219528
9222fn genericArgSrcLoc(sema: *Sema, block: *Block, param_index: u32, param_src: LazySrcLoc) Module.SrcLoc {
9223 const mod = sema.mod;
9224 if (sema.generic_owner == .none) return param_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9225 const arg_decl = sema.generic_call_decl.unwrap().?;
9226 const arg_src: LazySrcLoc = if (param_index == 0 and sema.generic_bound_arg_src != null)
9227 sema.generic_bound_arg_src.?
9228 else
9229 .{ .call_arg = .{
9230 .decl = arg_decl,
9231 .call_node_offset = sema.generic_call_src.node_offset.x,
9232 .arg_index = param_index - @intFromBool(sema.generic_bound_arg_src != null),
9233 } };
9234 return arg_src.toSrcLoc(mod.declPtr(arg_decl), mod);
9235}
9236
9237fn zirParam(9529fn zirParam(
9238 sema: *Sema,9530 sema: *Sema,
9239 block: *Block,9531 block: *Block,
9240 inst: Zir.Inst.Index,9532 inst: Zir.Inst.Index,
9241 param_index: u32,
9242 comptime_syntax: bool,9533 comptime_syntax: bool,
9243) CompileError!void {9534) CompileError!void {
9244 const gpa = sema.gpa;
9245 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;9535 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
9246 const src = inst_data.src();9536 const src = inst_data.src();
9247 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);9537 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
9248 const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name);9538 const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name);
9249 const body = sema.code.extra[extra.end..][0..extra.data.body_len];9539 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
92509540
9251 // We could be in a generic function instantiation, or we could be evaluating a generic
9252 // function without any comptime args provided.
9253 const param_ty = param_ty: {9541 const param_ty = param_ty: {
9254 const err = err: {9542 const err = err: {
9255 // Make sure any nested param instructions don't clobber our work.9543 // Make sure any nested param instructions don't clobber our work.
...@@ -9257,20 +9545,17 @@ fn zirParam(...@@ -9257,20 +9545,17 @@ fn zirParam(
9257 const prev_no_partial_func_type = sema.no_partial_func_ty;9545 const prev_no_partial_func_type = sema.no_partial_func_ty;
9258 const prev_generic_owner = sema.generic_owner;9546 const prev_generic_owner = sema.generic_owner;
9259 const prev_generic_call_src = sema.generic_call_src;9547 const prev_generic_call_src = sema.generic_call_src;
9260 const prev_generic_bound_arg_src = sema.generic_bound_arg_src;
9261 const prev_generic_call_decl = sema.generic_call_decl;9548 const prev_generic_call_decl = sema.generic_call_decl;
9262 block.params = .{};9549 block.params = .{};
9263 sema.no_partial_func_ty = true;9550 sema.no_partial_func_ty = true;
9264 sema.generic_owner = .none;9551 sema.generic_owner = .none;
9265 sema.generic_call_src = .unneeded;9552 sema.generic_call_src = .unneeded;
9266 sema.generic_bound_arg_src = null;
9267 sema.generic_call_decl = .none;9553 sema.generic_call_decl = .none;
9268 defer {9554 defer {
9269 block.params = prev_params;9555 block.params = prev_params;
9270 sema.no_partial_func_ty = prev_no_partial_func_type;9556 sema.no_partial_func_ty = prev_no_partial_func_type;
9271 sema.generic_owner = prev_generic_owner;9557 sema.generic_owner = prev_generic_owner;
9272 sema.generic_call_src = prev_generic_call_src;9558 sema.generic_call_src = prev_generic_call_src;
9273 sema.generic_bound_arg_src = prev_generic_bound_arg_src;
9274 sema.generic_call_decl = prev_generic_call_decl;9559 sema.generic_call_decl = prev_generic_call_decl;
9275 }9560 }
92769561
...@@ -9282,11 +9567,6 @@ fn zirParam(...@@ -9282,11 +9567,6 @@ fn zirParam(
9282 };9567 };
9283 switch (err) {9568 switch (err) {
9284 error.GenericPoison => {9569 error.GenericPoison => {
9285 if (sema.inst_map.contains(inst)) {
9286 // A generic function is about to evaluate to another generic function.
9287 // Return an error instead.
9288 return error.GenericPoison;
9289 }
9290 // The type is not available until the generic instantiation.9570 // The type is not available until the generic instantiation.
9291 // We result the param instruction with a poison value and9571 // We result the param instruction with a poison value and
9292 // insert an anytype parameter.9572 // insert an anytype parameter.
...@@ -9304,11 +9584,6 @@ fn zirParam(...@@ -9304,11 +9584,6 @@ fn zirParam(
93049584
9305 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {9585 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
9306 error.GenericPoison => {9586 error.GenericPoison => {
9307 if (sema.inst_map.contains(inst)) {
9308 // A generic function is about to evaluate to another generic function.
9309 // Return an error instead.
9310 return error.GenericPoison;
9311 }
9312 // The type is not available until the generic instantiation.9587 // The type is not available until the generic instantiation.
9313 // We result the param instruction with a poison value and9588 // We result the param instruction with a poison value and
9314 // insert an anytype parameter.9589 // insert an anytype parameter.
...@@ -9323,46 +9598,6 @@ fn zirParam(...@@ -9323,46 +9598,6 @@ fn zirParam(
9323 else => |e| return e,9598 else => |e| return e,
9324 } or comptime_syntax;9599 } or comptime_syntax;
93259600
9326 if (sema.inst_map.get(inst)) |arg| {
9327 if (is_comptime and sema.generic_owner != .none) {
9328 // We have a comptime value for this parameter so it should be elided from the
9329 // function type of the function instruction in this block.
9330 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
9331 error.NeededSourceLocation => {
9332 // We are instantiating a generic function and a comptime arg
9333 // cannot be coerced to the param type, but since we don't
9334 // have the callee source location return `GenericPoison`
9335 // so that the instantiation is failed and the coercion
9336 // is handled by comptime call logic instead.
9337 assert(sema.generic_owner != .none);
9338 return error.GenericPoison;
9339 },
9340 else => |e| return e,
9341 };
9342 sema.inst_map.putAssumeCapacity(inst, coerced_arg);
9343 if (try sema.resolveMaybeUndefVal(coerced_arg)) |val| {
9344 sema.comptime_args[param_index] = val.toIntern();
9345 return;
9346 }
9347 const msg = msg: {
9348 const src_loc = sema.genericArgSrcLoc(block, param_index, src);
9349 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9350 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9351 });
9352 errdefer msg.destroy(gpa);
9353
9354 if (sema.generic_call_decl != .none) {
9355 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")});
9356 }
9357 break :msg msg;
9358 };
9359 return sema.failWithOwnedErrorMsg(msg);
9360 }
9361 // Even though a comptime argument is provided, the generic function wants to treat
9362 // this as a runtime parameter.
9363 assert(sema.inst_map.remove(inst));
9364 }
9365
9366 try block.params.append(sema.arena, .{9601 try block.params.append(sema.arena, .{
9367 .ty = param_ty.toIntern(),9602 .ty = param_ty.toIntern(),
9368 .is_comptime = comptime_syntax,9603 .is_comptime = comptime_syntax,
...@@ -9388,75 +9623,10 @@ fn zirParamAnytype(...@@ -9388,75 +9623,10 @@ fn zirParamAnytype(
9388 sema: *Sema,9623 sema: *Sema,
9389 block: *Block,9624 block: *Block,
9390 inst: Zir.Inst.Index,9625 inst: Zir.Inst.Index,
9391 param_index: u32,
9392 comptime_syntax: bool,9626 comptime_syntax: bool,
9393) CompileError!void {9627) CompileError!void {
9394 const gpa = sema.gpa;
9395 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;9628 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
9396 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);9629 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
9397 const src = inst_data.src();
9398
9399 if (sema.inst_map.get(inst)) |air_ref| {
9400 const param_ty = sema.typeOf(air_ref);
9401 // If we have a comptime value for this parameter, it should be elided
9402 // from the function type of the function instruction in this block.
9403 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9404 sema.comptime_args[param_index] = opv.toIntern();
9405 return;
9406 }
9407
9408 if (comptime_syntax) {
9409 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9410 sema.comptime_args[param_index] = val.toIntern();
9411 return;
9412 }
9413 const msg = msg: {
9414 const src_loc = sema.genericArgSrcLoc(block, param_index, src);
9415 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9416 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9417 });
9418 errdefer msg.destroy(gpa);
9419
9420 if (sema.generic_call_decl != .none) {
9421 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")});
9422 }
9423 break :msg msg;
9424 };
9425 return sema.failWithOwnedErrorMsg(msg);
9426 }
9427
9428 if (try sema.typeRequiresComptime(param_ty)) {
9429 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9430 sema.comptime_args[param_index] = val.toIntern();
9431 return;
9432 }
9433 const msg = msg: {
9434 const src_loc = sema.genericArgSrcLoc(block, param_index, src);
9435 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9436 @as([]const u8, "runtime-known argument passed to comptime-only type parameter"),
9437 });
9438 errdefer msg.destroy(gpa);
9439
9440 if (sema.generic_call_decl != .none) {
9441 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared here")});
9442 }
9443
9444 try sema.explainWhyTypeIsComptime(msg, src_loc, param_ty);
9445
9446 break :msg msg;
9447 };
9448 return sema.failWithOwnedErrorMsg(msg);
9449 }
9450
9451 // The parameter is runtime-known.
9452 // The map is already populated but we do need to add a runtime parameter.
9453 try block.params.append(sema.arena, .{
9454 .ty = param_ty.toIntern(),
9455 .is_comptime = false,
9456 .name = param_name,
9457 });
9458 return;
9459 }
94609630
9461 // We are evaluating a generic function without any comptime args provided.9631 // We are evaluating a generic function without any comptime args provided.
94629632
...@@ -18794,7 +18964,13 @@ fn zirStructInit(...@@ -18794,7 +18964,13 @@ fn zirStructInit(
18794 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;18964 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
18795 const first_field_type_data = zir_datas[first_item.field_type].pl_node;18965 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
18796 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;18966 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
18797 const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type);18967 const resolved_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) {
18968 error.GenericPoison => {
18969 // The type wasn't actually known, so treat this as an anon struct init.
18970 return sema.structInitAnon(block, src, .typed_init, extra.data, extra.end, is_ref);
18971 },
18972 else => |e| return e,
18973 };
18798 try sema.resolveTypeLayout(resolved_ty);18974 try sema.resolveTypeLayout(resolved_ty);
1879918975
18800 if (resolved_ty.zigTypeTag(mod) == .Struct) {18976 if (resolved_ty.zigTypeTag(mod) == .Struct) {
...@@ -19037,26 +19213,57 @@ fn zirStructInitAnon(...@@ -19037,26 +19213,57 @@ fn zirStructInitAnon(
19037 inst: Zir.Inst.Index,19213 inst: Zir.Inst.Index,
19038 is_ref: bool,19214 is_ref: bool,
19039) CompileError!Air.Inst.Ref {19215) CompileError!Air.Inst.Ref {
19040 const mod = sema.mod;
19041 const gpa = sema.gpa;
19042 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;19216 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19043 const src = inst_data.src();19217 const src = inst_data.src();
19044 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);19218 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
19045 const types = try sema.arena.alloc(InternPool.Index, extra.data.fields_len);19219 return sema.structInitAnon(block, src, .anon_init, extra.data, extra.end, is_ref);
19220}
19221
19222fn structInitAnon(
19223 sema: *Sema,
19224 block: *Block,
19225 src: LazySrcLoc,
19226 /// It is possible for a typed struct_init to be downgraded to an anonymous init due to a
19227 /// generic poison type. In this case, we need to know to interpret the extra data differently.
19228 comptime kind: enum { anon_init, typed_init },
19229 extra_data: switch (kind) {
19230 .anon_init => Zir.Inst.StructInitAnon,
19231 .typed_init => Zir.Inst.StructInit,
19232 },
19233 extra_end: usize,
19234 is_ref: bool,
19235) CompileError!Air.Inst.Ref {
19236 const mod = sema.mod;
19237 const gpa = sema.gpa;
19238 const zir_datas = sema.code.instructions.items(.data);
19239
19240 const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len);
19046 const values = try sema.arena.alloc(InternPool.Index, types.len);19241 const values = try sema.arena.alloc(InternPool.Index, types.len);
19242
19047 var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena);19243 var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena);
19048 try fields.ensureUnusedCapacity(types.len);19244 try fields.ensureUnusedCapacity(types.len);
1904919245
19050 // Find which field forces the expression to be runtime, if any.19246 // Find which field forces the expression to be runtime, if any.
19051 const opt_runtime_index = rs: {19247 const opt_runtime_index = rs: {
19052 var runtime_index: ?usize = null;19248 var runtime_index: ?usize = null;
19053 var extra_index = extra.end;19249 var extra_index = extra_end;
19054 for (types, 0..) |*field_ty, i_usize| {19250 for (types, 0..) |*field_ty, i_usize| {
19055 const i = @as(u32, @intCast(i_usize));19251 const i: u32 = @intCast(i_usize);
19056 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);19252 const item = switch (kind) {
19253 .anon_init => sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index),
19254 .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index),
19255 };
19057 extra_index = item.end;19256 extra_index = item.end;
1905819257
19059 const name = sema.code.nullTerminatedString(item.data.field_name);19258 const name = switch (kind) {
19259 .anon_init => sema.code.nullTerminatedString(item.data.field_name),
19260 .typed_init => name: {
19261 // `item.data.field_type` references a `field_type` instruction
19262 const field_type_data = zir_datas[item.data.field_type].pl_node;
19263 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index);
19264 break :name sema.code.nullTerminatedString(field_type_extra.data.name_start);
19265 },
19266 };
19060 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);19267 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
19061 const gop = fields.getOrPutAssumeCapacity(name_ip);19268 const gop = fields.getOrPutAssumeCapacity(name_ip);
19062 if (gop.found_existing) {19269 if (gop.found_existing) {
...@@ -19129,10 +19336,13 @@ fn zirStructInitAnon(...@@ -19129,10 +19336,13 @@ fn zirStructInitAnon(
19129 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },19336 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
19130 });19337 });
19131 const alloc = try block.addTy(.alloc, alloc_ty);19338 const alloc = try block.addTy(.alloc, alloc_ty);
19132 var extra_index = extra.end;19339 var extra_index = extra_end;
19133 for (types, 0..) |field_ty, i_usize| {19340 for (types, 0..) |field_ty, i_usize| {
19134 const i = @as(u32, @intCast(i_usize));19341 const i = @as(u32, @intCast(i_usize));
19135 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);19342 const item = switch (kind) {
19343 .anon_init => sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index),
19344 .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index),
19345 };
19136 extra_index = item.end;19346 extra_index = item.end;
1913719347
19138 const field_ptr_ty = try mod.ptrType(.{19348 const field_ptr_ty = try mod.ptrType(.{
...@@ -19150,9 +19360,12 @@ fn zirStructInitAnon(...@@ -19150,9 +19360,12 @@ fn zirStructInitAnon(
19150 }19360 }
1915119361
19152 const element_refs = try sema.arena.alloc(Air.Inst.Ref, types.len);19362 const element_refs = try sema.arena.alloc(Air.Inst.Ref, types.len);
19153 var extra_index = extra.end;19363 var extra_index = extra_end;
19154 for (types, 0..) |_, i| {19364 for (types, 0..) |_, i| {
19155 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);19365 const item = switch (kind) {
19366 .anon_init => sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index),
19367 .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index),
19368 };
19156 extra_index = item.end;19369 extra_index = item.end;
19157 element_refs[i] = try sema.resolveInst(item.data.init);19370 element_refs[i] = try sema.resolveInst(item.data.init);
19158 }19371 }
...@@ -19175,14 +19388,21 @@ fn zirArrayInit(...@@ -19175,14 +19388,21 @@ fn zirArrayInit(
19175 const args = sema.code.refSlice(extra.end, extra.data.operands_len);19388 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
19176 assert(args.len >= 2); // array_ty + at least one element19389 assert(args.len >= 2); // array_ty + at least one element
1917719390
19178 const array_ty = try sema.resolveType(block, src, args[0]);19391 const array_ty = sema.resolveType(block, src, args[0]) catch |err| switch (err) {
19392 error.GenericPoison => {
19393 // The type wasn't actually known, so treat this as an anon array init.
19394 return sema.arrayInitAnon(block, src, args[1..], is_ref);
19395 },
19396 else => |e| return e,
19397 };
19398 const is_tuple = array_ty.zigTypeTag(mod) == .Struct;
19179 const sentinel_val = array_ty.sentinel(mod);19399 const sentinel_val = array_ty.sentinel(mod);
1918019400
19181 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @intFromBool(sentinel_val != null));19401 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @intFromBool(sentinel_val != null));
19182 defer gpa.free(resolved_args);19402 defer gpa.free(resolved_args);
19183 for (args[1..], 0..) |arg, i| {19403 for (args[1..], 0..) |arg, i| {
19184 const resolved_arg = try sema.resolveInst(arg);19404 const resolved_arg = try sema.resolveInst(arg);
19185 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)19405 const elem_ty = if (is_tuple)
19186 array_ty.structFieldType(i, mod)19406 array_ty.structFieldType(i, mod)
19187 else19407 else
19188 array_ty.elemType2(mod);19408 array_ty.elemType2(mod);
...@@ -19195,6 +19415,18 @@ fn zirArrayInit(...@@ -19195,6 +19415,18 @@ fn zirArrayInit(
19195 },19415 },
19196 else => return err,19416 else => return err,
19197 };19417 };
19418 if (is_tuple) if (try array_ty.structFieldValueComptime(mod, i)) |field_val| {
19419 const init_val = try sema.resolveMaybeUndefVal(resolved_args[i]) orelse {
19420 const decl = mod.declPtr(block.src_decl);
19421 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
19422 return sema.failWithNeededComptime(block, elem_src, "value stored in comptime field must be comptime-known");
19423 };
19424 if (!field_val.eql(init_val, elem_ty, mod)) {
19425 const decl = mod.declPtr(block.src_decl);
19426 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
19427 return sema.failWithInvalidComptimeFieldStore(block, elem_src, array_ty, i);
19428 }
19429 };
19198 }19430 }
1919919431
19200 if (sentinel_val) |some| {19432 if (sentinel_val) |some| {
...@@ -19283,6 +19515,16 @@ fn zirArrayInitAnon(...@@ -19283,6 +19515,16 @@ fn zirArrayInitAnon(
19283 const src = inst_data.src();19515 const src = inst_data.src();
19284 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);19516 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
19285 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);19517 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);
19518 return sema.arrayInitAnon(block, src, operands, is_ref);
19519}
19520
19521fn arrayInitAnon(
19522 sema: *Sema,
19523 block: *Block,
19524 src: LazySrcLoc,
19525 operands: []const Zir.Inst.Ref,
19526 is_ref: bool,
19527) CompileError!Air.Inst.Ref {
19286 const mod = sema.mod;19528 const mod = sema.mod;
1928719529
19288 const types = try sema.arena.alloc(InternPool.Index, operands.len);19530 const types = try sema.arena.alloc(InternPool.Index, operands.len);
...@@ -23034,7 +23276,21 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -23034,7 +23276,21 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
23034 const callee_ty = sema.typeOf(func);23276 const callee_ty = sema.typeOf(func);
23035 const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false);23277 const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false);
23036 const ensure_result_used = extra.flags.ensure_result_used;23278 const ensure_result_used = extra.flags.ensure_result_used;
23037 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null, .@"@call");23279 return sema.analyzeCall(
23280 block,
23281 func,
23282 func_ty,
23283 func_src,
23284 call_src,
23285 modifier,
23286 ensure_result_used,
23287 .{ .call_builtin = .{
23288 .call_node_offset = inst_data.src_node,
23289 .args = resolved_args,
23290 } },
23291 null,
23292 .@"@call",
23293 );
23038}23294}
2303923295
23040fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {23296fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/Zir.zig+15
...@@ -248,6 +248,9 @@ pub const Inst = struct {...@@ -248,6 +248,9 @@ pub const Inst = struct {
248 /// Given a pointer type, returns its element type.248 /// Given a pointer type, returns its element type.
249 /// Uses the `un_node` field.249 /// Uses the `un_node` field.
250 elem_type,250 elem_type,
251 /// Given a vector type, returns its element type.
252 /// Uses the `un_node` field.
253 vector_elem_type,
251 /// Given a pointer to an indexable object, returns the len property. This is254 /// Given a pointer to an indexable object, returns the len property. This is
252 /// used by for loops. This instruction also emits a for-loop specific compile255 /// used by for loops. This instruction also emits a for-loop specific compile
253 /// error if the indexable object is not indexable.256 /// error if the indexable object is not indexable.
...@@ -700,10 +703,16 @@ pub const Inst = struct {...@@ -700,10 +703,16 @@ pub const Inst = struct {
700 /// *?S returns *S703 /// *?S returns *S
701 /// Uses the `un_node` field.704 /// Uses the `un_node` field.
702 field_base_ptr,705 field_base_ptr,
706 /// Given a type, strips all optional and error union types wrapping it.
707 /// e.g. `E!?u32` becomes `u32`, `[]u8` becomes `[]u8`.
708 /// Uses the `un_node` field.
709 opt_eu_base_ty,
703 /// Checks that the type supports array init syntax.710 /// Checks that the type supports array init syntax.
711 /// Returns the underlying indexable type (since the given type may be e.g. an optional).
704 /// Uses the `un_node` field.712 /// Uses the `un_node` field.
705 validate_array_init_ty,713 validate_array_init_ty,
706 /// Checks that the type supports struct init syntax.714 /// Checks that the type supports struct init syntax.
715 /// Returns the underlying struct type (since the given type may be e.g. an optional).
707 /// Uses the `un_node` field.716 /// Uses the `un_node` field.
708 validate_struct_init_ty,717 validate_struct_init_ty,
709 /// Given a set of `field_ptr` instructions, assumes they are all part of a struct718 /// Given a set of `field_ptr` instructions, assumes they are all part of a struct
...@@ -1023,6 +1032,7 @@ pub const Inst = struct {...@@ -1023,6 +1032,7 @@ pub const Inst = struct {
1023 .vector_type,1032 .vector_type,
1024 .elem_type_index,1033 .elem_type_index,
1025 .elem_type,1034 .elem_type,
1035 .vector_elem_type,
1026 .indexable_ptr_len,1036 .indexable_ptr_len,
1027 .anyframe_type,1037 .anyframe_type,
1028 .as,1038 .as,
...@@ -1234,6 +1244,7 @@ pub const Inst = struct {...@@ -1234,6 +1244,7 @@ pub const Inst = struct {
1234 .save_err_ret_index,1244 .save_err_ret_index,
1235 .restore_err_ret_index,1245 .restore_err_ret_index,
1236 .for_len,1246 .for_len,
1247 .opt_eu_base_ty,
1237 => false,1248 => false,
12381249
1239 .@"break",1250 .@"break",
...@@ -1327,6 +1338,7 @@ pub const Inst = struct {...@@ -1327,6 +1338,7 @@ pub const Inst = struct {
1327 .vector_type,1338 .vector_type,
1328 .elem_type_index,1339 .elem_type_index,
1329 .elem_type,1340 .elem_type,
1341 .vector_elem_type,
1330 .indexable_ptr_len,1342 .indexable_ptr_len,
1331 .anyframe_type,1343 .anyframe_type,
1332 .as,1344 .as,
...@@ -1522,6 +1534,7 @@ pub const Inst = struct {...@@ -1522,6 +1534,7 @@ pub const Inst = struct {
1522 .for_len,1534 .for_len,
1523 .@"try",1535 .@"try",
1524 .try_ptr,1536 .try_ptr,
1537 .opt_eu_base_ty,
1525 => false,1538 => false,
15261539
1527 .extended => switch (data.extended.opcode) {1540 .extended => switch (data.extended.opcode) {
...@@ -1557,6 +1570,7 @@ pub const Inst = struct {...@@ -1557,6 +1570,7 @@ pub const Inst = struct {
1557 .vector_type = .pl_node,1570 .vector_type = .pl_node,
1558 .elem_type_index = .bin,1571 .elem_type_index = .bin,
1559 .elem_type = .un_node,1572 .elem_type = .un_node,
1573 .vector_elem_type = .un_node,
1560 .indexable_ptr_len = .un_node,1574 .indexable_ptr_len = .un_node,
1561 .anyframe_type = .un_node,1575 .anyframe_type = .un_node,
1562 .as = .bin,1576 .as = .bin,
...@@ -1676,6 +1690,7 @@ pub const Inst = struct {...@@ -1676,6 +1690,7 @@ pub const Inst = struct {
1676 .switch_block_ref = .pl_node,1690 .switch_block_ref = .pl_node,
1677 .array_base_ptr = .un_node,1691 .array_base_ptr = .un_node,
1678 .field_base_ptr = .un_node,1692 .field_base_ptr = .un_node,
1693 .opt_eu_base_ty = .un_node,
1679 .validate_array_init_ty = .pl_node,1694 .validate_array_init_ty = .pl_node,
1680 .validate_struct_init_ty = .un_node,1695 .validate_struct_init_ty = .un_node,
1681 .validate_struct_init = .pl_node,1696 .validate_struct_init = .pl_node,
src/print_zir.zig+2
...@@ -155,6 +155,7 @@ const Writer = struct {...@@ -155,6 +155,7 @@ const Writer = struct {
155 .alloc_mut,155 .alloc_mut,
156 .alloc_comptime_mut,156 .alloc_comptime_mut,
157 .elem_type,157 .elem_type,
158 .vector_elem_type,
158 .indexable_ptr_len,159 .indexable_ptr_len,
159 .anyframe_type,160 .anyframe_type,
160 .bit_not,161 .bit_not,
...@@ -229,6 +230,7 @@ const Writer = struct {...@@ -229,6 +230,7 @@ const Writer = struct {
229 .make_ptr_const,230 .make_ptr_const,
230 .validate_deref,231 .validate_deref,
231 .check_comptime_control_flow,232 .check_comptime_control_flow,
233 .opt_eu_base_ty,
232 => try self.writeUnNode(stream, inst),234 => try self.writeUnNode(stream, inst),
233235
234 .ref,236 .ref,
src/type.zig+1
...@@ -3039,6 +3039,7 @@ pub const Type = struct {...@@ -3039,6 +3039,7 @@ pub const Type = struct {
3039 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {3039 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3040 .struct_type => |struct_type| {3040 .struct_type => |struct_type| {
3041 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;3041 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3042 assert(struct_obj.haveFieldTypes());
3042 return struct_obj.fields.values()[index].ty;3043 return struct_obj.fields.values()[index].ty;
3043 },3044 },
3044 .union_type => |union_type| {3045 .union_type => |union_type| {
test/behavior/array.zig+14
...@@ -761,3 +761,17 @@ test "slicing array of zero-sized values" {...@@ -761,3 +761,17 @@ test "slicing array of zero-sized values" {
761 for (arr[0..]) |zero|761 for (arr[0..]) |zero|
762 try expect(zero == 0);762 try expect(zero == 0);
763}763}
764
765test "array init with no result pointer sets field result types" {
766 const S = struct {
767 // A function parameter has a result type, but no result pointer.
768 fn f(arr: [1]u32) u32 {
769 return arr[0];
770 }
771 };
772
773 const x: u64 = 123;
774 const y = S.f(.{@intCast(x)});
775
776 try expect(y == x);
777}
test/behavior/call.zig+61
...@@ -430,3 +430,64 @@ test "method call as parameter type" {...@@ -430,3 +430,64 @@ test "method call as parameter type" {
430 try expectEqual(@as(u64, 123), S.foo(S{}, 123));430 try expectEqual(@as(u64, 123), S.foo(S{}, 123));
431 try expectEqual(@as(u64, 500), S.foo(S{}, 500));431 try expectEqual(@as(u64, 500), S.foo(S{}, 500));
432}432}
433
434test "non-anytype generic parameters provide result type" {
435 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
437 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
439 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
440 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
441
442 const S = struct {
443 fn f(comptime T: type, y: T) !void {
444 try expectEqual(@as(T, 123), y);
445 }
446
447 fn g(x: anytype, y: @TypeOf(x)) !void {
448 try expectEqual(@as(@TypeOf(x), 0x222), y);
449 }
450 };
451
452 var rt_u16: u16 = 123;
453 var rt_u32: u32 = 0x10000222;
454
455 try S.f(u8, @intCast(rt_u16));
456 try S.f(u8, @intCast(123));
457
458 try S.g(rt_u16, @truncate(rt_u32));
459 try S.g(rt_u16, @truncate(0x10000222));
460
461 try comptime S.f(u8, @intCast(123));
462 try comptime S.g(@as(u16, undefined), @truncate(0x99990222));
463}
464
465test "argument to generic function has correct result type" {
466 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
468 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
469 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
471 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
472
473 const S = struct {
474 fn foo(_: anytype, e: enum { a, b }) bool {
475 return e == .b;
476 }
477
478 fn doTheTest() !void {
479 var t = true;
480
481 // Since the enum literal passes through a runtime conditional here, these can only
482 // compile if RLS provides the correct result type to the argument
483 try expect(foo({}, if (!t) .a else .b));
484 try expect(!foo("dummy", if (t) .a else .b));
485 try expect(foo({}, if (t) .b else .a));
486 try expect(!foo(123, if (t) .a else .a));
487 try expect(foo(123, if (t) .b else .b));
488 }
489 };
490
491 try S.doTheTest();
492 try comptime S.doTheTest();
493}
test/behavior/struct.zig+14
...@@ -1724,3 +1724,17 @@ test "packed struct field in anonymous struct" {...@@ -1724,3 +1724,17 @@ test "packed struct field in anonymous struct" {
1724fn countFields(v: anytype) usize {1724fn countFields(v: anytype) usize {
1725 return @typeInfo(@TypeOf(v)).Struct.fields.len;1725 return @typeInfo(@TypeOf(v)).Struct.fields.len;
1726}1726}
1727
1728test "struct init with no result pointer sets field result types" {
1729 const S = struct {
1730 // A function parameter has a result type, but no result pointer.
1731 fn f(s: struct { x: u32 }) u32 {
1732 return s.x;
1733 }
1734 };
1735
1736 const x: u64 = 123;
1737 const y = S.f(.{ .x = @intCast(x) });
1738
1739 try expect(y == x);
1740}
test/cases/compile_errors/anytype_param_requires_comptime.zig+1-1
...@@ -16,7 +16,7 @@ pub export fn entry() void {...@@ -16,7 +16,7 @@ pub export fn entry() void {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :7:14: error: runtime-known argument passed to comptime-only type parameter19// :7:14: error: runtime-known argument passed to parameter of comptime-only type
20// :9:12: note: declared here20// :9:12: note: declared here
21// :4:16: note: struct requires comptime because of this field21// :4:16: note: struct requires comptime because of this field
22// :4:16: note: types are not available at runtime22// :4:16: note: types are not available at runtime
test/cases/compile_errors/error_in_typeof_param.zig+1-1
...@@ -11,4 +11,4 @@ pub export fn entry() void {...@@ -11,4 +11,4 @@ pub export fn entry() void {
11// target=native11// target=native
12//12//
13// :6:31: error: unable to resolve comptime value13// :6:31: error: unable to resolve comptime value
14// :6:31: note: argument to parameter with comptime-only type must be comptime-known14// :6:31: note: value being casted to 'comptime_int' must be comptime-known
test/cases/compile_errors/generic_method_call_with_invalid_param.zig+2
...@@ -25,6 +25,8 @@ const S = struct {...@@ -25,6 +25,8 @@ const S = struct {
25// target=native25// target=native
26//26//
27// :3:18: error: expected type 'bool', found 'void'27// :3:18: error: expected type 'bool', found 'void'
28// :18:43: note: parameter type declared here
28// :8:18: error: expected type 'void', found 'bool'29// :8:18: error: expected type 'void', found 'bool'
30// :19:43: note: parameter type declared here
29// :14:26: error: runtime-known argument passed to comptime parameter31// :14:26: error: runtime-known argument passed to comptime parameter
30// :20:57: note: declared comptime here32// :20:57: note: declared comptime here
test/cases/compile_errors/invalid_store_to_comptime_field.zig+3-2
...@@ -76,8 +76,9 @@ pub export fn entry8() void {...@@ -76,8 +76,9 @@ pub export fn entry8() void {
76// :19:38: error: value stored in comptime field does not match the default value of the field76// :19:38: error: value stored in comptime field does not match the default value of the field
77// :31:19: error: value stored in comptime field does not match the default value of the field77// :31:19: error: value stored in comptime field does not match the default value of the field
78// :25:29: note: default value set here78// :25:29: note: default value set here
79// :41:16: error: value stored in comptime field does not match the default value of the field79// :41:19: error: value stored in comptime field does not match the default value of the field
80// :35:29: note: default value set here
80// :45:12: error: value stored in comptime field does not match the default value of the field81// :45:12: error: value stored in comptime field does not match the default value of the field
81// :53:16: error: value stored in comptime field does not match the default value of the field82// :53:25: error: value stored in comptime field does not match the default value of the field
82// :66:43: error: value stored in comptime field does not match the default value of the field83// :66:43: error: value stored in comptime field does not match the default value of the field
83// :59:35: error: value stored in comptime field does not match the default value of the field84// :59:35: error: value stored in comptime field does not match the default value of the field
test/cases/compile_errors/splat_result_type_non_vector.zig created+9
...@@ -0,0 +1,9 @@
1export fn f() void {
2 _ = @as(u32, @splat(5));
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:18: error: expected vector type, found 'u32'
test/cases/compile_errors/wrong_types_given_to_export.zig+1-1
...@@ -7,5 +7,5 @@ comptime {...@@ -7,5 +7,5 @@ comptime {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:51: error: expected type 'builtin.GlobalLinkage', found 'u32'10// :3:21: error: expected type 'builtin.GlobalLinkage', found 'u32'
11// :?:?: note: enum declared here11// :?:?: note: enum declared here
test/cases/compile_errors/zero-bit_generic_args_are_coerced_to_param_type.zig+1
...@@ -8,3 +8,4 @@ pub export fn entry() void {...@@ -8,3 +8,4 @@ pub export fn entry() void {
8// target=native8// target=native
9//9//
10// :3:21: error: expected type 'u0', found '*const [4:0]u8'10// :3:21: error: expected type 'u0', found '*const [4:0]u8'
11// :1:23: note: parameter type declared here
test/compile_errors.zig+1-1
...@@ -207,7 +207,7 @@ pub fn addCases(ctx: *Cases) !void {...@@ -207,7 +207,7 @@ pub fn addCases(ctx: *Cases) !void {
207 ":1:38: note: declared comptime here",207 ":1:38: note: declared comptime here",
208 ":8:36: error: runtime-known argument passed to comptime parameter",208 ":8:36: error: runtime-known argument passed to comptime parameter",
209 ":2:41: note: declared comptime here",209 ":2:41: note: declared comptime here",
210 ":13:29: error: runtime-known argument passed to comptime-only type parameter",210 ":13:29: error: runtime-known argument passed to parameter of comptime-only type",
211 ":3:24: note: declared here",211 ":3:24: note: declared here",
212 ":12:35: note: struct requires comptime because of this field",212 ":12:35: note: struct requires comptime because of this field",
213 ":12:35: note: types are not available at runtime",213 ":12:35: note: types are not available at runtime",