authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-06 17:26:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-06 17:26:37-07:00
loge974d4c4295c4fbdbc239caa2cf2d653f65662f1
treecd69c982cb6d80d6a1c2076c9552ed36b4e98816
parentede76f4fe31e6fc935ae10f030eb2c97ed36aaaa

stage2: get rid of "unable to monomorphize function" error

This commit solves the problem in a much simpler way: putting runtime-known values in place of non-comptime arguments when instantiating a generic function.

2 files changed, 43 insertions(+), 22 deletions(-)

src/Module.zig+10
......@@ -1376,6 +1376,16 @@ pub const Scope = struct {
13761376 });
13771377 }
13781378
1379 pub fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref {
1380 return block.addInst(.{
1381 .tag = .arg,
1382 .data = .{ .ty_str = .{
1383 .ty = try block.sema.addType(ty),
1384 .str = name,
1385 } },
1386 });
1387 }
1388
13791389 pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref {
13801390 return Air.indexToRef(try block.addInstAsIndex(inst));
13811391 }
src/Sema.zig+33-22
......@@ -2793,16 +2793,24 @@ fn analyzeCall(
27932793 } else if (is_comptime) {
27942794 return sema.failWithNeededComptime(block, arg_src);
27952795 } else if (is_anytype) {
2796 const child_arg = try child_sema.addConstant(
2797 sema.typeOf(arg),
2798 Value.initTag(.generic_poison),
2799 );
2796 // We insert into the map an instruction which is runtime-known
2797 // but has the type of the comptime argument.
2798 const child_arg = try child_block.addArg(sema.typeOf(arg), 0);
28002799 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
28012800 }
28022801 arg_i += 1;
28032802 }
2804 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body);
2805 const new_func_val = try child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst);
2803 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body) catch |err| {
2804 // TODO look up the compile error that happened here and attach a note to it
2805 // pointing here, at the generic instantiation callsite.
2806 if (sema.owner_func) |owner_func| {
2807 owner_func.state = .dependency_failure;
2808 } else {
2809 sema.owner_decl.analysis = .dependency_failure;
2810 }
2811 return err;
2812 };
2813 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst) catch unreachable;
28062814 const new_func = new_func_val.castTag(.function).?.data;
28072815 assert(new_func == new_module_func);
28082816
......@@ -2813,12 +2821,22 @@ fn analyzeCall(
28132821 else => continue,
28142822 }
28152823 const arg = child_sema.inst_map.get(inst).?;
2816 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(&child_block, .unneeded, arg) catch unreachable).?;
2817
2818 child_sema.comptime_args[arg_i] = .{
2819 .ty = try child_sema.typeOf(arg).copy(&new_decl_arena.allocator),
2820 .val = try arg_val.copy(&new_decl_arena.allocator),
2821 };
2824 const copied_arg_ty = try child_sema.typeOf(arg).copy(&new_decl_arena.allocator);
2825 if (child_sema.resolveMaybeUndefValAllowVariables(
2826 &child_block,
2827 .unneeded,
2828 arg,
2829 ) catch unreachable) |arg_val| {
2830 child_sema.comptime_args[arg_i] = .{
2831 .ty = copied_arg_ty,
2832 .val = try arg_val.copy(&new_decl_arena.allocator),
2833 };
2834 } else {
2835 child_sema.comptime_args[arg_i] = .{
2836 .ty = copied_arg_ty,
2837 .val = Value.initTag(.generic_poison),
2838 };
2839 }
28222840
28232841 arg_i += 1;
28242842 }
......@@ -2828,17 +2846,10 @@ fn analyzeCall(
28282846 new_decl.val = try Value.Tag.function.create(&new_decl_arena.allocator, new_func);
28292847 new_decl.analysis = .complete;
28302848
2831 if (new_decl.ty.fnInfo().is_generic) {
2832 // TODO improve this error message. This can happen because of the parameter
2833 // type expression or return type expression depending on runtime-provided values.
2834 // The error message should be emitted in zirParam or funcCommon when it
2835 // is determined that we are trying to instantiate a generic function.
2836 return mod.fail(&block.base, call_src, "unable to monomorphize function", .{});
2837 }
2838
28392849 log.debug("generic function '{s}' instantiated with type {}", .{
28402850 new_decl.name, new_decl.ty,
28412851 });
2852 assert(!new_decl.ty.fnInfo().is_generic);
28422853
28432854 // The generic function Decl is guaranteed to be the first dependency
28442855 // of each of its instantiations.
......@@ -8371,8 +8382,8 @@ fn analyzeDeclVal(
83718382fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
83728383 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
83738384 sema.mod.ensureDeclAnalyzed(decl) catch |err| {
8374 if (sema.func) |func| {
8375 func.state = .dependency_failure;
8385 if (sema.owner_func) |owner_func| {
8386 owner_func.state = .dependency_failure;
83768387 } else {
83778388 sema.owner_decl.analysis = .dependency_failure;
83788389 }