aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig10
-rw-r--r--src/Sema.zig55
2 files changed, 43 insertions, 22 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 3652a27927..42b36b5a04 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1376,6 +1376,16 @@ pub const Scope = struct {
});
}
+ pub fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref {
+ return block.addInst(.{
+ .tag = .arg,
+ .data = .{ .ty_str = .{
+ .ty = try block.sema.addType(ty),
+ .str = name,
+ } },
+ });
+ }
+
pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref {
return Air.indexToRef(try block.addInstAsIndex(inst));
}
diff --git a/src/Sema.zig b/src/Sema.zig
index 8bf4111566..87df3c375f 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2793,16 +2793,24 @@ fn analyzeCall(
} else if (is_comptime) {
return sema.failWithNeededComptime(block, arg_src);
} else if (is_anytype) {
- const child_arg = try child_sema.addConstant(
- sema.typeOf(arg),
- Value.initTag(.generic_poison),
- );
+ // We insert into the map an instruction which is runtime-known
+ // but has the type of the comptime argument.
+ const child_arg = try child_block.addArg(sema.typeOf(arg), 0);
child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
}
arg_i += 1;
}
- const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body);
- const new_func_val = try child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst);
+ const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body) catch |err| {
+ // TODO look up the compile error that happened here and attach a note to it
+ // pointing here, at the generic instantiation callsite.
+ if (sema.owner_func) |owner_func| {
+ owner_func.state = .dependency_failure;
+ } else {
+ sema.owner_decl.analysis = .dependency_failure;
+ }
+ return err;
+ };
+ const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst) catch unreachable;
const new_func = new_func_val.castTag(.function).?.data;
assert(new_func == new_module_func);
@@ -2813,12 +2821,22 @@ fn analyzeCall(
else => continue,
}
const arg = child_sema.inst_map.get(inst).?;
- const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(&child_block, .unneeded, arg) catch unreachable).?;
-
- child_sema.comptime_args[arg_i] = .{
- .ty = try child_sema.typeOf(arg).copy(&new_decl_arena.allocator),
- .val = try arg_val.copy(&new_decl_arena.allocator),
- };
+ const copied_arg_ty = try child_sema.typeOf(arg).copy(&new_decl_arena.allocator);
+ if (child_sema.resolveMaybeUndefValAllowVariables(
+ &child_block,
+ .unneeded,
+ arg,
+ ) catch unreachable) |arg_val| {
+ child_sema.comptime_args[arg_i] = .{
+ .ty = copied_arg_ty,
+ .val = try arg_val.copy(&new_decl_arena.allocator),
+ };
+ } else {
+ child_sema.comptime_args[arg_i] = .{
+ .ty = copied_arg_ty,
+ .val = Value.initTag(.generic_poison),
+ };
+ }
arg_i += 1;
}
@@ -2828,17 +2846,10 @@ fn analyzeCall(
new_decl.val = try Value.Tag.function.create(&new_decl_arena.allocator, new_func);
new_decl.analysis = .complete;
- if (new_decl.ty.fnInfo().is_generic) {
- // TODO improve this error message. This can happen because of the parameter
- // type expression or return type expression depending on runtime-provided values.
- // The error message should be emitted in zirParam or funcCommon when it
- // is determined that we are trying to instantiate a generic function.
- return mod.fail(&block.base, call_src, "unable to monomorphize function", .{});
- }
-
log.debug("generic function '{s}' instantiated with type {}", .{
new_decl.name, new_decl.ty,
});
+ assert(!new_decl.ty.fnInfo().is_generic);
// The generic function Decl is guaranteed to be the first dependency
// of each of its instantiations.
@@ -8371,8 +8382,8 @@ fn analyzeDeclVal(
fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
try sema.mod.declareDeclDependency(sema.owner_decl, decl);
sema.mod.ensureDeclAnalyzed(decl) catch |err| {
- if (sema.func) |func| {
- func.state = .dependency_failure;
+ if (sema.owner_func) |owner_func| {
+ owner_func.state = .dependency_failure;
} else {
sema.owner_decl.analysis = .dependency_failure;
}