| ... | @@ -6679,78 +6679,6 @@ fn callBuiltin( | ... | @@ -6679,78 +6679,6 @@ fn callBuiltin( |
| 6679 | _ = try sema.analyzeCall(block, builtin_fn, func_ty, sema.src, sema.src, modifier, false, args, null, null); | 6679 | _ = try sema.analyzeCall(block, builtin_fn, func_ty, sema.src, sema.src, modifier, false, args, null, null); |
| 6680 | } | 6680 | } |
| 6681 | | 6681 | |
| 6682 | const GenericCallAdapter = struct { | | |
| 6683 | generic_fn: *Module.Fn, | | |
| 6684 | precomputed_hash: u64, | | |
| 6685 | func_ty_info: InternPool.Key.FuncType, | | |
| 6686 | args: []const Arg, | | |
| 6687 | module: *Module, | | |
| 6688 | | | |
| 6689 | const Arg = struct { | | |
| 6690 | ty: Type, | | |
| 6691 | val: Value, | | |
| 6692 | is_anytype: bool, | | |
| 6693 | }; | | |
| 6694 | | | |
| 6695 | pub fn eql(ctx: @This(), adapted_key: void, other_key: Module.Fn.Index) bool { | | |
| 6696 | _ = adapted_key; | | |
| 6697 | const other_func = ctx.module.funcPtr(other_key); | | |
| 6698 | | | |
| 6699 | // Checking for equality may happen on an item that has been inserted | | |
| 6700 | // into the map but is not yet fully initialized. In such case, the | | |
| 6701 | // two initialized fields are `hash` and `generic_owner_decl`. | | |
| 6702 | if (ctx.generic_fn.owner_decl != other_func.generic_owner_decl.unwrap().?) return false; | | |
| 6703 | | | |
| 6704 | const other_comptime_args = other_func.comptime_args.?; | | |
| 6705 | for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| { | | |
| 6706 | const this_arg = ctx.args[i]; | | |
| 6707 | const this_is_comptime = !this_arg.val.isGenericPoison(); | | |
| 6708 | const other_is_comptime = !other_arg.val.isGenericPoison(); | | |
| 6709 | const this_is_anytype = this_arg.is_anytype; | | |
| 6710 | const other_is_anytype = other_func.isAnytypeParam(ctx.module, @intCast(u32, i)); | | |
| 6711 | | | |
| 6712 | if (other_is_anytype != this_is_anytype) return false; | | |
| 6713 | if (other_is_comptime != this_is_comptime) return false; | | |
| 6714 | | | |
| 6715 | if (this_is_anytype) { | | |
| 6716 | // Both are anytype parameters. | | |
| 6717 | if (!this_arg.ty.eql(other_arg.ty, ctx.module)) { | | |
| 6718 | return false; | | |
| 6719 | } | | |
| 6720 | if (this_is_comptime) { | | |
| 6721 | // Both are comptime and anytype parameters with matching types. | | |
| 6722 | if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.module)) { | | |
| 6723 | return false; | | |
| 6724 | } | | |
| 6725 | } | | |
| 6726 | } else if (this_is_comptime) { | | |
| 6727 | // Both are comptime parameters but not anytype parameters. | | |
| 6728 | // We assert no error is possible here because any lazy values must be resolved | | |
| 6729 | // before inserting into the generic function hash map. | | |
| 6730 | const is_eql = Value.eqlAdvanced( | | |
| 6731 | this_arg.val, | | |
| 6732 | this_arg.ty, | | |
| 6733 | other_arg.val, | | |
| 6734 | other_arg.ty, | | |
| 6735 | ctx.module, | | |
| 6736 | null, | | |
| 6737 | ) catch unreachable; | | |
| 6738 | if (!is_eql) { | | |
| 6739 | return false; | | |
| 6740 | } | | |
| 6741 | } | | |
| 6742 | } | | |
| 6743 | return true; | | |
| 6744 | } | | |
| 6745 | | | |
| 6746 | /// The implementation of the hash is in semantic analysis of function calls, so | | |
| 6747 | /// that any errors when computing the hash can be properly reported. | | |
| 6748 | pub fn hash(ctx: @This(), adapted_key: void) u64 { | | |
| 6749 | _ = adapted_key; | | |
| 6750 | return ctx.precomputed_hash; | | |
| 6751 | } | | |
| 6752 | }; | | |
| 6753 | | | |
| 6754 | fn analyzeCall( | 6682 | fn analyzeCall( |
| 6755 | sema: *Sema, | 6683 | sema: *Sema, |
| 6756 | block: *Block, | 6684 | block: *Block, |
| ... | @@ -7480,11 +7408,12 @@ fn instantiateGenericCall( | ... | @@ -7480,11 +7408,12 @@ fn instantiateGenericCall( |
| 7480 | const ip = &mod.intern_pool; | 7408 | const ip = &mod.intern_pool; |
| 7481 | | 7409 | |
| 7482 | const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known"); | 7410 | const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known"); |
| 7483 | const module_fn = mod.funcPtr(switch (ip.indexToKey(func_val.toIntern())) { | 7411 | const module_fn_index = switch (ip.indexToKey(func_val.toIntern())) { |
| 7484 | .func => |function| function.index, | 7412 | .func => |function| function.index, |
| 7485 | .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?, | 7413 | .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?, |
| 7486 | else => unreachable, | 7414 | else => unreachable, |
| 7487 | }); | 7415 | }; |
| | 7416 | const module_fn = mod.funcPtr(module_fn_index); |
| 7488 | // Check the Module's generic function map with an adapted context, so that we | 7417 | // Check the Module's generic function map with an adapted context, so that we |
| 7489 | // can match against `uncasted_args` rather than doing the work below to create a | 7418 | // can match against `uncasted_args` rather than doing the work below to create a |
| 7490 | // generic Scope only to junk it if it matches an existing instantiation. | 7419 | // generic Scope only to junk it if it matches an existing instantiation. |
| ... | @@ -7495,32 +7424,24 @@ fn instantiateGenericCall( | ... | @@ -7495,32 +7424,24 @@ fn instantiateGenericCall( |
| 7495 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); | 7424 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); |
| 7496 | const zir_tags = fn_zir.instructions.items(.tag); | 7425 | const zir_tags = fn_zir.instructions.items(.tag); |
| 7497 | | 7426 | |
| 7498 | // This hash must match `Module.MonomorphedFuncsContext.hash`. | 7427 | const generic_args = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); |
| 7499 | // For parameters explicitly marked comptime and simple parameter type expressions, | 7428 | const callee_index = callee: { |
| 7500 | // we know whether a parameter is elided from a monomorphed function, and can | 7429 | var arg_i: usize = 0; |
| 7501 | // use it in the hash here. However, for parameter type expressions that are not | 7430 | var generic_arg_i: u32 = 0; |
| 7502 | // explicitly marked comptime and rely on previous parameter comptime values, we | 7431 | var known_unique = false; |
| 7503 | // don't find out until after generating a monomorphed function whether the parameter | | |
| 7504 | // type ended up being a "must-be-comptime-known" type. | | |
| 7505 | var hasher = std.hash.Wyhash.init(0); | | |
| 7506 | std.hash.autoHash(&hasher, module_fn.owner_decl); | | |
| 7507 | | | |
| 7508 | const generic_args = try sema.arena.alloc(GenericCallAdapter.Arg, func_ty_info.param_types.len); | | |
| 7509 | { | | |
| 7510 | var i: usize = 0; | | |
| 7511 | for (fn_info.param_body) |inst| { | 7432 | for (fn_info.param_body) |inst| { |
| 7512 | var is_comptime = false; | 7433 | var is_comptime = false; |
| 7513 | var is_anytype = false; | 7434 | var is_anytype = false; |
| 7514 | switch (zir_tags[inst]) { | 7435 | switch (zir_tags[inst]) { |
| 7515 | .param => { | 7436 | .param => { |
| 7516 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, i)); | 7437 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i)); |
| 7517 | }, | 7438 | }, |
| 7518 | .param_comptime => { | 7439 | .param_comptime => { |
| 7519 | is_comptime = true; | 7440 | is_comptime = true; |
| 7520 | }, | 7441 | }, |
| 7521 | .param_anytype => { | 7442 | .param_anytype => { |
| 7522 | is_anytype = true; | 7443 | is_anytype = true; |
| 7523 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, i)); | 7444 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i)); |
| 7524 | }, | 7445 | }, |
| 7525 | .param_anytype_comptime => { | 7446 | .param_anytype_comptime => { |
| 7526 | is_anytype = true; | 7447 | is_anytype = true; |
| ... | @@ -7529,7 +7450,15 @@ fn instantiateGenericCall( | ... | @@ -7529,7 +7450,15 @@ fn instantiateGenericCall( |
| 7529 | else => continue, | 7450 | else => continue, |
| 7530 | } | 7451 | } |
| 7531 | | 7452 | |
| 7532 | const arg_ty = sema.typeOf(uncasted_args[i]); | 7453 | defer arg_i += 1; |
| | 7454 | if (known_unique) { |
| | 7455 | if (is_comptime or is_anytype) { |
| | 7456 | generic_arg_i += 1; |
| | 7457 | } |
| | 7458 | continue; |
| | 7459 | } |
| | 7460 | |
| | 7461 | const arg_ty = sema.typeOf(uncasted_args[arg_i]); |
| 7533 | if (is_comptime or is_anytype) { | 7462 | if (is_comptime or is_anytype) { |
| 7534 | // Tuple default values are a part of the type and need to be | 7463 | // Tuple default values are a part of the type and need to be |
| 7535 | // resolved to hash the type. | 7464 | // resolved to hash the type. |
| ... | @@ -7537,69 +7466,72 @@ fn instantiateGenericCall( | ... | @@ -7537,69 +7466,72 @@ fn instantiateGenericCall( |
| 7537 | } | 7466 | } |
| 7538 | | 7467 | |
| 7539 | if (is_comptime) { | 7468 | if (is_comptime) { |
| 7540 | const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) { | 7469 | const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[arg_i]) catch |err| switch (err) { |
| 7541 | error.NeededSourceLocation => { | 7470 | error.NeededSourceLocation => { |
| 7542 | const decl = sema.mod.declPtr(block.src_decl); | 7471 | const decl = sema.mod.declPtr(block.src_decl); |
| 7543 | const arg_src = mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src); | 7472 | const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src); |
| 7544 | _ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[i]); | 7473 | _ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[arg_i]); |
| 7545 | unreachable; | 7474 | unreachable; |
| 7546 | }, | 7475 | }, |
| 7547 | else => |e| return e, | 7476 | else => |e| return e, |
| 7548 | }; | 7477 | }; |
| 7549 | arg_val.hashUncoerced(arg_ty, &hasher, mod); | 7478 | |
| 7550 | if (is_anytype) { | 7479 | if (is_anytype) { |
| 7551 | std.hash.autoHash(&hasher, arg_ty.toIntern()); | 7480 | generic_args[generic_arg_i] = arg_val.toIntern(); |
| 7552 | generic_args[i] = .{ | | |
| 7553 | .ty = arg_ty, | | |
| 7554 | .val = arg_val, | | |
| 7555 | .is_anytype = true, | | |
| 7556 | }; | | |
| 7557 | } else { | 7481 | } else { |
| 7558 | generic_args[i] = .{ | 7482 | const final_arg_ty = mod.monomorphed_funcs.getAdapted( |
| 7559 | .ty = arg_ty, | 7483 | Module.MonomorphedFuncAdaptedKey{ |
| 7560 | .val = arg_val, | 7484 | .func = module_fn_index, |
| 7561 | .is_anytype = false, | 7485 | .args = generic_args[0..generic_arg_i], |
| | 7486 | }, |
| | 7487 | Module.MonomorphedFuncsAdaptedContext{ .mod = mod }, |
| | 7488 | ) orelse { |
| | 7489 | known_unique = true; |
| | 7490 | generic_arg_i += 1; |
| | 7491 | continue; |
| | 7492 | }; |
| | 7493 | const casted_arg = sema.coerce(block, final_arg_ty.toType(), uncasted_args[arg_i], .unneeded) catch |err| switch (err) { |
| | 7494 | error.NeededSourceLocation => { |
| | 7495 | const decl = sema.mod.declPtr(block.src_decl); |
| | 7496 | const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src); |
| | 7497 | _ = try sema.coerce(block, final_arg_ty.toType(), uncasted_args[arg_i], arg_src); |
| | 7498 | unreachable; |
| | 7499 | }, |
| | 7500 | else => |e| return e, |
| 7562 | }; | 7501 | }; |
| | 7502 | const casted_arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, casted_arg) catch |err| switch (err) { |
| | 7503 | error.NeededSourceLocation => { |
| | 7504 | const decl = sema.mod.declPtr(block.src_decl); |
| | 7505 | const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src); |
| | 7506 | _ = try sema.analyzeGenericCallArgVal(block, arg_src, casted_arg); |
| | 7507 | unreachable; |
| | 7508 | }, |
| | 7509 | else => |e| return e, |
| | 7510 | }; |
| | 7511 | generic_args[generic_arg_i] = casted_arg_val.toIntern(); |
| 7563 | } | 7512 | } |
| | 7513 | generic_arg_i += 1; |
| 7564 | } else if (is_anytype) { | 7514 | } else if (is_anytype) { |
| 7565 | std.hash.autoHash(&hasher, arg_ty.toIntern()); | 7515 | generic_args[generic_arg_i] = arg_ty.toIntern(); |
| 7566 | generic_args[i] = .{ | 7516 | generic_arg_i += 1; |
| 7567 | .ty = arg_ty, | | |
| 7568 | .val = Value.generic_poison, | | |
| 7569 | .is_anytype = true, | | |
| 7570 | }; | | |
| 7571 | } else { | | |
| 7572 | generic_args[i] = .{ | | |
| 7573 | .ty = arg_ty, | | |
| 7574 | .val = Value.generic_poison, | | |
| 7575 | .is_anytype = false, | | |
| 7576 | }; | | |
| 7577 | } | 7517 | } |
| 7578 | | | |
| 7579 | i += 1; | | |
| 7580 | } | 7518 | } |
| 7581 | } | | |
| 7582 | | 7519 | |
| 7583 | const precomputed_hash = hasher.final(); | 7520 | if (!known_unique) { |
| | 7521 | if (mod.monomorphed_funcs.getAdapted( |
| | 7522 | Module.MonomorphedFuncAdaptedKey{ |
| | 7523 | .func = module_fn_index, |
| | 7524 | .args = generic_args[0..generic_arg_i], |
| | 7525 | }, |
| | 7526 | Module.MonomorphedFuncsAdaptedContext{ .mod = mod }, |
| | 7527 | )) |callee_func| break :callee mod.intern_pool.indexToKey(callee_func).func.index; |
| | 7528 | } |
| 7584 | | 7529 | |
| 7585 | const adapter: GenericCallAdapter = .{ | | |
| 7586 | .generic_fn = module_fn, | | |
| 7587 | .precomputed_hash = precomputed_hash, | | |
| 7588 | .func_ty_info = func_ty_info, | | |
| 7589 | .args = generic_args, | | |
| 7590 | .module = mod, | | |
| 7591 | }; | | |
| 7592 | const gop = try mod.monomorphed_funcs.getOrPutContextAdapted(gpa, {}, adapter, .{ .mod = mod }); | | |
| 7593 | const callee_index = if (!gop.found_existing) callee: { | | |
| 7594 | const new_module_func_index = try mod.createFunc(undefined); | 7530 | const new_module_func_index = try mod.createFunc(undefined); |
| 7595 | const new_module_func = mod.funcPtr(new_module_func_index); | 7531 | const new_module_func = mod.funcPtr(new_module_func_index); |
| 7596 | | 7532 | |
| 7597 | // This ensures that we can operate on the hash map before the Module.Fn | | |
| 7598 | // struct is fully initialized. | | |
| 7599 | new_module_func.hash = precomputed_hash; | | |
| 7600 | new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional(); | 7533 | new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional(); |
| 7601 | new_module_func.comptime_args = null; | 7534 | new_module_func.comptime_args = null; |
| 7602 | gop.key_ptr.* = new_module_func_index; | | |
| 7603 | | 7535 | |
| 7604 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); | 7536 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); |
| 7605 | | 7537 | |
| ... | @@ -7641,7 +7573,8 @@ fn instantiateGenericCall( | ... | @@ -7641,7 +7573,8 @@ fn instantiateGenericCall( |
| 7641 | new_decl, | 7573 | new_decl, |
| 7642 | new_decl_index, | 7574 | new_decl_index, |
| 7643 | uncasted_args, | 7575 | uncasted_args, |
| 7644 | module_fn, | 7576 | generic_arg_i, |
| | 7577 | module_fn_index, |
| 7645 | new_module_func_index, | 7578 | new_module_func_index, |
| 7646 | namespace_index, | 7579 | namespace_index, |
| 7647 | func_ty_info, | 7580 | func_ty_info, |
| ... | @@ -7657,12 +7590,10 @@ fn instantiateGenericCall( | ... | @@ -7657,12 +7590,10 @@ fn instantiateGenericCall( |
| 7657 | } | 7590 | } |
| 7658 | assert(namespace.anon_decls.orderedRemove(new_decl_index)); | 7591 | assert(namespace.anon_decls.orderedRemove(new_decl_index)); |
| 7659 | mod.destroyDecl(new_decl_index); | 7592 | mod.destroyDecl(new_decl_index); |
| 7660 | assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod })); | | |
| 7661 | mod.destroyFunc(new_module_func_index); | 7593 | mod.destroyFunc(new_module_func_index); |
| 7662 | return err; | 7594 | return err; |
| 7663 | }, | 7595 | }, |
| 7664 | else => { | 7596 | else => { |
| 7665 | assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod })); | | |
| 7666 | // TODO look up the compile error that happened here and attach a note to it | 7597 | // TODO look up the compile error that happened here and attach a note to it |
| 7667 | // pointing here, at the generic instantiation callsite. | 7598 | // pointing here, at the generic instantiation callsite. |
| 7668 | if (sema.owner_func) |owner_func| { | 7599 | if (sema.owner_func) |owner_func| { |
| ... | @@ -7675,9 +7606,8 @@ fn instantiateGenericCall( | ... | @@ -7675,9 +7606,8 @@ fn instantiateGenericCall( |
| 7675 | }; | 7606 | }; |
| 7676 | | 7607 | |
| 7677 | break :callee new_func; | 7608 | break :callee new_func; |
| 7678 | } else gop.key_ptr.*; | 7609 | }; |
| 7679 | const callee = mod.funcPtr(callee_index); | 7610 | const callee = mod.funcPtr(callee_index); |
| 7680 | | | |
| 7681 | callee.branch_quota = @max(callee.branch_quota, sema.branch_quota); | 7611 | callee.branch_quota = @max(callee.branch_quota, sema.branch_quota); |
| 7682 | | 7612 | |
| 7683 | const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl); | 7613 | const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl); |
| ... | @@ -7752,7 +7682,7 @@ fn instantiateGenericCall( | ... | @@ -7752,7 +7682,7 @@ fn instantiateGenericCall( |
| 7752 | if (call_tag == .call_always_tail) { | 7682 | if (call_tag == .call_always_tail) { |
| 7753 | return sema.handleTailCall(block, call_src, func_ty, result); | 7683 | return sema.handleTailCall(block, call_src, func_ty, result); |
| 7754 | } | 7684 | } |
| 7755 | if (new_fn_info.return_type == .noreturn_type) { | 7685 | if (func_ty.fnReturnType(mod).isNoReturn(mod)) { |
| 7756 | _ = try block.addNoOp(.unreach); | 7686 | _ = try block.addNoOp(.unreach); |
| 7757 | return Air.Inst.Ref.unreachable_value; | 7687 | return Air.Inst.Ref.unreachable_value; |
| 7758 | } | 7688 | } |
| ... | @@ -7766,7 +7696,8 @@ fn resolveGenericInstantiationType( | ... | @@ -7766,7 +7696,8 @@ fn resolveGenericInstantiationType( |
| 7766 | new_decl: *Decl, | 7696 | new_decl: *Decl, |
| 7767 | new_decl_index: Decl.Index, | 7697 | new_decl_index: Decl.Index, |
| 7768 | uncasted_args: []const Air.Inst.Ref, | 7698 | uncasted_args: []const Air.Inst.Ref, |
| 7769 | module_fn: *Module.Fn, | 7699 | generic_args_len: u32, |
| | 7700 | module_fn_index: Module.Fn.Index, |
| 7770 | new_module_func: Module.Fn.Index, | 7701 | new_module_func: Module.Fn.Index, |
| 7771 | namespace: Namespace.Index, | 7702 | namespace: Namespace.Index, |
| 7772 | func_ty_info: InternPool.Key.FuncType, | 7703 | func_ty_info: InternPool.Key.FuncType, |
| ... | @@ -7777,6 +7708,7 @@ fn resolveGenericInstantiationType( | ... | @@ -7777,6 +7708,7 @@ fn resolveGenericInstantiationType( |
| 7777 | const gpa = sema.gpa; | 7708 | const gpa = sema.gpa; |
| 7778 | | 7709 | |
| 7779 | const zir_tags = fn_zir.instructions.items(.tag); | 7710 | const zir_tags = fn_zir.instructions.items(.tag); |
| | 7711 | const module_fn = mod.funcPtr(module_fn_index); |
| 7780 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); | 7712 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); |
| 7781 | | 7713 | |
| 7782 | // Re-run the block that creates the function, with the comptime parameters | 7714 | // Re-run the block that creates the function, with the comptime parameters |
| ... | @@ -7893,9 +7825,15 @@ fn resolveGenericInstantiationType( | ... | @@ -7893,9 +7825,15 @@ fn resolveGenericInstantiationType( |
| 7893 | const new_func = new_func_val.getFunctionIndex(mod).unwrap().?; | 7825 | const new_func = new_func_val.getFunctionIndex(mod).unwrap().?; |
| 7894 | assert(new_func == new_module_func); | 7826 | assert(new_func == new_module_func); |
| 7895 | | 7827 | |
| | 7828 | const generic_args_index = @intCast(u32, mod.monomorphed_func_keys.items.len); |
| | 7829 | const generic_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, generic_args_len); |
| | 7830 | var generic_arg_i: u32 = 0; |
| | 7831 | try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, generic_args_len + 1, .{ .mod = mod }); |
| | 7832 | |
| 7896 | arg_i = 0; | 7833 | arg_i = 0; |
| 7897 | for (fn_info.param_body) |inst| { | 7834 | for (fn_info.param_body) |inst| { |
| 7898 | var is_comptime = false; | 7835 | var is_comptime = false; |
| | 7836 | var is_anytype = false; |
| 7899 | switch (zir_tags[inst]) { | 7837 | switch (zir_tags[inst]) { |
| 7900 | .param => { | 7838 | .param => { |
| 7901 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i)); | 7839 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i)); |
| ... | @@ -7904,9 +7842,11 @@ fn resolveGenericInstantiationType( | ... | @@ -7904,9 +7842,11 @@ fn resolveGenericInstantiationType( |
| 7904 | is_comptime = true; | 7842 | is_comptime = true; |
| 7905 | }, | 7843 | }, |
| 7906 | .param_anytype => { | 7844 | .param_anytype => { |
| | 7845 | is_anytype = true; |
| 7907 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i)); | 7846 | is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i)); |
| 7908 | }, | 7847 | }, |
| 7909 | .param_anytype_comptime => { | 7848 | .param_anytype_comptime => { |
| | 7849 | is_anytype = true; |
| 7910 | is_comptime = true; | 7850 | is_comptime = true; |
| 7911 | }, | 7851 | }, |
| 7912 | else => continue, | 7852 | else => continue, |
| ... | @@ -7924,11 +7864,24 @@ fn resolveGenericInstantiationType( | ... | @@ -7924,11 +7864,24 @@ fn resolveGenericInstantiationType( |
| 7924 | | 7864 | |
| 7925 | if (is_comptime) { | 7865 | if (is_comptime) { |
| 7926 | const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?; | 7866 | const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?; |
| | 7867 | if (!is_anytype) { |
| | 7868 | if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{ |
| | 7869 | .func = module_fn_index, |
| | 7870 | .args_index = generic_args_index, |
| | 7871 | .args_len = generic_arg_i, |
| | 7872 | }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern()); |
| | 7873 | } |
| | 7874 | generic_args[generic_arg_i] = arg_val.toIntern(); |
| | 7875 | generic_arg_i += 1; |
| 7927 | child_sema.comptime_args[arg_i] = .{ | 7876 | child_sema.comptime_args[arg_i] = .{ |
| 7928 | .ty = arg_ty, | 7877 | .ty = arg_ty, |
| 7929 | .val = (try arg_val.intern(arg_ty, mod)).toValue(), | 7878 | .val = (try arg_val.intern(arg_ty, mod)).toValue(), |
| 7930 | }; | 7879 | }; |
| 7931 | } else { | 7880 | } else { |
| | 7881 | if (is_anytype) { |
| | 7882 | generic_args[generic_arg_i] = arg_ty.toIntern(); |
| | 7883 | generic_arg_i += 1; |
| | 7884 | } |
| 7932 | child_sema.comptime_args[arg_i] = .{ | 7885 | child_sema.comptime_args[arg_i] = .{ |
| 7933 | .ty = arg_ty, | 7886 | .ty = arg_ty, |
| 7934 | .val = Value.generic_poison, | 7887 | .val = Value.generic_poison, |
| ... | @@ -7963,6 +7916,12 @@ fn resolveGenericInstantiationType( | ... | @@ -7963,6 +7916,12 @@ fn resolveGenericInstantiationType( |
| 7963 | new_decl.owns_tv = true; | 7916 | new_decl.owns_tv = true; |
| 7964 | new_decl.analysis = .complete; | 7917 | new_decl.analysis = .complete; |
| 7965 | | 7918 | |
| | 7919 | mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{ |
| | 7920 | .func = module_fn_index, |
| | 7921 | .args_index = generic_args_index, |
| | 7922 | .args_len = generic_arg_i, |
| | 7923 | }, new_decl.val.toIntern(), .{ .mod = mod }); |
| | 7924 | |
| 7966 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field | 7925 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field |
| 7967 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR | 7926 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR |
| 7968 | // parameters mapped appropriately. | 7927 | // parameters mapped appropriately. |