authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-30 15:44:28+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-03 18:38:15+02:00
logabd005f302ee81213b3f3a97a08d025cb3b1ecee
treefa30badad6a8e4e8af338e33fea1fb35e3c427e0
parentdaeb992c7346cf3ecaca9e0bcbee20737b005eaa

Sema: do not immediately destroy failed generic instantiation

Closes #12535 Closes #12765 Closes #12927

5 files changed, 331 insertions(+), 221 deletions(-)

src/Module.zig+14-13
......@@ -3540,8 +3540,8 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
35403540 if (decl.getInnerNamespace()) |namespace| {
35413541 namespace.destroyDecls(mod);
35423542 }
3543 decl.clearValues(mod);
35443543 }
3544 decl.clearValues(mod);
35453545 decl.dependants.deinit(gpa);
35463546 decl.dependencies.deinit(gpa);
35473547 decl.clearName(gpa);
......@@ -4610,9 +4610,18 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46104610
46114611 // We need the memory for the Type to go into the arena for the Decl
46124612 var decl_arena = std.heap.ArenaAllocator.init(gpa);
4613 errdefer decl_arena.deinit();
46144613 const decl_arena_allocator = decl_arena.allocator();
46154614
4615 const decl_arena_state = blk: {
4616 errdefer decl_arena.deinit();
4617 const s = try decl_arena_allocator.create(std.heap.ArenaAllocator.State);
4618 break :blk s;
4619 };
4620 defer {
4621 decl_arena_state.* = decl_arena.state;
4622 decl.value_arena = decl_arena_state;
4623 }
4624
46164625 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
46174626 defer analysis_arena.deinit();
46184627 const analysis_arena_allocator = analysis_arena.allocator();
......@@ -4681,8 +4690,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46814690 // not the struct itself.
46824691 try sema.resolveTypeLayout(decl_tv.ty);
46834692
4684 const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State);
4685
46864693 if (decl.is_usingnamespace) {
46874694 if (!decl_tv.ty.eql(Type.type, mod)) {
46884695 return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
......@@ -4701,8 +4708,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47014708 decl.@"linksection" = null;
47024709 decl.has_tv = true;
47034710 decl.owns_tv = false;
4704 decl_arena_state.* = decl_arena.state;
4705 decl.value_arena = decl_arena_state;
47064711 decl.analysis = .complete;
47074712 decl.generation = mod.generation;
47084713
......@@ -4723,16 +4728,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47234728 if (decl.getFunction()) |prev_func| {
47244729 prev_is_inline = prev_func.state == .inline_only;
47254730 }
4726 decl.clearValues(mod);
47274731 }
4732 decl.clearValues(mod);
47284733
47294734 decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
47304735 decl.val = try decl_tv.val.copy(decl_arena_allocator);
47314736 // linksection, align, and addrspace were already set by Sema
47324737 decl.has_tv = true;
47334738 decl.owns_tv = owns_tv;
4734 decl_arena_state.* = decl_arena.state;
4735 decl.value_arena = decl_arena_state;
47364739 decl.analysis = .complete;
47374740 decl.generation = mod.generation;
47384741
......@@ -4767,8 +4770,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47674770 var type_changed = true;
47684771 if (decl.has_tv) {
47694772 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4770 decl.clearValues(mod);
47714773 }
4774 decl.clearValues(mod);
47724775
47734776 decl.owns_tv = false;
47744777 var queue_linker_work = false;
......@@ -4841,8 +4844,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
48414844 };
48424845 };
48434846 decl.has_tv = true;
4844 decl_arena_state.* = decl_arena.state;
4845 decl.value_arena = decl_arena_state;
48464847 decl.analysis = .complete;
48474848 decl.generation = mod.generation;
48484849
......@@ -5447,8 +5448,8 @@ pub fn clearDecl(
54475448 if (decl.getInnerNamespace()) |namespace| {
54485449 try namespace.deleteAllDecls(mod, outdated_decls);
54495450 }
5450 decl.clearValues(mod);
54515451 }
5452 decl.clearValues(mod);
54525453
54535454 if (decl.deletion_flag) {
54545455 decl.deletion_flag = false;
src/Sema.zig+254-208
......@@ -7112,7 +7112,6 @@ fn instantiateGenericCall(
71127112 const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter);
71137113 const callee = if (!gop.found_existing) callee: {
71147114 const new_module_func = try gpa.create(Module.Fn);
7115 errdefer gpa.destroy(new_module_func);
71167115
71177116 // This ensures that we can operate on the hash map before the Module.Fn
71187117 // struct is fully initialized.
......@@ -7120,7 +7119,6 @@ fn instantiateGenericCall(
71207119 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
71217120 new_module_func.comptime_args = null;
71227121 gop.key_ptr.* = new_module_func;
7123 errdefer assert(mod.monomorphed_funcs.remove(new_module_func));
71247122
71257123 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
71267124
......@@ -7128,7 +7126,6 @@ fn instantiateGenericCall(
71287126 const src_decl_index = namespace.getDeclIndex();
71297127 const src_decl = mod.declPtr(src_decl_index);
71307128 const new_decl_index = try mod.allocateNewDecl(namespace, fn_owner_decl.src_node, src_decl.src_scope);
7131 errdefer mod.destroyDecl(new_decl_index);
71327129 const new_decl = mod.declPtr(new_decl_index);
71337130 // TODO better names for generic function instantiations
71347131 const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{
......@@ -7148,223 +7145,59 @@ fn instantiateGenericCall(
71487145 new_decl.generation = mod.generation;
71497146
71507147 namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {});
7151 errdefer assert(namespace.anon_decls.orderedRemove(new_decl_index));
71527148
71537149 // The generic function Decl is guaranteed to be the first dependency
71547150 // of each of its instantiations.
71557151 assert(new_decl.dependencies.keys().len == 0);
71567152 try mod.declareDeclDependency(new_decl_index, module_fn.owner_decl);
7157 // Resolving the new function type below will possibly declare more decl dependencies
7158 // and so we remove them all here in case of error.
7159 errdefer {
7160 for (new_decl.dependencies.keys()) |dep_index| {
7161 const dep = mod.declPtr(dep_index);
7162 dep.removeDependant(new_decl_index);
7163 }
7164 }
71657153
71667154 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
7167 errdefer new_decl_arena.deinit();
71687155 const new_decl_arena_allocator = new_decl_arena.allocator();
71697156
7170 // Re-run the block that creates the function, with the comptime parameters
7171 // pre-populated inside `inst_map`. This causes `param_comptime` and
7172 // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a
7173 // new, monomorphized function, with the comptime parameters elided.
7174 var child_sema: Sema = .{
7175 .mod = mod,
7176 .gpa = gpa,
7177 .arena = sema.arena,
7178 .perm_arena = new_decl_arena_allocator,
7179 .code = fn_zir,
7180 .owner_decl = new_decl,
7181 .owner_decl_index = new_decl_index,
7182 .func = null,
7183 .fn_ret_ty = Type.void,
7184 .owner_func = null,
7185 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
7186 .comptime_args_fn_inst = module_fn.zir_body_inst,
7187 .preallocated_new_func = new_module_func,
7188 .is_generic_instantiation = true,
7189 .branch_quota = sema.branch_quota,
7190 .branch_count = sema.branch_count,
7191 };
7192 defer child_sema.deinit();
7193
7194 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
7195 defer wip_captures.deinit();
7196
7197 var child_block: Block = .{
7198 .parent = null,
7199 .sema = &child_sema,
7200 .src_decl = new_decl_index,
7201 .namespace = namespace,
7202 .wip_capture_scope = wip_captures.scope,
7203 .instructions = .{},
7204 .inlining = null,
7205 .is_comptime = true,
7206 };
7207 defer {
7208 child_block.instructions.deinit(gpa);
7209 child_block.params.deinit(gpa);
7210 }
7211
7212 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
7213
7214 var arg_i: usize = 0;
7215 for (fn_info.param_body) |inst| {
7216 var is_comptime = false;
7217 var is_anytype = false;
7218 switch (zir_tags[inst]) {
7219 .param => {
7220 is_comptime = func_ty_info.paramIsComptime(arg_i);
7221 },
7222 .param_comptime => {
7223 is_comptime = true;
7224 },
7225 .param_anytype => {
7226 is_anytype = true;
7227 is_comptime = func_ty_info.paramIsComptime(arg_i);
7228 },
7229 .param_anytype_comptime => {
7230 is_anytype = true;
7231 is_comptime = true;
7232 },
7233 else => continue,
7234 }
7235 const arg = uncasted_args[arg_i];
7236 if (is_comptime) {
7237 const arg_val = (try sema.resolveMaybeUndefVal(arg)).?;
7238 const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
7239 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7240 } else if (is_anytype) {
7241 const arg_ty = sema.typeOf(arg);
7242 if (try sema.typeRequiresComptime(arg_ty)) {
7243 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
7244 error.NeededSourceLocation => {
7245 const decl = sema.mod.declPtr(block.src_decl);
7246 const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src);
7247 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
7248 unreachable;
7249 },
7250 else => |e| return e,
7251 };
7252 const child_arg = try child_sema.addConstant(arg_ty, arg_val);
7253 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7157 const new_func = sema.resolveGenericInstantiationType(
7158 block,
7159 new_decl_arena_allocator,
7160 fn_zir,
7161 new_decl,
7162 new_decl_index,
7163 uncasted_args,
7164 module_fn,
7165 new_module_func,
7166 namespace,
7167 func_ty_info,
7168 call_src,
7169 bound_arg_src,
7170 ) catch |err| switch (err) {
7171 error.GenericPoison, error.ComptimeReturn => {
7172 new_decl_arena.deinit();
7173 // Resolving the new function type below will possibly declare more decl dependencies
7174 // and so we remove them all here in case of error.
7175 for (new_decl.dependencies.keys()) |dep_index| {
7176 const dep = mod.declPtr(dep_index);
7177 dep.removeDependant(new_decl_index);
7178 }
7179 assert(namespace.anon_decls.orderedRemove(new_decl_index));
7180 mod.destroyDecl(new_decl_index);
7181 assert(mod.monomorphed_funcs.remove(new_module_func));
7182 gpa.destroy(new_module_func);
7183 return err;
7184 },
7185 else => {
7186 {
7187 errdefer new_decl_arena.deinit();
7188 try new_decl.finalizeNewArena(&new_decl_arena);
7189 }
7190 // TODO look up the compile error that happened here and attach a note to it
7191 // pointing here, at the generic instantiation callsite.
7192 if (sema.owner_func) |owner_func| {
7193 owner_func.state = .dependency_failure;
72547194 } else {
7255 // We insert into the map an instruction which is runtime-known
7256 // but has the type of the argument.
7257 const child_arg = try child_block.addInst(.{
7258 .tag = .arg,
7259 .data = .{ .arg = .{
7260 .ty = try child_sema.addType(arg_ty),
7261 .src_index = @intCast(u32, arg_i),
7262 } },
7263 });
7264 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7195 sema.owner_decl.analysis = .dependency_failure;
72657196 }
7266 }
7267 arg_i += 1;
7268 }
7269
7270 // Save the error trace as our first action in the function.
7271 // If this is unnecessary after all, Liveness will clean it up for us.
7272 const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block);
7273 child_sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
7274 child_block.error_return_trace_index = error_return_trace_index;
7275
7276 const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst) catch |err| {
7277 if (err == error.GenericPoison) return error.GenericPoison;
7278 // TODO look up the compile error that happened here and attach a note to it
7279 // pointing here, at the generic instantiation callsite.
7280 if (sema.owner_func) |owner_func| {
7281 owner_func.state = .dependency_failure;
7282 } else {
7283 sema.owner_decl.analysis = .dependency_failure;
7284 }
7285 return err;
7197 return err;
7198 },
72867199 };
7287 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, "") catch unreachable;
7288 const new_func = new_func_val.castTag(.function).?.data;
7289 errdefer new_func.deinit(gpa);
7290 assert(new_func == new_module_func);
7291
7292 arg_i = 0;
7293 for (fn_info.param_body) |inst| {
7294 var is_comptime = false;
7295 switch (zir_tags[inst]) {
7296 .param => {
7297 is_comptime = func_ty_info.paramIsComptime(arg_i);
7298 },
7299 .param_comptime => {
7300 is_comptime = true;
7301 },
7302 .param_anytype => {
7303 is_comptime = func_ty_info.paramIsComptime(arg_i);
7304 },
7305 .param_anytype_comptime => {
7306 is_comptime = true;
7307 },
7308 else => continue,
7309 }
7310
7311 // We populate the Type here regardless because it is needed by
7312 // `GenericCallAdapter.eql` as well as function body analysis.
7313 // Whether it is anytype is communicated by `isAnytypeParam`.
7314 const arg = child_sema.inst_map.get(inst).?;
7315 const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator);
7316
7317 if (try sema.typeRequiresComptime(copied_arg_ty)) {
7318 is_comptime = true;
7319 }
7320
7321 if (is_comptime) {
7322 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7323 child_sema.comptime_args[arg_i] = .{
7324 .ty = copied_arg_ty,
7325 .val = try arg_val.copy(new_decl_arena_allocator),
7326 };
7327 } else {
7328 child_sema.comptime_args[arg_i] = .{
7329 .ty = copied_arg_ty,
7330 .val = Value.initTag(.generic_poison),
7331 };
7332 }
7333
7334 arg_i += 1;
7335 }
7336
7337 try wip_captures.finalize();
7338
7339 // Populate the Decl ty/val with the function and its type.
7340 new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);
7341 // If the call evaluated to a return type that requires comptime, never mind
7342 // our generic instantiation. Instead we need to perform a comptime call.
7343 const new_fn_info = new_decl.ty.fnInfo();
7344 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {
7345 return error.ComptimeReturn;
7346 }
7347 // Similarly, if the call evaluated to a generic type we need to instead
7348 // call it inline.
7349 if (new_fn_info.is_generic or new_fn_info.cc == .Inline) {
7350 return error.GenericPoison;
7351 }
7352
7353 new_decl.val = try Value.Tag.function.create(new_decl_arena_allocator, new_func);
7354 new_decl.@"align" = 0;
7355 new_decl.has_tv = true;
7356 new_decl.owns_tv = true;
7357 new_decl.analysis = .complete;
7358
7359 log.debug("generic function '{s}' instantiated with type {}", .{
7360 new_decl.name, new_decl.ty.fmtDebug(),
7361 });
7362
7363 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
7364 // will be populated, ensuring it will have `analyzeBody` called with the ZIR
7365 // parameters mapped appropriately.
7366 try mod.comp.bin_file.allocateDeclIndexes(new_decl_index);
7367 try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func });
7200 errdefer new_decl_arena.deinit();
73687201
73697202 try new_decl.finalizeNewArena(&new_decl_arena);
73707203 break :callee new_func;
......@@ -7444,6 +7277,218 @@ fn instantiateGenericCall(
74447277 return result;
74457278}
74467279
7280fn resolveGenericInstantiationType(
7281 sema: *Sema,
7282 block: *Block,
7283 new_decl_arena_allocator: Allocator,
7284 fn_zir: Zir,
7285 new_decl: *Decl,
7286 new_decl_index: Decl.Index,
7287 uncasted_args: []const Air.Inst.Ref,
7288 module_fn: *Module.Fn,
7289 new_module_func: *Module.Fn,
7290 namespace: *Namespace,
7291 func_ty_info: Type.Payload.Function.Data,
7292 call_src: LazySrcLoc,
7293 bound_arg_src: ?LazySrcLoc,
7294) !*Module.Fn {
7295 const mod = sema.mod;
7296 const gpa = sema.gpa;
7297
7298 const zir_tags = fn_zir.instructions.items(.tag);
7299 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
7300
7301 // Re-run the block that creates the function, with the comptime parameters
7302 // pre-populated inside `inst_map`. This causes `param_comptime` and
7303 // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a
7304 // new, monomorphized function, with the comptime parameters elided.
7305 var child_sema: Sema = .{
7306 .mod = mod,
7307 .gpa = gpa,
7308 .arena = sema.arena,
7309 .perm_arena = new_decl_arena_allocator,
7310 .code = fn_zir,
7311 .owner_decl = new_decl,
7312 .owner_decl_index = new_decl_index,
7313 .func = null,
7314 .fn_ret_ty = Type.void,
7315 .owner_func = null,
7316 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
7317 .comptime_args_fn_inst = module_fn.zir_body_inst,
7318 .preallocated_new_func = new_module_func,
7319 .is_generic_instantiation = true,
7320 .branch_quota = sema.branch_quota,
7321 .branch_count = sema.branch_count,
7322 };
7323 defer child_sema.deinit();
7324
7325 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
7326 defer wip_captures.deinit();
7327
7328 var child_block: Block = .{
7329 .parent = null,
7330 .sema = &child_sema,
7331 .src_decl = new_decl_index,
7332 .namespace = namespace,
7333 .wip_capture_scope = wip_captures.scope,
7334 .instructions = .{},
7335 .inlining = null,
7336 .is_comptime = true,
7337 };
7338 defer {
7339 child_block.instructions.deinit(gpa);
7340 child_block.params.deinit(gpa);
7341 }
7342
7343 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
7344
7345 var arg_i: usize = 0;
7346 for (fn_info.param_body) |inst| {
7347 var is_comptime = false;
7348 var is_anytype = false;
7349 switch (zir_tags[inst]) {
7350 .param => {
7351 is_comptime = func_ty_info.paramIsComptime(arg_i);
7352 },
7353 .param_comptime => {
7354 is_comptime = true;
7355 },
7356 .param_anytype => {
7357 is_anytype = true;
7358 is_comptime = func_ty_info.paramIsComptime(arg_i);
7359 },
7360 .param_anytype_comptime => {
7361 is_anytype = true;
7362 is_comptime = true;
7363 },
7364 else => continue,
7365 }
7366 const arg = uncasted_args[arg_i];
7367 if (is_comptime) {
7368 const arg_val = (try sema.resolveMaybeUndefVal(arg)).?;
7369 const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
7370 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7371 } else if (is_anytype) {
7372 const arg_ty = sema.typeOf(arg);
7373 if (try sema.typeRequiresComptime(arg_ty)) {
7374 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
7375 error.NeededSourceLocation => {
7376 const decl = sema.mod.declPtr(block.src_decl);
7377 const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src);
7378 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
7379 unreachable;
7380 },
7381 else => |e| return e,
7382 };
7383 const child_arg = try child_sema.addConstant(arg_ty, arg_val);
7384 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7385 } else {
7386 // We insert into the map an instruction which is runtime-known
7387 // but has the type of the argument.
7388 const child_arg = try child_block.addInst(.{
7389 .tag = .arg,
7390 .data = .{ .arg = .{
7391 .ty = try child_sema.addType(arg_ty),
7392 .src_index = @intCast(u32, arg_i),
7393 } },
7394 });
7395 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7396 }
7397 }
7398 arg_i += 1;
7399 }
7400
7401 // Save the error trace as our first action in the function.
7402 // If this is unnecessary after all, Liveness will clean it up for us.
7403 const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block);
7404 child_sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
7405 child_block.error_return_trace_index = error_return_trace_index;
7406
7407 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7408 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
7409 const new_func = new_func_val.castTag(.function).?.data;
7410 errdefer new_func.deinit(gpa);
7411 assert(new_func == new_module_func);
7412
7413 arg_i = 0;
7414 for (fn_info.param_body) |inst| {
7415 var is_comptime = false;
7416 switch (zir_tags[inst]) {
7417 .param => {
7418 is_comptime = func_ty_info.paramIsComptime(arg_i);
7419 },
7420 .param_comptime => {
7421 is_comptime = true;
7422 },
7423 .param_anytype => {
7424 is_comptime = func_ty_info.paramIsComptime(arg_i);
7425 },
7426 .param_anytype_comptime => {
7427 is_comptime = true;
7428 },
7429 else => continue,
7430 }
7431
7432 // We populate the Type here regardless because it is needed by
7433 // `GenericCallAdapter.eql` as well as function body analysis.
7434 // Whether it is anytype is communicated by `isAnytypeParam`.
7435 const arg = child_sema.inst_map.get(inst).?;
7436 const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator);
7437
7438 if (try sema.typeRequiresComptime(copied_arg_ty)) {
7439 is_comptime = true;
7440 }
7441
7442 if (is_comptime) {
7443 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7444 child_sema.comptime_args[arg_i] = .{
7445 .ty = copied_arg_ty,
7446 .val = try arg_val.copy(new_decl_arena_allocator),
7447 };
7448 } else {
7449 child_sema.comptime_args[arg_i] = .{
7450 .ty = copied_arg_ty,
7451 .val = Value.initTag(.generic_poison),
7452 };
7453 }
7454
7455 arg_i += 1;
7456 }
7457
7458 try wip_captures.finalize();
7459
7460 // Populate the Decl ty/val with the function and its type.
7461 new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);
7462 // If the call evaluated to a return type that requires comptime, never mind
7463 // our generic instantiation. Instead we need to perform a comptime call.
7464 const new_fn_info = new_decl.ty.fnInfo();
7465 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {
7466 return error.ComptimeReturn;
7467 }
7468 // Similarly, if the call evaluated to a generic type we need to instead
7469 // call it inline.
7470 if (new_fn_info.is_generic or new_fn_info.cc == .Inline) {
7471 return error.GenericPoison;
7472 }
7473
7474 new_decl.val = try Value.Tag.function.create(new_decl_arena_allocator, new_func);
7475 new_decl.@"align" = 0;
7476 new_decl.has_tv = true;
7477 new_decl.owns_tv = true;
7478 new_decl.analysis = .complete;
7479
7480 log.debug("generic function '{s}' instantiated with type {}", .{
7481 new_decl.name, new_decl.ty.fmtDebug(),
7482 });
7483
7484 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
7485 // will be populated, ensuring it will have `analyzeBody` called with the ZIR
7486 // parameters mapped appropriately.
7487 try mod.comp.bin_file.allocateDeclIndexes(new_decl_index);
7488 try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func });
7489 return new_func;
7490}
7491
74477492fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
74487493 if (!ty.isSimpleTuple()) return;
74497494 const tuple = ty.tupleFields();
......@@ -11506,6 +11551,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
1150611551 .dbg_block_begin,
1150711552 .dbg_block_end,
1150811553 .dbg_stmt,
11554 .save_err_ret_index,
1150911555 => {},
1151011556 .@"unreachable" => break inst,
1151111557 else => return,
test/cases/compile_errors/error_in_comptime_call_in_container_level_initializer.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2const Version = std.SemanticVersion;
3const print = @import("std").debug.print;
4
5fn readVersion() Version {
6 const version_file = "foo";
7 const len = std.mem.indexOfAny(u8, version_file, " \n") orelse version_file.len;
8 const version_string = version_file[0..len];
9 return Version.parse(version_string) catch unreachable;
10}
11
12const version: Version = readVersion();
13pub export fn entry() void {
14 print("Version {}.{}.{}+{?s}\n", .{ version.major, version.minor, version.patch, version.build });
15}
16
17// error
18// backend=llvm
19// target=native
20//
21// :9:48: error: caught unexpected error 'InvalidVersion'
22// :12:37: note: called from here
test/cases/compile_errors/generic_instantiation_failure.zig created+27
......@@ -0,0 +1,27 @@
1fn List(comptime Head: type, comptime Tail: type) type {
2 return union {
3 const Self = @This();
4 head: Head,
5 tail: Tail,
6
7 fn AppendReturnType(comptime item: anytype) type {
8 return List(Head, List(@TypeOf(item), void));
9 }
10 };
11}
12
13fn makeList(item: anytype) List(@TypeOf(item), void) {
14 return List(@TypeOf(item), void){ .head = item };
15}
16
17pub export fn entry() void {
18 @TypeOf(makeList(42)).AppendReturnType(64);
19}
20
21// error
22// backend=llvm
23// target=native
24//
25// :18:43: error: value of type 'type' ignored
26// :18:43: note: all non-void values must be used
27// :18:43: note: this error can be suppressed by assigning the value to '_'
test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig created+14
......@@ -0,0 +1,14 @@
1const std = @import("std");
2
3pub export fn entry() void {
4 var ohnoes: *usize = undefined;
5 _ = sliceAsBytes(ohnoes);
6}
7fn sliceAsBytes(slice: anytype) std.meta.trait.isPtrTo(.Array)(@TypeOf(slice)) {}
8
9
10// error
11// backend=llvm
12// target=native
13//
14// :7:63: error: expected type 'type', found 'bool'