| ... | ... | @@ -7112,7 +7112,6 @@ fn instantiateGenericCall( |
| 7112 | 7112 | const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter); |
| 7113 | 7113 | const callee = if (!gop.found_existing) callee: { |
| 7114 | 7114 | const new_module_func = try gpa.create(Module.Fn); |
| 7115 | | errdefer gpa.destroy(new_module_func); |
| 7116 | 7115 | |
| 7117 | 7116 | // This ensures that we can operate on the hash map before the Module.Fn |
| 7118 | 7117 | // struct is fully initialized. |
| ... | ... | @@ -7120,7 +7119,6 @@ fn instantiateGenericCall( |
| 7120 | 7119 | new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional(); |
| 7121 | 7120 | new_module_func.comptime_args = null; |
| 7122 | 7121 | gop.key_ptr.* = new_module_func; |
| 7123 | | errdefer assert(mod.monomorphed_funcs.remove(new_module_func)); |
| 7124 | 7122 | |
| 7125 | 7123 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); |
| 7126 | 7124 | |
| ... | ... | @@ -7128,7 +7126,6 @@ fn instantiateGenericCall( |
| 7128 | 7126 | const src_decl_index = namespace.getDeclIndex(); |
| 7129 | 7127 | const src_decl = mod.declPtr(src_decl_index); |
| 7130 | 7128 | const new_decl_index = try mod.allocateNewDecl(namespace, fn_owner_decl.src_node, src_decl.src_scope); |
| 7131 | | errdefer mod.destroyDecl(new_decl_index); |
| 7132 | 7129 | const new_decl = mod.declPtr(new_decl_index); |
| 7133 | 7130 | // TODO better names for generic function instantiations |
| 7134 | 7131 | const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ |
| ... | ... | @@ -7148,223 +7145,59 @@ fn instantiateGenericCall( |
| 7148 | 7145 | new_decl.generation = mod.generation; |
| 7149 | 7146 | |
| 7150 | 7147 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {}); |
| 7151 | | errdefer assert(namespace.anon_decls.orderedRemove(new_decl_index)); |
| 7152 | 7148 | |
| 7153 | 7149 | // The generic function Decl is guaranteed to be the first dependency |
| 7154 | 7150 | // of each of its instantiations. |
| 7155 | 7151 | assert(new_decl.dependencies.keys().len == 0); |
| 7156 | 7152 | 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 | | } |
| 7165 | 7153 | |
| 7166 | 7154 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 7167 | | errdefer new_decl_arena.deinit(); |
| 7168 | 7155 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 7169 | 7156 | |
| 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; |
| 7254 | 7194 | } 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; |
| 7265 | 7196 | } |
| 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 | }, |
| 7286 | 7199 | }; |
| 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(); |
| 7368 | 7201 | |
| 7369 | 7202 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 7370 | 7203 | break :callee new_func; |
| ... | ... | @@ -7444,6 +7277,218 @@ fn instantiateGenericCall( |
| 7444 | 7277 | return result; |
| 7445 | 7278 | } |
| 7446 | 7279 | |
| 7280 | fn 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 | |
| 7447 | 7492 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 7448 | 7493 | if (!ty.isSimpleTuple()) return; |
| 7449 | 7494 | const tuple = ty.tupleFields(); |
| ... | ... | @@ -11506,6 +11551,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I |
| 11506 | 11551 | .dbg_block_begin, |
| 11507 | 11552 | .dbg_block_end, |
| 11508 | 11553 | .dbg_stmt, |
| 11554 | .save_err_ret_index, |
| 11509 | 11555 | => {}, |
| 11510 | 11556 | .@"unreachable" => break inst, |
| 11511 | 11557 | else => return, |