| ... | @@ -7112,7 +7112,6 @@ fn instantiateGenericCall( | ... | @@ -7112,7 +7112,6 @@ fn instantiateGenericCall( |
| 7112 | const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter); | 7112 | const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter); |
| 7113 | const callee = if (!gop.found_existing) callee: { | 7113 | const callee = if (!gop.found_existing) callee: { |
| 7114 | const new_module_func = try gpa.create(Module.Fn); | 7114 | const new_module_func = try gpa.create(Module.Fn); |
| 7115 | errdefer gpa.destroy(new_module_func); | | |
| 7116 | | 7115 | |
| 7117 | // This ensures that we can operate on the hash map before the Module.Fn | 7116 | // This ensures that we can operate on the hash map before the Module.Fn |
| 7118 | // struct is fully initialized. | 7117 | // struct is fully initialized. |
| ... | @@ -7120,7 +7119,6 @@ fn instantiateGenericCall( | ... | @@ -7120,7 +7119,6 @@ fn instantiateGenericCall( |
| 7120 | new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional(); | 7119 | new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional(); |
| 7121 | new_module_func.comptime_args = null; | 7120 | new_module_func.comptime_args = null; |
| 7122 | gop.key_ptr.* = new_module_func; | 7121 | gop.key_ptr.* = new_module_func; |
| 7123 | errdefer assert(mod.monomorphed_funcs.remove(new_module_func)); | | |
| 7124 | | 7122 | |
| 7125 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); | 7123 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); |
| 7126 | | 7124 | |
| ... | @@ -7128,7 +7126,6 @@ fn instantiateGenericCall( | ... | @@ -7128,7 +7126,6 @@ fn instantiateGenericCall( |
| 7128 | const src_decl_index = namespace.getDeclIndex(); | 7126 | const src_decl_index = namespace.getDeclIndex(); |
| 7129 | const src_decl = mod.declPtr(src_decl_index); | 7127 | const src_decl = mod.declPtr(src_decl_index); |
| 7130 | const new_decl_index = try mod.allocateNewDecl(namespace, fn_owner_decl.src_node, src_decl.src_scope); | 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 | const new_decl = mod.declPtr(new_decl_index); | 7129 | const new_decl = mod.declPtr(new_decl_index); |
| 7133 | // TODO better names for generic function instantiations | 7130 | // TODO better names for generic function instantiations |
| 7134 | const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ | 7131 | const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ |
| ... | @@ -7148,223 +7145,59 @@ fn instantiateGenericCall( | ... | @@ -7148,223 +7145,59 @@ fn instantiateGenericCall( |
| 7148 | new_decl.generation = mod.generation; | 7145 | new_decl.generation = mod.generation; |
| 7149 | | 7146 | |
| 7150 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {}); | 7147 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {}); |
| 7151 | errdefer assert(namespace.anon_decls.orderedRemove(new_decl_index)); | | |
| 7152 | | 7148 | |
| 7153 | // The generic function Decl is guaranteed to be the first dependency | 7149 | // The generic function Decl is guaranteed to be the first dependency |
| 7154 | // of each of its instantiations. | 7150 | // of each of its instantiations. |
| 7155 | assert(new_decl.dependencies.keys().len == 0); | 7151 | assert(new_decl.dependencies.keys().len == 0); |
| 7156 | try mod.declareDeclDependency(new_decl_index, module_fn.owner_decl); | 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 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | 7154 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 7167 | errdefer new_decl_arena.deinit(); | | |
| 7168 | const new_decl_arena_allocator = new_decl_arena.allocator(); | 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 | 7157 | const new_func = sema.resolveGenericInstantiationType( |
| 7171 | // pre-populated inside `inst_map`. This causes `param_comptime` and | 7158 | block, |
| 7172 | // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a | 7159 | new_decl_arena_allocator, |
| 7173 | // new, monomorphized function, with the comptime parameters elided. | 7160 | fn_zir, |
| 7174 | var child_sema: Sema = .{ | 7161 | new_decl, |
| 7175 | .mod = mod, | 7162 | new_decl_index, |
| 7176 | .gpa = gpa, | 7163 | uncasted_args, |
| 7177 | .arena = sema.arena, | 7164 | module_fn, |
| 7178 | .perm_arena = new_decl_arena_allocator, | 7165 | new_module_func, |
| 7179 | .code = fn_zir, | 7166 | namespace, |
| 7180 | .owner_decl = new_decl, | 7167 | func_ty_info, |
| 7181 | .owner_decl_index = new_decl_index, | 7168 | call_src, |
| 7182 | .func = null, | 7169 | bound_arg_src, |
| 7183 | .fn_ret_ty = Type.void, | 7170 | ) catch |err| switch (err) { |
| 7184 | .owner_func = null, | 7171 | error.GenericPoison, error.ComptimeReturn => { |
| 7185 | .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len), | 7172 | new_decl_arena.deinit(); |
| 7186 | .comptime_args_fn_inst = module_fn.zir_body_inst, | 7173 | // Resolving the new function type below will possibly declare more decl dependencies |
| 7187 | .preallocated_new_func = new_module_func, | 7174 | // and so we remove them all here in case of error. |
| 7188 | .is_generic_instantiation = true, | 7175 | for (new_decl.dependencies.keys()) |dep_index| { |
| 7189 | .branch_quota = sema.branch_quota, | 7176 | const dep = mod.declPtr(dep_index); |
| 7190 | .branch_count = sema.branch_count, | 7177 | dep.removeDependant(new_decl_index); |
| 7191 | }; | 7178 | } |
| 7192 | defer child_sema.deinit(); | 7179 | assert(namespace.anon_decls.orderedRemove(new_decl_index)); |
| 7193 | | 7180 | mod.destroyDecl(new_decl_index); |
| 7194 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); | 7181 | assert(mod.monomorphed_funcs.remove(new_module_func)); |
| 7195 | defer wip_captures.deinit(); | 7182 | gpa.destroy(new_module_func); |
| 7196 | | 7183 | return err; |
| 7197 | var child_block: Block = .{ | 7184 | }, |
| 7198 | .parent = null, | 7185 | else => { |
| 7199 | .sema = &child_sema, | 7186 | { |
| 7200 | .src_decl = new_decl_index, | 7187 | errdefer new_decl_arena.deinit(); |
| 7201 | .namespace = namespace, | 7188 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 7202 | .wip_capture_scope = wip_captures.scope, | 7189 | } |
| 7203 | .instructions = .{}, | 7190 | // TODO look up the compile error that happened here and attach a note to it |
| 7204 | .inlining = null, | 7191 | // pointing here, at the generic instantiation callsite. |
| 7205 | .is_comptime = true, | 7192 | if (sema.owner_func) |owner_func| { |
| 7206 | }; | 7193 | owner_func.state = .dependency_failure; |
| 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); | | |
| 7254 | } else { | 7194 | } else { |
| 7255 | // We insert into the map an instruction which is runtime-known | 7195 | sema.owner_decl.analysis = .dependency_failure; |
| 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); | | |
| 7265 | } | 7196 | } |
| 7266 | } | 7197 | return err; |
| 7267 | arg_i += 1; | 7198 | }, |
| 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; | | |
| 7286 | }; | 7199 | }; |
| 7287 | const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, "") catch unreachable; | 7200 | errdefer new_decl_arena.deinit(); |
| 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 }); | | |
| 7368 | | 7201 | |
| 7369 | try new_decl.finalizeNewArena(&new_decl_arena); | 7202 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 7370 | break :callee new_func; | 7203 | break :callee new_func; |
| ... | @@ -7444,6 +7277,218 @@ fn instantiateGenericCall( | ... | @@ -7444,6 +7277,218 @@ fn instantiateGenericCall( |
| 7444 | return result; | 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 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { | 7492 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 7448 | if (!ty.isSimpleTuple()) return; | 7493 | if (!ty.isSimpleTuple()) return; |
| 7449 | const tuple = ty.tupleFields(); | 7494 | const tuple = ty.tupleFields(); |
| ... | @@ -11506,6 +11551,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I | ... | @@ -11506,6 +11551,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I |
| 11506 | .dbg_block_begin, | 11551 | .dbg_block_begin, |
| 11507 | .dbg_block_end, | 11552 | .dbg_block_end, |
| 11508 | .dbg_stmt, | 11553 | .dbg_stmt, |
| | 11554 | .save_err_ret_index, |
| 11509 | => {}, | 11555 | => {}, |
| 11510 | .@"unreachable" => break inst, | 11556 | .@"unreachable" => break inst, |
| 11511 | else => return, | 11557 | else => return, |