authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-12 20:30:11-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-12 18:24:01-07:00
log3d48c406c18d6bcc579130d7cac91d47cc119dd8
treed89b8a339c355062fa2b7a86ca397131474161de
parent52e7934a21e29b5a39fa207ef29520f58e311bb0

Sema: redo monomorphed funcs to make more sense

By correctly handling comptime-only types appearing in non-comptime parameters (when the parameter is either anytype or generic), this avoids an index out of bounds later when later filling out `monomorphed_args` using what used to be slightly different logic.

1 files changed, 86 insertions(+), 94 deletions(-)

src/Sema.zig+86-94
......@@ -6748,7 +6748,7 @@ fn analyzeCall(
67486748 func,
67496749 func_src,
67506750 call_src,
6751 func_ty_info,
6751 func_ty,
67526752 ensure_result_used,
67536753 uncasted_args,
67546754 call_tag,
......@@ -7367,8 +7367,16 @@ fn analyzeGenericCallArg(
73677367 }
73687368}
73697369
7370fn analyzeGenericCallArgVal(sema: *Sema, block: *Block, arg_src: LazySrcLoc, uncasted_arg: Air.Inst.Ref) !Value {
7371 return sema.resolveLazyValue(try sema.resolveValue(block, arg_src, uncasted_arg, "parameter is comptime"));
7370fn analyzeGenericCallArgVal(
7371 sema: *Sema,
7372 block: *Block,
7373 arg_src: LazySrcLoc,
7374 arg_ty: Type,
7375 uncasted_arg: Air.Inst.Ref,
7376 reason: []const u8,
7377) !Value {
7378 const casted_arg = try sema.coerce(block, arg_ty, uncasted_arg, arg_src);
7379 return sema.resolveLazyValue(try sema.resolveValue(block, arg_src, casted_arg, reason));
73727380}
73737381
73747382fn instantiateGenericCall(
......@@ -7377,7 +7385,7 @@ fn instantiateGenericCall(
73777385 func: Air.Inst.Ref,
73787386 func_src: LazySrcLoc,
73797387 call_src: LazySrcLoc,
7380 func_ty_info: InternPool.Key.FuncType,
7388 generic_func_ty: Type,
73817389 ensure_result_used: bool,
73827390 uncasted_args: []const Air.Inst.Ref,
73837391 call_tag: Air.Inst.Tag,
......@@ -7404,24 +7412,25 @@ fn instantiateGenericCall(
74047412 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
74057413 const zir_tags = fn_zir.instructions.items(.tag);
74067414
7407 const generic_args = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
7415 const monomorphed_args = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(generic_func_ty).?.param_types.len);
74087416 const callee_index = callee: {
74097417 var arg_i: usize = 0;
7410 var generic_arg_i: u32 = 0;
7418 var monomorphed_arg_i: u32 = 0;
74117419 var known_unique = false;
74127420 for (fn_info.param_body) |inst| {
7421 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
74137422 var is_comptime = false;
74147423 var is_anytype = false;
74157424 switch (zir_tags[inst]) {
74167425 .param => {
7417 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7426 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
74187427 },
74197428 .param_comptime => {
74207429 is_comptime = true;
74217430 },
74227431 .param_anytype => {
74237432 is_anytype = true;
7424 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7433 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
74257434 },
74267435 .param_anytype_comptime => {
74277436 is_anytype = true;
......@@ -7431,69 +7440,60 @@ fn instantiateGenericCall(
74317440 }
74327441
74337442 defer arg_i += 1;
7443 const param_ty = generic_func_ty_info.param_types[arg_i];
7444 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7445
74347446 if (known_unique) {
7435 if (is_comptime or is_anytype) {
7436 generic_arg_i += 1;
7447 if (is_comptime or is_anytype or is_generic) {
7448 monomorphed_arg_i += 1;
74377449 }
74387450 continue;
74397451 }
74407452
7441 const arg_ty = sema.typeOf(uncasted_args[arg_i]);
7453 const uncasted_arg = uncasted_args[arg_i];
7454 const arg_ty = if (is_generic) mod.monomorphed_funcs.getAdapted(
7455 Module.MonomorphedFuncAdaptedKey{
7456 .func = module_fn_index,
7457 .args = monomorphed_args[0..monomorphed_arg_i],
7458 },
7459 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7460 ) orelse {
7461 known_unique = true;
7462 monomorphed_arg_i += 1;
7463 continue;
7464 } else if (is_anytype) sema.typeOf(uncasted_arg).toIntern() else param_ty;
7465 const was_comptime = is_comptime;
7466 if (!is_comptime and try sema.typeRequiresComptime(arg_ty.toType())) is_comptime = true;
74427467 if (is_comptime or is_anytype) {
74437468 // Tuple default values are a part of the type and need to be
74447469 // resolved to hash the type.
7445 try sema.resolveTupleLazyValues(block, call_src, arg_ty);
7470 try sema.resolveTupleLazyValues(block, call_src, arg_ty.toType());
74467471 }
74477472
74487473 if (is_comptime) {
7449 const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[arg_i]) catch |err| switch (err) {
7474 const casted_arg = sema.analyzeGenericCallArgVal(block, .unneeded, arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) {
74507475 error.NeededSourceLocation => {
74517476 const decl = mod.declPtr(block.src_decl);
74527477 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7453 _ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[arg_i]);
7478 _ = try sema.analyzeGenericCallArgVal(
7479 block,
7480 arg_src,
7481 arg_ty.toType(),
7482 uncasted_arg,
7483 if (was_comptime)
7484 "parameter is comptime"
7485 else
7486 "argument to parameter with comptime-only type must be comptime-known",
7487 );
74547488 unreachable;
74557489 },
74567490 else => |e| return e,
74577491 };
7458
7459 if (is_anytype) {
7460 generic_args[generic_arg_i] = arg_val.toIntern();
7461 } else {
7462 const final_arg_ty = mod.monomorphed_funcs.getAdapted(
7463 Module.MonomorphedFuncAdaptedKey{
7464 .func = module_fn_index,
7465 .args = generic_args[0..generic_arg_i],
7466 },
7467 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7468 ) orelse {
7469 known_unique = true;
7470 generic_arg_i += 1;
7471 continue;
7472 };
7473 const casted_arg = sema.coerce(block, final_arg_ty.toType(), uncasted_args[arg_i], .unneeded) catch |err| switch (err) {
7474 error.NeededSourceLocation => {
7475 const decl = mod.declPtr(block.src_decl);
7476 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7477 _ = try sema.coerce(block, final_arg_ty.toType(), uncasted_args[arg_i], arg_src);
7478 unreachable;
7479 },
7480 else => |e| return e,
7481 };
7482 const casted_arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, casted_arg) catch |err| switch (err) {
7483 error.NeededSourceLocation => {
7484 const decl = mod.declPtr(block.src_decl);
7485 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7486 _ = try sema.analyzeGenericCallArgVal(block, arg_src, casted_arg);
7487 unreachable;
7488 },
7489 else => |e| return e,
7490 };
7491 generic_args[generic_arg_i] = casted_arg_val.toIntern();
7492 }
7493 generic_arg_i += 1;
7494 } else if (is_anytype) {
7495 generic_args[generic_arg_i] = arg_ty.toIntern();
7496 generic_arg_i += 1;
7492 monomorphed_args[monomorphed_arg_i] = casted_arg.toIntern();
7493 monomorphed_arg_i += 1;
7494 } else if (is_anytype or is_generic) {
7495 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty });
7496 monomorphed_arg_i += 1;
74977497 }
74987498 }
74997499
......@@ -7501,7 +7501,7 @@ fn instantiateGenericCall(
75017501 if (mod.monomorphed_funcs.getAdapted(
75027502 Module.MonomorphedFuncAdaptedKey{
75037503 .func = module_fn_index,
7504 .args = generic_args[0..generic_arg_i],
7504 .args = monomorphed_args[0..monomorphed_arg_i],
75057505 },
75067506 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
75077507 )) |callee_func| break :callee mod.intern_pool.indexToKey(callee_func).func.index;
......@@ -7550,11 +7550,11 @@ fn instantiateGenericCall(
75507550 new_decl,
75517551 new_decl_index,
75527552 uncasted_args,
7553 generic_arg_i,
7553 monomorphed_arg_i,
75547554 module_fn_index,
75557555 new_module_func_index,
75567556 namespace_index,
7557 func_ty_info,
7557 generic_func_ty,
75587558 call_src,
75597559 bound_arg_src,
75607560 ) catch |err| switch (err) {
......@@ -7673,11 +7673,11 @@ fn resolveGenericInstantiationType(
76737673 new_decl: *Decl,
76747674 new_decl_index: Decl.Index,
76757675 uncasted_args: []const Air.Inst.Ref,
7676 generic_args_len: u32,
7676 monomorphed_args_len: u32,
76777677 module_fn_index: Module.Fn.Index,
76787678 new_module_func: Module.Fn.Index,
76797679 namespace: Namespace.Index,
7680 func_ty_info: InternPool.Key.FuncType,
7680 generic_func_ty: Type,
76817681 call_src: LazySrcLoc,
76827682 bound_arg_src: ?LazySrcLoc,
76837683) !Module.Fn.Index {
......@@ -7737,18 +7737,19 @@ fn resolveGenericInstantiationType(
77377737
77387738 var arg_i: usize = 0;
77397739 for (fn_info.param_body) |inst| {
7740 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
77407741 var is_comptime = false;
77417742 var is_anytype = false;
77427743 switch (zir_tags[inst]) {
77437744 .param => {
7744 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7745 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77457746 },
77467747 .param_comptime => {
77477748 is_comptime = true;
77487749 },
77497750 .param_anytype => {
77507751 is_anytype = true;
7751 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7752 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77527753 },
77537754 .param_anytype_comptime => {
77547755 is_anytype = true;
......@@ -7802,25 +7803,26 @@ fn resolveGenericInstantiationType(
78027803 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
78037804 assert(new_func == new_module_func);
78047805
7805 const generic_args_index = @intCast(u32, mod.monomorphed_func_keys.items.len);
7806 const generic_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, generic_args_len);
7807 var generic_arg_i: u32 = 0;
7808 try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, generic_args_len + 1, .{ .mod = mod });
7806 const monomorphed_args_index = @intCast(u32, mod.monomorphed_func_keys.items.len);
7807 const monomorphed_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, monomorphed_args_len);
7808 var monomorphed_arg_i: u32 = 0;
7809 try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, monomorphed_args_len + 1, .{ .mod = mod });
78097810
78107811 arg_i = 0;
78117812 for (fn_info.param_body) |inst| {
7813 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
78127814 var is_comptime = false;
78137815 var is_anytype = false;
78147816 switch (zir_tags[inst]) {
78157817 .param => {
7816 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7818 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
78177819 },
78187820 .param_comptime => {
78197821 is_comptime = true;
78207822 },
78217823 .param_anytype => {
78227824 is_anytype = true;
7823 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7825 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
78247826 },
78257827 .param_anytype_comptime => {
78267828 is_anytype = true;
......@@ -7829,40 +7831,30 @@ fn resolveGenericInstantiationType(
78297831 else => continue,
78307832 }
78317833
7832 // We populate the Type here regardless because it is needed by
7833 // `GenericCallAdapter.eql` as well as function body analysis.
7834 // Whether it is anytype is communicated by `isAnytypeParam`.
7834 const param_ty = generic_func_ty_info.param_types[arg_i];
7835 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7836
78357837 const arg = child_sema.inst_map.get(inst).?;
78367838 const arg_ty = child_sema.typeOf(arg);
78377839
7838 if (try sema.typeRequiresComptime(arg_ty)) {
7839 is_comptime = true;
7840 }
7840 if (is_generic) if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{
7841 .func = module_fn_index,
7842 .args_index = monomorphed_args_index,
7843 .args_len = monomorphed_arg_i,
7844 }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern());
7845 if (!is_comptime and try sema.typeRequiresComptime(arg_ty)) is_comptime = true;
78417846
78427847 if (is_comptime) {
78437848 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7844 if (!is_anytype) {
7845 if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{
7846 .func = module_fn_index,
7847 .args_index = generic_args_index,
7848 .args_len = generic_arg_i,
7849 }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern());
7850 }
7851 generic_args[generic_arg_i] = arg_val.toIntern();
7852 generic_arg_i += 1;
7853 child_sema.comptime_args[arg_i] = .{
7854 .ty = arg_ty,
7855 .val = (try arg_val.intern(arg_ty, mod)).toValue(),
7856 };
7849 monomorphed_args[monomorphed_arg_i] = arg_val.toIntern();
7850 monomorphed_arg_i += 1;
7851 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = arg_val };
78577852 } else {
7858 if (is_anytype) {
7859 generic_args[generic_arg_i] = arg_ty.toIntern();
7860 generic_arg_i += 1;
7853 if (is_anytype or is_generic) {
7854 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty.toIntern() });
7855 monomorphed_arg_i += 1;
78617856 }
7862 child_sema.comptime_args[arg_i] = .{
7863 .ty = arg_ty,
7864 .val = Value.generic_poison,
7865 };
7857 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = Value.generic_poison };
78667858 }
78677859
78687860 arg_i += 1;
......@@ -7895,8 +7887,8 @@ fn resolveGenericInstantiationType(
78957887
78967888 mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{
78977889 .func = module_fn_index,
7898 .args_index = generic_args_index,
7899 .args_len = generic_arg_i,
7890 .args_index = monomorphed_args_index,
7891 .args_len = monomorphed_arg_i,
79007892 }, new_decl.val.toIntern(), .{ .mod = mod });
79017893
79027894 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field