| ... | @@ -70,7 +70,6 @@ generic_owner: InternPool.Index = .none, | ... | @@ -70,7 +70,6 @@ generic_owner: InternPool.Index = .none, |
| 70 | /// instantiation can point back to the instantiation site in addition to the | 70 | /// instantiation can point back to the instantiation site in addition to the |
| 71 | /// declaration site. | 71 | /// declaration site. |
| 72 | generic_call_src: LazySrcLoc = .unneeded, | 72 | generic_call_src: LazySrcLoc = .unneeded, |
| 73 | generic_bound_arg_src: ?LazySrcLoc = null, | | |
| 74 | /// Corresponds to `generic_call_src`. | 73 | /// Corresponds to `generic_call_src`. |
| 75 | generic_call_decl: Decl.OptionalIndex = .none, | 74 | generic_call_decl: Decl.OptionalIndex = .none, |
| 76 | /// The key is types that must be fully resolved prior to machine code | 75 | /// The key is types that must be fully resolved prior to machine code |
| ... | @@ -1022,6 +1021,7 @@ fn analyzeBodyInner( | ... | @@ -1022,6 +1021,7 @@ fn analyzeBodyInner( |
| 1022 | .elem_val_node => try sema.zirElemValNode(block, inst), | 1021 | .elem_val_node => try sema.zirElemValNode(block, inst), |
| 1023 | .elem_type_index => try sema.zirElemTypeIndex(block, inst), | 1022 | .elem_type_index => try sema.zirElemTypeIndex(block, inst), |
| 1024 | .elem_type => try sema.zirElemType(block, inst), | 1023 | .elem_type => try sema.zirElemType(block, inst), |
| | 1024 | .vector_elem_type => try sema.zirVectorElemType(block, inst), |
| 1025 | .enum_literal => try sema.zirEnumLiteral(block, inst), | 1025 | .enum_literal => try sema.zirEnumLiteral(block, inst), |
| 1026 | .int_from_enum => try sema.zirIntFromEnum(block, inst), | 1026 | .int_from_enum => try sema.zirIntFromEnum(block, inst), |
| 1027 | .enum_from_int => try sema.zirEnumFromInt(block, inst), | 1027 | .enum_from_int => try sema.zirEnumFromInt(block, inst), |
| ... | @@ -1125,6 +1125,7 @@ fn analyzeBodyInner( | ... | @@ -1125,6 +1125,7 @@ fn analyzeBodyInner( |
| 1125 | .array_base_ptr => try sema.zirArrayBasePtr(block, inst), | 1125 | .array_base_ptr => try sema.zirArrayBasePtr(block, inst), |
| 1126 | .field_base_ptr => try sema.zirFieldBasePtr(block, inst), | 1126 | .field_base_ptr => try sema.zirFieldBasePtr(block, inst), |
| 1127 | .for_len => try sema.zirForLen(block, inst), | 1127 | .for_len => try sema.zirForLen(block, inst), |
| | 1128 | .opt_eu_base_ty => try sema.zirOptEuBaseTy(block, inst), |
| 1128 | | 1129 | |
| 1129 | .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), | 1130 | .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), |
| 1130 | .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), | 1131 | .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), |
| ... | @@ -1359,12 +1360,12 @@ fn analyzeBodyInner( | ... | @@ -1359,12 +1360,12 @@ fn analyzeBodyInner( |
| 1359 | continue; | 1360 | continue; |
| 1360 | }, | 1361 | }, |
| 1361 | .validate_array_init_ty => { | 1362 | .validate_array_init_ty => { |
| 1362 | try sema.validateArrayInitTy(block, inst); | 1363 | try sema.zirValidateArrayInitTy(block, inst); |
| 1363 | i += 1; | 1364 | i += 1; |
| 1364 | continue; | 1365 | continue; |
| 1365 | }, | 1366 | }, |
| 1366 | .validate_struct_init_ty => { | 1367 | .validate_struct_init_ty => { |
| 1367 | try sema.validateStructInitTy(block, inst); | 1368 | try sema.zirValidateStructInitTy(block, inst); |
| 1368 | i += 1; | 1369 | i += 1; |
| 1369 | continue; | 1370 | continue; |
| 1370 | }, | 1371 | }, |
| ... | @@ -1399,22 +1400,22 @@ fn analyzeBodyInner( | ... | @@ -1399,22 +1400,22 @@ fn analyzeBodyInner( |
| 1399 | continue; | 1400 | continue; |
| 1400 | }, | 1401 | }, |
| 1401 | .param => { | 1402 | .param => { |
| 1402 | try sema.zirParam(block, inst, i, false); | 1403 | try sema.zirParam(block, inst, false); |
| 1403 | i += 1; | 1404 | i += 1; |
| 1404 | continue; | 1405 | continue; |
| 1405 | }, | 1406 | }, |
| 1406 | .param_comptime => { | 1407 | .param_comptime => { |
| 1407 | try sema.zirParam(block, inst, i, true); | 1408 | try sema.zirParam(block, inst, true); |
| 1408 | i += 1; | 1409 | i += 1; |
| 1409 | continue; | 1410 | continue; |
| 1410 | }, | 1411 | }, |
| 1411 | .param_anytype => { | 1412 | .param_anytype => { |
| 1412 | try sema.zirParamAnytype(block, inst, i, false); | 1413 | try sema.zirParamAnytype(block, inst, false); |
| 1413 | i += 1; | 1414 | i += 1; |
| 1414 | continue; | 1415 | continue; |
| 1415 | }, | 1416 | }, |
| 1416 | .param_anytype_comptime => { | 1417 | .param_anytype_comptime => { |
| 1417 | try sema.zirParamAnytype(block, inst, i, true); | 1418 | try sema.zirParamAnytype(block, inst, true); |
| 1418 | i += 1; | 1419 | i += 1; |
| 1419 | continue; | 1420 | continue; |
| 1420 | }, | 1421 | }, |
| ... | @@ -4312,7 +4313,31 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -4312,7 +4313,31 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4312 | return len; | 4313 | return len; |
| 4313 | } | 4314 | } |
| 4314 | | 4315 | |
| 4315 | fn validateArrayInitTy( | 4316 | fn zirOptEuBaseTy( |
| | 4317 | sema: *Sema, |
| | 4318 | block: *Block, |
| | 4319 | inst: Zir.Inst.Index, |
| | 4320 | ) CompileError!Air.Inst.Ref { |
| | 4321 | const mod = sema.mod; |
| | 4322 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| | 4323 | var ty = sema.resolveType(block, .unneeded, inst_data.operand) catch |err| switch (err) { |
| | 4324 | // Since this is a ZIR instruction that returns a type, encountering |
| | 4325 | // generic poison should not result in a failed compilation, but the |
| | 4326 | // generic poison type. This prevents unnecessary failures when |
| | 4327 | // constructing types at compile-time. |
| | 4328 | error.GenericPoison => return .generic_poison_type, |
| | 4329 | else => |e| return e, |
| | 4330 | }; |
| | 4331 | while (true) { |
| | 4332 | switch (ty.zigTypeTag(mod)) { |
| | 4333 | .Optional => ty = ty.optionalChild(mod), |
| | 4334 | .ErrorUnion => ty = ty.errorUnionPayload(mod), |
| | 4335 | else => return sema.addType(ty), |
| | 4336 | } |
| | 4337 | } |
| | 4338 | } |
| | 4339 | |
| | 4340 | fn zirValidateArrayInitTy( |
| 4316 | sema: *Sema, | 4341 | sema: *Sema, |
| 4317 | block: *Block, | 4342 | block: *Block, |
| 4318 | inst: Zir.Inst.Index, | 4343 | inst: Zir.Inst.Index, |
| ... | @@ -4322,7 +4347,11 @@ fn validateArrayInitTy( | ... | @@ -4322,7 +4347,11 @@ fn validateArrayInitTy( |
| 4322 | const src = inst_data.src(); | 4347 | const src = inst_data.src(); |
| 4323 | const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; | 4348 | const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; |
| 4324 | const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; | 4349 | const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; |
| 4325 | const ty = try sema.resolveType(block, ty_src, extra.ty); | 4350 | const ty = sema.resolveType(block, ty_src, extra.ty) catch |err| switch (err) { |
| | 4351 | // It's okay for the type to be unknown: this will result in an anonymous array init. |
| | 4352 | error.GenericPoison => return, |
| | 4353 | else => |e| return e, |
| | 4354 | }; |
| 4326 | | 4355 | |
| 4327 | switch (ty.zigTypeTag(mod)) { | 4356 | switch (ty.zigTypeTag(mod)) { |
| 4328 | .Array => { | 4357 | .Array => { |
| ... | @@ -4358,7 +4387,7 @@ fn validateArrayInitTy( | ... | @@ -4358,7 +4387,7 @@ fn validateArrayInitTy( |
| 4358 | return sema.failWithArrayInitNotSupported(block, ty_src, ty); | 4387 | return sema.failWithArrayInitNotSupported(block, ty_src, ty); |
| 4359 | } | 4388 | } |
| 4360 | | 4389 | |
| 4361 | fn validateStructInitTy( | 4390 | fn zirValidateStructInitTy( |
| 4362 | sema: *Sema, | 4391 | sema: *Sema, |
| 4363 | block: *Block, | 4392 | block: *Block, |
| 4364 | inst: Zir.Inst.Index, | 4393 | inst: Zir.Inst.Index, |
| ... | @@ -4366,7 +4395,11 @@ fn validateStructInitTy( | ... | @@ -4366,7 +4395,11 @@ fn validateStructInitTy( |
| 4366 | const mod = sema.mod; | 4395 | const mod = sema.mod; |
| 4367 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 4396 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4368 | const src = inst_data.src(); | 4397 | const src = inst_data.src(); |
| 4369 | const ty = try sema.resolveType(block, src, inst_data.operand); | 4398 | const ty = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) { |
| | 4399 | // It's okay for the type to be unknown: this will result in an anonymous struct init. |
| | 4400 | error.GenericPoison => return, |
| | 4401 | else => |e| return e, |
| | 4402 | }; |
| 4370 | | 4403 | |
| 4371 | switch (ty.zigTypeTag(mod)) { | 4404 | switch (ty.zigTypeTag(mod)) { |
| 4372 | .Struct, .Union => return, | 4405 | .Struct, .Union => return, |
| ... | @@ -6502,7 +6535,6 @@ fn zirCall( | ... | @@ -6502,7 +6535,6 @@ fn zirCall( |
| 6502 | defer tracy.end(); | 6535 | defer tracy.end(); |
| 6503 | | 6536 | |
| 6504 | const mod = sema.mod; | 6537 | const mod = sema.mod; |
| 6505 | const ip = &mod.intern_pool; | | |
| 6506 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 6538 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6507 | const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; | 6539 | const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; |
| 6508 | const call_src = inst_data.src(); | 6540 | const call_src = inst_data.src(); |
| ... | @@ -6526,96 +6558,62 @@ fn zirCall( | ... | @@ -6526,96 +6558,62 @@ fn zirCall( |
| 6526 | break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src); | 6558 | break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src); |
| 6527 | }, | 6559 | }, |
| 6528 | }; | 6560 | }; |
| 6529 | var resolved_args: []Air.Inst.Ref = undefined; | 6561 | const func: Air.Inst.Ref = switch (callee) { |
| 6530 | var bound_arg_src: ?LazySrcLoc = null; | 6562 | .direct => |func_inst| func_inst, |
| 6531 | var func: Air.Inst.Ref = undefined; | 6563 | .method => |method| method.func_inst, |
| 6532 | var arg_index: u32 = 0; | 6564 | }; |
| 6533 | switch (callee) { | | |
| 6534 | .direct => |func_inst| { | | |
| 6535 | resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len); | | |
| 6536 | func = func_inst; | | |
| 6537 | }, | | |
| 6538 | .method => |method| { | | |
| 6539 | resolved_args = try sema.arena.alloc(Air.Inst.Ref, args_len + 1); | | |
| 6540 | func = method.func_inst; | | |
| 6541 | resolved_args[0] = method.arg0_inst; | | |
| 6542 | arg_index += 1; | | |
| 6543 | bound_arg_src = callee_src; | | |
| 6544 | }, | | |
| 6545 | } | | |
| 6546 | | 6565 | |
| 6547 | const callee_ty = sema.typeOf(func); | 6566 | const callee_ty = sema.typeOf(func); |
| 6548 | const total_args = args_len + @intFromBool(bound_arg_src != null); | 6567 | const total_args = args_len + @intFromBool(callee == .method); |
| 6549 | const func_ty = try sema.checkCallArgumentCount(block, func, callee_src, callee_ty, total_args, bound_arg_src != null); | 6568 | const func_ty = try sema.checkCallArgumentCount(block, func, callee_src, callee_ty, total_args, callee == .method); |
| 6550 | | | |
| 6551 | const args_body = sema.code.extra[extra.end..]; | | |
| 6552 | | 6569 | |
| 6553 | var input_is_error = false; | 6570 | // The block index before the call, so we can potentially insert an error trace save here later. |
| 6554 | const block_index: Air.Inst.Index = @intCast(block.instructions.items.len); | 6571 | const block_index: Air.Inst.Index = @intCast(block.instructions.items.len); |
| 6555 | | 6572 | |
| 6556 | const func_ty_info = mod.typeToFunc(func_ty).?; | 6573 | // This will be set by `analyzeCall` to indicate whether any parameter was an error (making the |
| 6557 | const fn_params_len = func_ty_info.param_types.len; | 6574 | // error trace potentially dirty). |
| 6558 | const parent_comptime = block.is_comptime; | 6575 | var input_is_error = false; |
| 6559 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. | | |
| 6560 | var extra_index: usize = 0; | | |
| 6561 | var arg_start: u32 = args_len; | | |
| 6562 | while (extra_index < args_len) : ({ | | |
| 6563 | extra_index += 1; | | |
| 6564 | arg_index += 1; | | |
| 6565 | }) { | | |
| 6566 | const arg_end = sema.code.extra[extra.end + extra_index]; | | |
| 6567 | defer arg_start = arg_end; | | |
| 6568 | | | |
| 6569 | // Generate args to comptime params in comptime block. | | |
| 6570 | defer block.is_comptime = parent_comptime; | | |
| 6571 | if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) { | | |
| 6572 | block.is_comptime = true; | | |
| 6573 | // TODO set comptime_reason | | |
| 6574 | } | | |
| 6575 | | | |
| 6576 | sema.inst_map.putAssumeCapacity(inst, inst: { | | |
| 6577 | if (arg_index >= fn_params_len) | | |
| 6578 | break :inst Air.Inst.Ref.var_args_param_type; | | |
| 6579 | | 6576 | |
| 6580 | if (func_ty_info.param_types.get(ip)[arg_index] == .generic_poison_type) | 6577 | const args_info: CallArgsInfo = .{ .zir_call = .{ |
| 6581 | break :inst Air.Inst.Ref.generic_poison_type; | 6578 | .bound_arg = switch (callee) { |
| | 6579 | .direct => .none, |
| | 6580 | .method => |method| method.arg0_inst, |
| | 6581 | }, |
| | 6582 | .bound_arg_src = callee_src, |
| | 6583 | .call_inst = inst, |
| | 6584 | .call_node_offset = inst_data.src_node, |
| | 6585 | .num_args = args_len, |
| | 6586 | .args_body = sema.code.extra[extra.end..], |
| | 6587 | .any_arg_is_error = &input_is_error, |
| | 6588 | } }; |
| 6582 | | 6589 | |
| 6583 | break :inst try sema.addType(func_ty_info.param_types.get(ip)[arg_index].toType()); | 6590 | // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction. |
| 6584 | }); | 6591 | const call_dbg_node = inst - 1; |
| | 6592 | const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call); |
| 6585 | | 6593 | |
| 6586 | const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); | | |
| 6587 | const resolved_ty = sema.typeOf(resolved); | | |
| 6588 | if (resolved_ty.zigTypeTag(mod) == .NoReturn) { | | |
| 6589 | return resolved; | | |
| 6590 | } | | |
| 6591 | if (resolved_ty.isError(mod)) { | | |
| 6592 | input_is_error = true; | | |
| 6593 | } | | |
| 6594 | resolved_args[arg_index] = resolved; | | |
| 6595 | } | | |
| 6596 | if (sema.owner_func_index == .none or | 6594 | if (sema.owner_func_index == .none or |
| 6597 | !ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) | 6595 | !mod.intern_pool.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) |
| 6598 | { | 6596 | { |
| 6599 | input_is_error = false; // input was an error type, but no errorable fn's were actually called | 6597 | // No errorable fn actually called; we have no error return trace |
| | 6598 | input_is_error = false; |
| 6600 | } | 6599 | } |
| 6601 | | 6600 | |
| 6602 | // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction. | | |
| 6603 | const call_dbg_node = inst - 1; | | |
| 6604 | | | |
| 6605 | if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and | 6601 | if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and |
| 6606 | !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace)) | 6602 | !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace)) |
| 6607 | { | 6603 | { |
| 6608 | const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: { | | |
| 6609 | break :b try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node, .call); | | |
| 6610 | }; | | |
| 6611 | | | |
| 6612 | const return_ty = sema.typeOf(call_inst); | 6604 | const return_ty = sema.typeOf(call_inst); |
| 6613 | if (modifier != .always_tail and return_ty.isNoReturn(mod)) | 6605 | if (modifier != .always_tail and return_ty.isNoReturn(mod)) |
| 6614 | return call_inst; // call to "fn(...) noreturn", don't pop | 6606 | return call_inst; // call to "fn(...) noreturn", don't pop |
| 6615 | | 6607 | |
| | 6608 | // TODO: we don't fix up the error trace for always_tail correctly, we should be doing it |
| | 6609 | // *before* the recursive call. This will be a bit tricky to do and probably requires |
| | 6610 | // moving this logic into analyzeCall. But that's probably a good idea anyway. |
| | 6611 | if (modifier == .always_tail) |
| | 6612 | return call_inst; |
| | 6613 | |
| 6616 | // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only | 6614 | // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only |
| 6617 | // need to clean-up our own trace if we were passed to a non-error-handling expression. | 6615 | // need to clean-up our own trace if we were passed to a non-error-handling expression. |
| 6618 | if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError(mod))) { | 6616 | if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) { |
| 6619 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); | 6617 | const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); |
| 6620 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); | 6618 | const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); |
| 6621 | const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index"); | 6619 | const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index"); |
| ... | @@ -6635,12 +6633,9 @@ fn zirCall( | ... | @@ -6635,12 +6633,9 @@ fn zirCall( |
| 6635 | try sema.popErrorReturnTrace(block, call_src, operand, save_inst); | 6633 | try sema.popErrorReturnTrace(block, call_src, operand, save_inst); |
| 6636 | } | 6634 | } |
| 6637 | | 6635 | |
| 6638 | if (modifier == .always_tail) // Perform the call *after* the restore, so that a tail call is possible. | | |
| 6639 | return sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node, .call); | | |
| 6640 | | | |
| 6641 | return call_inst; | 6636 | return call_inst; |
| 6642 | } else { | 6637 | } else { |
| 6643 | return sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src, call_dbg_node, .call); | 6638 | return call_inst; |
| 6644 | } | 6639 | } |
| 6645 | } | 6640 | } |
| 6646 | | 6641 | |
| ... | @@ -6747,7 +6742,19 @@ fn callBuiltin( | ... | @@ -6747,7 +6742,19 @@ fn callBuiltin( |
| 6747 | if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) { | 6742 | if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) { |
| 6748 | std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len }); | 6743 | std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len }); |
| 6749 | } | 6744 | } |
| 6750 | _ = try sema.analyzeCall(block, builtin_fn, func_ty, call_src, call_src, modifier, false, args, null, null, operation); | 6745 | |
| | 6746 | _ = try sema.analyzeCall( |
| | 6747 | block, |
| | 6748 | builtin_fn, |
| | 6749 | func_ty, |
| | 6750 | call_src, |
| | 6751 | call_src, |
| | 6752 | modifier, |
| | 6753 | false, |
| | 6754 | .{ .resolved = .{ .src = call_src, .args = args } }, |
| | 6755 | null, |
| | 6756 | operation, |
| | 6757 | ); |
| 6751 | } | 6758 | } |
| 6752 | | 6759 | |
| 6753 | const CallOperation = enum { | 6760 | const CallOperation = enum { |
| ... | @@ -6758,6 +6765,251 @@ const CallOperation = enum { | ... | @@ -6758,6 +6765,251 @@ const CallOperation = enum { |
| 6758 | @"error return", | 6765 | @"error return", |
| 6759 | }; | 6766 | }; |
| 6760 | | 6767 | |
| | 6768 | const CallArgsInfo = union(enum) { |
| | 6769 | /// The full list of resolved (but uncoerced) arguments is known ahead of time. |
| | 6770 | resolved: struct { |
| | 6771 | src: LazySrcLoc, |
| | 6772 | args: []const Air.Inst.Ref, |
| | 6773 | }, |
| | 6774 | |
| | 6775 | /// The list of resolved (but uncoerced) arguments is known ahead of time, but |
| | 6776 | /// originated from a usage of the @call builtin at the given node offset. |
| | 6777 | call_builtin: struct { |
| | 6778 | call_node_offset: i32, |
| | 6779 | args: []const Air.Inst.Ref, |
| | 6780 | }, |
| | 6781 | |
| | 6782 | /// This call corresponds to a ZIR call instruction. The arguments have not yet been |
| | 6783 | /// resolved. They must be resolved by `analyzeCall` so that argument resolution and |
| | 6784 | /// generic instantiation may be interleaved. This is required for RLS to work on |
| | 6785 | /// generic parameters. |
| | 6786 | zir_call: struct { |
| | 6787 | /// This may be `none`, in which case it is ignored. Otherwise, it is the |
| | 6788 | /// already-resolved value of the first argument, from method call syntax. |
| | 6789 | bound_arg: Air.Inst.Ref, |
| | 6790 | /// The source location of `bound_arg` if it is not `null`. Otherwise `undefined`. |
| | 6791 | bound_arg_src: LazySrcLoc, |
| | 6792 | /// The ZIR call instruction. The parameter type is placed at this index while |
| | 6793 | /// analyzing arguments. |
| | 6794 | call_inst: Zir.Inst.Index, |
| | 6795 | /// The node offset of `call_inst`. |
| | 6796 | call_node_offset: i32, |
| | 6797 | /// The number of arguments to this call, not including `bound_arg`. |
| | 6798 | num_args: u32, |
| | 6799 | /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it |
| | 6800 | /// is not `none`). Format is precisely the same as trailing data of ZIR `call`. |
| | 6801 | args_body: []const Zir.Inst.Index, |
| | 6802 | /// This bool will be set to true if any argument evaluated turns out to have an error set or error union type. |
| | 6803 | /// This is used by the caller to restore the error return trace when necessary. |
| | 6804 | any_arg_is_error: *bool, |
| | 6805 | }, |
| | 6806 | |
| | 6807 | fn count(cai: CallArgsInfo) usize { |
| | 6808 | return switch (cai) { |
| | 6809 | inline .resolved, .call_builtin => |resolved| resolved.args.len, |
| | 6810 | .zir_call => |zir_call| zir_call.num_args + @intFromBool(zir_call.bound_arg != .none), |
| | 6811 | }; |
| | 6812 | } |
| | 6813 | |
| | 6814 | fn argSrc(cai: CallArgsInfo, block: *Block, arg_index: usize) LazySrcLoc { |
| | 6815 | return switch (cai) { |
| | 6816 | .resolved => |resolved| resolved.src, |
| | 6817 | .call_builtin => |call_builtin| .{ .call_arg = .{ |
| | 6818 | .decl = block.src_decl, |
| | 6819 | .call_node_offset = call_builtin.call_node_offset, |
| | 6820 | .arg_index = @intCast(arg_index), |
| | 6821 | } }, |
| | 6822 | .zir_call => |zir_call| if (arg_index == 0 and zir_call.bound_arg != .none) { |
| | 6823 | return zir_call.bound_arg_src; |
| | 6824 | } else .{ .call_arg = .{ |
| | 6825 | .decl = block.src_decl, |
| | 6826 | .call_node_offset = zir_call.call_node_offset, |
| | 6827 | .arg_index = @intCast(arg_index - @intFromBool(zir_call.bound_arg != .none)), |
| | 6828 | } }, |
| | 6829 | }; |
| | 6830 | } |
| | 6831 | |
| | 6832 | /// Analyzes the arg at `arg_index` and coerces it to `param_ty`. |
| | 6833 | /// `param_ty` may be `generic_poison` or `var_args_param`. |
| | 6834 | /// `func_ty_info` may be the type before instantiation, even if a generic |
| | 6835 | /// instantiation has been partially completed. |
| | 6836 | fn analyzeArg( |
| | 6837 | cai: CallArgsInfo, |
| | 6838 | sema: *Sema, |
| | 6839 | block: *Block, |
| | 6840 | arg_index: usize, |
| | 6841 | param_ty: Type, |
| | 6842 | func_ty_info: InternPool.Key.FuncType, |
| | 6843 | func_inst: Air.Inst.Ref, |
| | 6844 | ) CompileError!Air.Inst.Ref { |
| | 6845 | const mod = sema.mod; |
| | 6846 | const param_count = func_ty_info.param_types.len; |
| | 6847 | switch (param_ty.toIntern()) { |
| | 6848 | .generic_poison_type, .var_args_param_type => {}, |
| | 6849 | else => try sema.queueFullTypeResolution(param_ty), |
| | 6850 | } |
| | 6851 | const uncoerced_arg: Air.Inst.Ref = switch (cai) { |
| | 6852 | inline .resolved, .call_builtin => |resolved| resolved.args[arg_index], |
| | 6853 | .zir_call => |zir_call| arg_val: { |
| | 6854 | const has_bound_arg = zir_call.bound_arg != .none; |
| | 6855 | if (arg_index == 0 and has_bound_arg) { |
| | 6856 | break :arg_val zir_call.bound_arg; |
| | 6857 | } |
| | 6858 | const real_arg_idx = arg_index - @intFromBool(has_bound_arg); |
| | 6859 | |
| | 6860 | const arg_body = if (real_arg_idx == 0) blk: { |
| | 6861 | const start = zir_call.num_args; |
| | 6862 | const end = zir_call.args_body[0]; |
| | 6863 | break :blk zir_call.args_body[start..end]; |
| | 6864 | } else blk: { |
| | 6865 | const start = zir_call.args_body[real_arg_idx - 1]; |
| | 6866 | const end = zir_call.args_body[real_arg_idx]; |
| | 6867 | break :blk zir_call.args_body[start..end]; |
| | 6868 | }; |
| | 6869 | |
| | 6870 | // Generate args to comptime params in comptime block |
| | 6871 | const parent_comptime = block.is_comptime; |
| | 6872 | defer block.is_comptime = parent_comptime; |
| | 6873 | // Note that we are indexing into parameters, not arguments, so use `arg_index` instead of `real_arg_idx` |
| | 6874 | if (arg_index < @min(param_count, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) { |
| | 6875 | block.is_comptime = true; |
| | 6876 | // TODO set comptime_reason |
| | 6877 | } |
| | 6878 | // Give the arg its result type |
| | 6879 | sema.inst_map.putAssumeCapacity(zir_call.call_inst, try sema.addType(param_ty)); |
| | 6880 | // Resolve the arg! |
| | 6881 | const uncoerced_arg = try sema.resolveBody(block, arg_body, zir_call.call_inst); |
| | 6882 | |
| | 6883 | if (sema.typeOf(uncoerced_arg).zigTypeTag(mod) == .NoReturn) { |
| | 6884 | // This terminates resolution of arguments. The caller should |
| | 6885 | // propagate this. |
| | 6886 | return uncoerced_arg; |
| | 6887 | } |
| | 6888 | |
| | 6889 | if (sema.typeOf(uncoerced_arg).isError(mod)) { |
| | 6890 | zir_call.any_arg_is_error.* = true; |
| | 6891 | } |
| | 6892 | |
| | 6893 | break :arg_val uncoerced_arg; |
| | 6894 | }, |
| | 6895 | }; |
| | 6896 | switch (param_ty.toIntern()) { |
| | 6897 | .generic_poison_type => return uncoerced_arg, |
| | 6898 | .var_args_param_type => return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index)), |
| | 6899 | else => return sema.coerceExtra( |
| | 6900 | block, |
| | 6901 | param_ty, |
| | 6902 | uncoerced_arg, |
| | 6903 | cai.argSrc(block, arg_index), |
| | 6904 | .{ .param_src = .{ |
| | 6905 | .func_inst = func_inst, |
| | 6906 | .param_i = @intCast(arg_index), |
| | 6907 | } }, |
| | 6908 | ) catch |err| switch (err) { |
| | 6909 | error.NotCoercible => unreachable, |
| | 6910 | else => |e| return e, |
| | 6911 | }, |
| | 6912 | } |
| | 6913 | } |
| | 6914 | }; |
| | 6915 | |
| | 6916 | /// While performing an inline call, we need to switch between two Sema states a few times: the |
| | 6917 | /// state for the caller (with the callee's `code`, `fn_ret_ty`, etc), and the state for the callee. |
| | 6918 | /// These cannot be two separate Sema instances as they must share AIR. |
| | 6919 | /// Therefore, this struct acts as a helper to switch between the two. |
| | 6920 | /// This switching is required during argument evaluation, where function argument analysis must be |
| | 6921 | /// interleaved with resolving generic parameter types. |
| | 6922 | const InlineCallSema = struct { |
| | 6923 | sema: *Sema, |
| | 6924 | cur: enum { |
| | 6925 | caller, |
| | 6926 | callee, |
| | 6927 | }, |
| | 6928 | |
| | 6929 | other_code: Zir, |
| | 6930 | other_func_index: InternPool.Index, |
| | 6931 | other_fn_ret_ty: Type, |
| | 6932 | other_fn_ret_ty_ies: ?*InferredErrorSet, |
| | 6933 | other_inst_map: InstMap, |
| | 6934 | other_error_return_trace_index_on_fn_entry: Air.Inst.Ref, |
| | 6935 | other_generic_owner: InternPool.Index, |
| | 6936 | other_generic_call_src: LazySrcLoc, |
| | 6937 | other_generic_call_decl: Decl.OptionalIndex, |
| | 6938 | |
| | 6939 | /// Sema should currently be set up for the caller (i.e. unchanged yet). This init will not |
| | 6940 | /// change that. The other parameters contain data for the callee Sema. The other modified |
| | 6941 | /// Sema fields are all initialized to default values for the callee. |
| | 6942 | /// Must call deinit on the result. |
| | 6943 | fn init( |
| | 6944 | sema: *Sema, |
| | 6945 | callee_code: Zir, |
| | 6946 | callee_func_index: InternPool.Index, |
| | 6947 | callee_error_return_trace_index_on_fn_entry: Air.Inst.Ref, |
| | 6948 | ) InlineCallSema { |
| | 6949 | return .{ |
| | 6950 | .sema = sema, |
| | 6951 | .cur = .caller, |
| | 6952 | .other_code = callee_code, |
| | 6953 | .other_func_index = callee_func_index, |
| | 6954 | .other_fn_ret_ty = Type.void, |
| | 6955 | .other_fn_ret_ty_ies = null, |
| | 6956 | .other_inst_map = .{}, |
| | 6957 | .other_error_return_trace_index_on_fn_entry = callee_error_return_trace_index_on_fn_entry, |
| | 6958 | .other_generic_owner = .none, |
| | 6959 | .other_generic_call_src = .unneeded, |
| | 6960 | .other_generic_call_decl = .none, |
| | 6961 | }; |
| | 6962 | } |
| | 6963 | |
| | 6964 | /// Switch back to the caller Sema if necessary and free all temporary state of the callee Sema. |
| | 6965 | fn deinit(ics: *InlineCallSema) void { |
| | 6966 | switch (ics.cur) { |
| | 6967 | .caller => {}, |
| | 6968 | .callee => ics.swap(), |
| | 6969 | } |
| | 6970 | // Callee Sema owns the inst_map memory |
| | 6971 | ics.other_inst_map.deinit(ics.sema.gpa); |
| | 6972 | ics.* = undefined; |
| | 6973 | } |
| | 6974 | |
| | 6975 | /// Returns a Sema instance suitable for usage from the caller context. |
| | 6976 | fn caller(ics: *InlineCallSema) *Sema { |
| | 6977 | switch (ics.cur) { |
| | 6978 | .caller => {}, |
| | 6979 | .callee => ics.swap(), |
| | 6980 | } |
| | 6981 | return ics.sema; |
| | 6982 | } |
| | 6983 | |
| | 6984 | /// Returns a Sema instance suitable for usage from the callee context. |
| | 6985 | fn callee(ics: *InlineCallSema) *Sema { |
| | 6986 | switch (ics.cur) { |
| | 6987 | .caller => ics.swap(), |
| | 6988 | .callee => {}, |
| | 6989 | } |
| | 6990 | return ics.sema; |
| | 6991 | } |
| | 6992 | |
| | 6993 | /// Internal use only. Swaps to the other Sema state. |
| | 6994 | fn swap(ics: *InlineCallSema) void { |
| | 6995 | ics.cur = switch (ics.cur) { |
| | 6996 | .caller => .callee, |
| | 6997 | .callee => .caller, |
| | 6998 | }; |
| | 6999 | // zig fmt: off |
| | 7000 | std.mem.swap(Zir, &ics.sema.code, &ics.other_code); |
| | 7001 | std.mem.swap(InternPool.Index, &ics.sema.func_index, &ics.other_func_index); |
| | 7002 | std.mem.swap(Type, &ics.sema.fn_ret_ty, &ics.other_fn_ret_ty); |
| | 7003 | std.mem.swap(?*InferredErrorSet, &ics.sema.fn_ret_ty_ies, &ics.other_fn_ret_ty_ies); |
| | 7004 | std.mem.swap(InstMap, &ics.sema.inst_map, &ics.other_inst_map); |
| | 7005 | std.mem.swap(InternPool.Index, &ics.sema.generic_owner, &ics.other_generic_owner); |
| | 7006 | std.mem.swap(LazySrcLoc, &ics.sema.generic_call_src, &ics.other_generic_call_src); |
| | 7007 | std.mem.swap(Decl.OptionalIndex, &ics.sema.generic_call_decl, &ics.other_generic_call_decl); |
| | 7008 | std.mem.swap(Air.Inst.Ref, &ics.sema.error_return_trace_index_on_fn_entry, &ics.other_error_return_trace_index_on_fn_entry); |
| | 7009 | // zig fmt: on |
| | 7010 | } |
| | 7011 | }; |
| | 7012 | |
| 6761 | fn analyzeCall( | 7013 | fn analyzeCall( |
| 6762 | sema: *Sema, | 7014 | sema: *Sema, |
| 6763 | block: *Block, | 7015 | block: *Block, |
| ... | @@ -6767,8 +7019,7 @@ fn analyzeCall( | ... | @@ -6767,8 +7019,7 @@ fn analyzeCall( |
| 6767 | call_src: LazySrcLoc, | 7019 | call_src: LazySrcLoc, |
| 6768 | modifier: std.builtin.CallModifier, | 7020 | modifier: std.builtin.CallModifier, |
| 6769 | ensure_result_used: bool, | 7021 | ensure_result_used: bool, |
| 6770 | uncasted_args: []const Air.Inst.Ref, | 7022 | args_info: CallArgsInfo, |
| 6771 | bound_arg_src: ?LazySrcLoc, | | |
| 6772 | call_dbg_node: ?Zir.Inst.Index, | 7023 | call_dbg_node: ?Zir.Inst.Index, |
| 6773 | operation: CallOperation, | 7024 | operation: CallOperation, |
| 6774 | ) CompileError!Air.Inst.Ref { | 7025 | ) CompileError!Air.Inst.Ref { |
| ... | @@ -6777,7 +7028,6 @@ fn analyzeCall( | ... | @@ -6777,7 +7028,6 @@ fn analyzeCall( |
| 6777 | | 7028 | |
| 6778 | const callee_ty = sema.typeOf(func); | 7029 | const callee_ty = sema.typeOf(func); |
| 6779 | const func_ty_info = mod.typeToFunc(func_ty).?; | 7030 | const func_ty_info = mod.typeToFunc(func_ty).?; |
| 6780 | const fn_params_len = func_ty_info.param_types.len; | | |
| 6781 | const cc = func_ty_info.cc; | 7031 | const cc = func_ty_info.cc; |
| 6782 | if (cc == .Naked) { | 7032 | if (cc == .Naked) { |
| 6783 | const maybe_decl = try sema.funcDeclSrc(func); | 7033 | const maybe_decl = try sema.funcDeclSrc(func); |
| ... | @@ -6862,9 +7112,8 @@ fn analyzeCall( | ... | @@ -6862,9 +7112,8 @@ fn analyzeCall( |
| 6862 | func_src, | 7112 | func_src, |
| 6863 | call_src, | 7113 | call_src, |
| 6864 | ensure_result_used, | 7114 | ensure_result_used, |
| 6865 | uncasted_args, | 7115 | args_info, |
| 6866 | call_tag, | 7116 | call_tag, |
| 6867 | bound_arg_src, | | |
| 6868 | call_dbg_node, | 7117 | call_dbg_node, |
| 6869 | )) |some| { | 7118 | )) |some| { |
| 6870 | return some; | 7119 | return some; |
| ... | @@ -6939,31 +7188,23 @@ fn analyzeCall( | ... | @@ -6939,31 +7188,23 @@ fn analyzeCall( |
| 6939 | .block_inst = block_inst, | 7188 | .block_inst = block_inst, |
| 6940 | }, | 7189 | }, |
| 6941 | }; | 7190 | }; |
| 6942 | // In order to save a bit of stack space, directly modify Sema rather | 7191 | |
| 6943 | // than create a child one. | | |
| 6944 | const parent_zir = sema.code; | | |
| 6945 | const module_fn = mod.funcInfo(module_fn_index); | 7192 | const module_fn = mod.funcInfo(module_fn_index); |
| 6946 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | 7193 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); |
| 6947 | sema.code = fn_owner_decl.getFileScope(mod).zir; | | |
| 6948 | defer sema.code = parent_zir; | | |
| 6949 | | | |
| 6950 | try mod.declareDeclDependencyType(sema.owner_decl_index, module_fn.owner_decl, .function_body); | | |
| 6951 | | 7194 | |
| 6952 | const parent_inst_map = sema.inst_map; | 7195 | // We effectively want a child Sema here, but can't literally do that, because we need AIR |
| 6953 | sema.inst_map = .{}; | 7196 | // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in |
| 6954 | defer { | 7197 | // scope, we should use its `caller`/`callee` methods rather than using `sema` directly |
| 6955 | sema.src = call_src; | 7198 | // whenever performing an operation where the difference matters. |
| 6956 | sema.inst_map.deinit(gpa); | 7199 | var ics = InlineCallSema.init( |
| 6957 | sema.inst_map = parent_inst_map; | 7200 | sema, |
| 6958 | } | 7201 | fn_owner_decl.getFileScope(mod).zir, |
| 6959 | | 7202 | module_fn_index, |
| 6960 | const parent_func_index = sema.func_index; | 7203 | block.error_return_trace_index, |
| 6961 | sema.func_index = module_fn_index; | 7204 | ); |
| 6962 | defer sema.func_index = parent_func_index; | 7205 | defer ics.deinit(); |
| 6963 | | 7206 | |
| 6964 | const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry; | 7207 | try mod.declareDeclDependencyType(ics.callee().owner_decl_index, module_fn.owner_decl, .function_body); |
| 6965 | sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index; | | |
| 6966 | defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index; | | |
| 6967 | | 7208 | |
| 6968 | var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope); | 7209 | var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope); |
| 6969 | defer wip_captures.deinit(); | 7210 | defer wip_captures.deinit(); |
| ... | @@ -7019,37 +7260,37 @@ fn analyzeCall( | ... | @@ -7019,37 +7260,37 @@ fn analyzeCall( |
| 7019 | // the AIR instructions of the callsite. The callee could be a generic function | 7260 | // the AIR instructions of the callsite. The callee could be a generic function |
| 7020 | // which means its parameter type expressions must be resolved in order and used | 7261 | // which means its parameter type expressions must be resolved in order and used |
| 7021 | // to successively coerce the arguments. | 7262 | // to successively coerce the arguments. |
| 7022 | const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst); | 7263 | const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst); |
| 7023 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body); | 7264 | try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); |
| 7024 | | 7265 | |
| 7025 | var has_comptime_args = false; | 7266 | var has_comptime_args = false; |
| 7026 | var arg_i: u32 = 0; | 7267 | var arg_i: u32 = 0; |
| 7027 | for (fn_info.param_body) |inst| { | 7268 | for (fn_info.param_body) |inst| { |
| 7028 | const arg_src: LazySrcLoc = if (arg_i == 0 and bound_arg_src != null) | 7269 | const opt_noreturn_ref = try analyzeInlineCallArg( |
| 7029 | bound_arg_src.? | 7270 | &ics, |
| 7030 | else | | |
| 7031 | .{ .call_arg = .{ | | |
| 7032 | .decl = block.src_decl, | | |
| 7033 | .call_node_offset = call_src.node_offset.x, | | |
| 7034 | .arg_index = arg_i - @intFromBool(bound_arg_src != null), | | |
| 7035 | } }; | | |
| 7036 | try sema.analyzeInlineCallArg( | | |
| 7037 | block, | 7271 | block, |
| 7038 | &child_block, | 7272 | &child_block, |
| 7039 | arg_src, | | |
| 7040 | inst, | 7273 | inst, |
| 7041 | new_fn_info.param_types, | 7274 | new_fn_info.param_types, |
| 7042 | &arg_i, | 7275 | &arg_i, |
| 7043 | uncasted_args, | 7276 | args_info, |
| 7044 | is_comptime_call, | 7277 | is_comptime_call, |
| 7045 | &should_memoize, | 7278 | &should_memoize, |
| 7046 | memoized_arg_values, | 7279 | memoized_arg_values, |
| 7047 | func_ty_info.param_types, | 7280 | func_ty_info, |
| 7048 | func, | 7281 | func, |
| 7049 | &has_comptime_args, | 7282 | &has_comptime_args, |
| 7050 | ); | 7283 | ); |
| | 7284 | if (opt_noreturn_ref) |ref| { |
| | 7285 | // Analyzing this argument gave a ref of a noreturn type. Terminate argument analysis here. |
| | 7286 | return ref; |
| | 7287 | } |
| 7051 | } | 7288 | } |
| 7052 | | 7289 | |
| | 7290 | // From here, we only really need to use the callee Sema. Make it the active one, then we |
| | 7291 | // can just use `sema` directly. |
| | 7292 | _ = ics.callee(); |
| | 7293 | |
| 7053 | if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure) | 7294 | if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure) |
| 7054 | return error.AnalysisFail; | 7295 | return error.AnalysisFail; |
| 7055 | | 7296 | |
| ... | @@ -7073,26 +7314,7 @@ fn analyzeCall( | ... | @@ -7073,26 +7314,7 @@ fn analyzeCall( |
| 7073 | else | 7314 | else |
| 7074 | try sema.resolveInst(fn_info.ret_ty_ref); | 7315 | try sema.resolveInst(fn_info.ret_ty_ref); |
| 7075 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 7316 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 7076 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); | 7317 | sema.fn_ret_ty = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); |
| 7077 | const parent_fn_ret_ty = sema.fn_ret_ty; | | |
| 7078 | const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies; | | |
| 7079 | const parent_generic_owner = sema.generic_owner; | | |
| 7080 | const parent_generic_call_src = sema.generic_call_src; | | |
| 7081 | const parent_generic_bound_arg_src = sema.generic_bound_arg_src; | | |
| 7082 | const parent_generic_call_decl = sema.generic_call_decl; | | |
| 7083 | sema.fn_ret_ty = bare_return_type; | | |
| 7084 | sema.fn_ret_ty_ies = null; | | |
| 7085 | sema.generic_owner = .none; | | |
| 7086 | sema.generic_call_src = .unneeded; | | |
| 7087 | sema.generic_bound_arg_src = null; | | |
| 7088 | sema.generic_call_decl = .none; | | |
| 7089 | defer sema.fn_ret_ty = parent_fn_ret_ty; | | |
| 7090 | defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies; | | |
| 7091 | defer sema.generic_owner = parent_generic_owner; | | |
| 7092 | defer sema.generic_call_src = parent_generic_call_src; | | |
| 7093 | defer sema.generic_bound_arg_src = parent_generic_bound_arg_src; | | |
| 7094 | defer sema.generic_call_decl = parent_generic_call_decl; | | |
| 7095 | | | |
| 7096 | if (module_fn.analysis(ip).inferred_error_set) { | 7318 | if (module_fn.analysis(ip).inferred_error_set) { |
| 7097 | // Create a fresh inferred error set type for inline/comptime calls. | 7319 | // Create a fresh inferred error set type for inline/comptime calls. |
| 7098 | const ies = try sema.arena.create(InferredErrorSet); | 7320 | const ies = try sema.arena.create(InferredErrorSet); |
| ... | @@ -7100,7 +7322,7 @@ fn analyzeCall( | ... | @@ -7100,7 +7322,7 @@ fn analyzeCall( |
| 7100 | sema.fn_ret_ty_ies = ies; | 7322 | sema.fn_ret_ty_ies = ies; |
| 7101 | sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{ | 7323 | sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{ |
| 7102 | .error_set_type = .adhoc_inferred_error_set_type, | 7324 | .error_set_type = .adhoc_inferred_error_set_type, |
| 7103 | .payload_type = bare_return_type.toIntern(), | 7325 | .payload_type = sema.fn_ret_ty.toIntern(), |
| 7104 | } })).toType(); | 7326 | } })).toType(); |
| 7105 | } | 7327 | } |
| 7106 | | 7328 | |
| ... | @@ -7123,7 +7345,7 @@ fn analyzeCall( | ... | @@ -7123,7 +7345,7 @@ fn analyzeCall( |
| 7123 | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); | 7345 | new_fn_info.return_type = sema.fn_ret_ty.toIntern(); |
| 7124 | const new_func_resolved_ty = try mod.funcType(new_fn_info); | 7346 | const new_func_resolved_ty = try mod.funcType(new_fn_info); |
| 7125 | if (!is_comptime_call and !block.is_typeof) { | 7347 | if (!is_comptime_call and !block.is_typeof) { |
| 7126 | try sema.emitDbgInline(block, parent_func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin); | 7348 | try sema.emitDbgInline(block, sema.func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin); |
| 7127 | | 7349 | |
| 7128 | const zir_tags = sema.code.instructions.items(.tag); | 7350 | const zir_tags = sema.code.instructions.items(.tag); |
| 7129 | for (fn_info.param_body) |param| switch (zir_tags[param]) { | 7351 | for (fn_info.param_body) |param| switch (zir_tags[param]) { |
| ... | @@ -7157,7 +7379,7 @@ fn analyzeCall( | ... | @@ -7157,7 +7379,7 @@ fn analyzeCall( |
| 7157 | const err_msg = sema.err orelse return err; | 7379 | const err_msg = sema.err orelse return err; |
| 7158 | if (mem.eql(u8, err_msg.msg, recursive_msg)) return err; | 7380 | if (mem.eql(u8, err_msg.msg, recursive_msg)) return err; |
| 7159 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); | 7381 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); |
| 7160 | err_msg.clearTrace(sema.gpa); | 7382 | err_msg.clearTrace(gpa); |
| 7161 | return err; | 7383 | return err; |
| 7162 | }, | 7384 | }, |
| 7163 | else => |e| return e, | 7385 | else => |e| return e, |
| ... | @@ -7171,8 +7393,8 @@ fn analyzeCall( | ... | @@ -7171,8 +7393,8 @@ fn analyzeCall( |
| 7171 | try sema.emitDbgInline( | 7393 | try sema.emitDbgInline( |
| 7172 | block, | 7394 | block, |
| 7173 | module_fn_index, | 7395 | module_fn_index, |
| 7174 | parent_func_index, | 7396 | sema.func_index, |
| 7175 | mod.funcOwnerDeclPtr(parent_func_index).ty, | 7397 | mod.funcOwnerDeclPtr(sema.func_index).ty, |
| 7176 | .dbg_inline_end, | 7398 | .dbg_inline_end, |
| 7177 | ); | 7399 | ); |
| 7178 | } | 7400 | } |
| ... | @@ -7217,47 +7439,16 @@ fn analyzeCall( | ... | @@ -7217,47 +7439,16 @@ fn analyzeCall( |
| 7217 | } else res: { | 7439 | } else res: { |
| 7218 | assert(!func_ty_info.is_generic); | 7440 | assert(!func_ty_info.is_generic); |
| 7219 | | 7441 | |
| 7220 | const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len); | 7442 | const args = try sema.arena.alloc(Air.Inst.Ref, args_info.count()); |
| 7221 | for (uncasted_args, 0..) |uncasted_arg, i| { | 7443 | for (args, 0..) |*arg_out, arg_idx| { |
| 7222 | if (i < fn_params_len) { | 7444 | // Non-generic, so param types are already resolved |
| 7223 | const opts: CoerceOpts = .{ .param_src = .{ | 7445 | const param_ty = if (arg_idx < func_ty_info.param_types.len) ty: { |
| 7224 | .func_inst = func, | 7446 | break :ty func_ty_info.param_types.get(ip)[arg_idx].toType(); |
| 7225 | .param_i = @intCast(i), | 7447 | } else InternPool.Index.var_args_param_type.toType(); |
| 7226 | } }; | 7448 | assert(!param_ty.isGenericPoison()); |
| 7227 | const param_ty = func_ty_info.param_types.get(ip)[i].toType(); | 7449 | arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func); |
| 7228 | args[i] = sema.analyzeCallArg( | 7450 | if (sema.typeOf(arg_out.*).zigTypeTag(mod) == .NoReturn) { |
| 7229 | block, | 7451 | return arg_out.*; |
| 7230 | .unneeded, | | |
| 7231 | param_ty, | | |
| 7232 | uncasted_arg, | | |
| 7233 | opts, | | |
| 7234 | ) catch |err| switch (err) { | | |
| 7235 | error.NeededSourceLocation => { | | |
| 7236 | const decl = mod.declPtr(block.src_decl); | | |
| 7237 | _ = try sema.analyzeCallArg( | | |
| 7238 | block, | | |
| 7239 | mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src), | | |
| 7240 | param_ty, | | |
| 7241 | uncasted_arg, | | |
| 7242 | opts, | | |
| 7243 | ); | | |
| 7244 | unreachable; | | |
| 7245 | }, | | |
| 7246 | else => |e| return e, | | |
| 7247 | }; | | |
| 7248 | } else { | | |
| 7249 | args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) { | | |
| 7250 | error.NeededSourceLocation => { | | |
| 7251 | const decl = mod.declPtr(block.src_decl); | | |
| 7252 | _ = try sema.coerceVarArgParam( | | |
| 7253 | block, | | |
| 7254 | uncasted_arg, | | |
| 7255 | mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src), | | |
| 7256 | ); | | |
| 7257 | unreachable; | | |
| 7258 | }, | | |
| 7259 | else => |e| return e, | | |
| 7260 | }; | | |
| 7261 | } | 7452 | } |
| 7262 | } | 7453 | } |
| 7263 | | 7454 | |
| ... | @@ -7341,25 +7532,25 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ | ... | @@ -7341,25 +7532,25 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ |
| 7341 | return Air.Inst.Ref.unreachable_value; | 7532 | return Air.Inst.Ref.unreachable_value; |
| 7342 | } | 7533 | } |
| 7343 | | 7534 | |
| | 7535 | /// Usually, returns null. If an argument was noreturn, returns that ref (which should become the call result). |
| 7344 | fn analyzeInlineCallArg( | 7536 | fn analyzeInlineCallArg( |
| 7345 | sema: *Sema, | 7537 | ics: *InlineCallSema, |
| 7346 | arg_block: *Block, | 7538 | arg_block: *Block, |
| 7347 | param_block: *Block, | 7539 | param_block: *Block, |
| 7348 | arg_src: LazySrcLoc, | | |
| 7349 | inst: Zir.Inst.Index, | 7540 | inst: Zir.Inst.Index, |
| 7350 | new_param_types: []InternPool.Index, | 7541 | new_param_types: []InternPool.Index, |
| 7351 | arg_i: *u32, | 7542 | arg_i: *u32, |
| 7352 | uncasted_args: []const Air.Inst.Ref, | 7543 | args_info: CallArgsInfo, |
| 7353 | is_comptime_call: bool, | 7544 | is_comptime_call: bool, |
| 7354 | should_memoize: *bool, | 7545 | should_memoize: *bool, |
| 7355 | memoized_arg_values: []InternPool.Index, | 7546 | memoized_arg_values: []InternPool.Index, |
| 7356 | raw_param_types: InternPool.Index.Slice, | 7547 | func_ty_info: InternPool.Key.FuncType, |
| 7357 | func_inst: Air.Inst.Ref, | 7548 | func_inst: Air.Inst.Ref, |
| 7358 | has_comptime_args: *bool, | 7549 | has_comptime_args: *bool, |
| 7359 | ) !void { | 7550 | ) !?Air.Inst.Ref { |
| 7360 | const mod = sema.mod; | 7551 | const mod = ics.sema.mod; |
| 7361 | const ip = &mod.intern_pool; | 7552 | const ip = &mod.intern_pool; |
| 7362 | const zir_tags = sema.code.instructions.items(.tag); | 7553 | const zir_tags = ics.callee().code.instructions.items(.tag); |
| 7363 | switch (zir_tags[inst]) { | 7554 | switch (zir_tags[inst]) { |
| 7364 | .param_comptime, .param_anytype_comptime => has_comptime_args.* = true, | 7555 | .param_comptime, .param_anytype_comptime => has_comptime_args.* = true, |
| 7365 | else => {}, | 7556 | else => {}, |
| ... | @@ -7368,39 +7559,36 @@ fn analyzeInlineCallArg( | ... | @@ -7368,39 +7559,36 @@ fn analyzeInlineCallArg( |
| 7368 | .param, .param_comptime => { | 7559 | .param, .param_comptime => { |
| 7369 | // Evaluate the parameter type expression now that previous ones have | 7560 | // Evaluate the parameter type expression now that previous ones have |
| 7370 | // been mapped, and coerce the corresponding argument to it. | 7561 | // been mapped, and coerce the corresponding argument to it. |
| 7371 | const pl_tok = sema.code.instructions.items(.data)[inst].pl_tok; | 7562 | const pl_tok = ics.callee().code.instructions.items(.data)[inst].pl_tok; |
| 7372 | const param_src = pl_tok.src(); | 7563 | const param_src = pl_tok.src(); |
| 7373 | const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index); | 7564 | const extra = ics.callee().code.extraData(Zir.Inst.Param, pl_tok.payload_index); |
| 7374 | const param_body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 7565 | const param_body = ics.callee().code.extra[extra.end..][0..extra.data.body_len]; |
| 7375 | const param_ty = param_ty: { | 7566 | const param_ty = param_ty: { |
| 7376 | const raw_param_ty = raw_param_types.get(ip)[arg_i.*]; | 7567 | const raw_param_ty = func_ty_info.param_types.get(ip)[arg_i.*]; |
| 7377 | if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty; | 7568 | if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty; |
| 7378 | const param_ty_inst = try sema.resolveBody(param_block, param_body, inst); | 7569 | const param_ty_inst = try ics.callee().resolveBody(param_block, param_body, inst); |
| 7379 | const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst); | 7570 | const param_ty = try ics.callee().analyzeAsType(param_block, param_src, param_ty_inst); |
| 7380 | break :param_ty param_ty.toIntern(); | 7571 | break :param_ty param_ty.toIntern(); |
| 7381 | }; | 7572 | }; |
| 7382 | new_param_types[arg_i.*] = param_ty; | 7573 | new_param_types[arg_i.*] = param_ty; |
| 7383 | const uncasted_arg = uncasted_args[arg_i.*]; | 7574 | const casted_arg = try args_info.analyzeArg(ics.caller(), arg_block, arg_i.*, param_ty.toType(), func_ty_info, func_inst); |
| 7384 | if (try sema.typeRequiresComptime(param_ty.toType())) { | 7575 | if (ics.caller().typeOf(casted_arg).zigTypeTag(mod) == .NoReturn) { |
| 7385 | _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| { | 7576 | return casted_arg; |
| 7386 | if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err); | 7577 | } |
| | 7578 | const arg_src = args_info.argSrc(arg_block, arg_i.*); |
| | 7579 | if (try ics.callee().typeRequiresComptime(param_ty.toType())) { |
| | 7580 | _ = ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| { |
| | 7581 | if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(ics.caller(), ics.caller().err); |
| 7387 | return err; | 7582 | return err; |
| 7388 | }; | 7583 | }; |
| 7389 | } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) { | 7584 | } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) { |
| 7390 | _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime"); | 7585 | _ = try ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "parameter is comptime"); |
| 7391 | } | 7586 | } |
| 7392 | const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{ | | |
| 7393 | .func_inst = func_inst, | | |
| 7394 | .param_i = @intCast(arg_i.*), | | |
| 7395 | } }) catch |err| switch (err) { | | |
| 7396 | error.NotCoercible => unreachable, | | |
| 7397 | else => |e| return e, | | |
| 7398 | }; | | |
| 7399 | | 7587 | |
| 7400 | if (is_comptime_call) { | 7588 | if (is_comptime_call) { |
| 7401 | sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); | 7589 | ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg); |
| 7402 | const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| { | 7590 | const arg_val = ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| { |
| 7403 | if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err); | 7591 | if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(ics.caller(), ics.caller().err); |
| 7404 | return err; | 7592 | return err; |
| 7405 | }; | 7593 | }; |
| 7406 | switch (arg_val.toIntern()) { | 7594 | switch (arg_val.toIntern()) { |
| ... | @@ -7414,14 +7602,14 @@ fn analyzeInlineCallArg( | ... | @@ -7414,14 +7602,14 @@ fn analyzeInlineCallArg( |
| 7414 | // Needed so that lazy values do not trigger | 7602 | // Needed so that lazy values do not trigger |
| 7415 | // assertion due to type not being resolved | 7603 | // assertion due to type not being resolved |
| 7416 | // when the hash function is called. | 7604 | // when the hash function is called. |
| 7417 | const resolved_arg_val = try sema.resolveLazyValue(arg_val); | 7605 | const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val); |
| 7418 | should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod); | 7606 | should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod); |
| 7419 | memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(param_ty.toType(), mod); | 7607 | memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(param_ty.toType(), mod); |
| 7420 | } else { | 7608 | } else { |
| 7421 | sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); | 7609 | ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg); |
| 7422 | } | 7610 | } |
| 7423 | | 7611 | |
| 7424 | if (try sema.resolveMaybeUndefVal(casted_arg)) |_| { | 7612 | if (try ics.caller().resolveMaybeUndefVal(casted_arg)) |_| { |
| 7425 | has_comptime_args.* = true; | 7613 | has_comptime_args.* = true; |
| 7426 | } | 7614 | } |
| 7427 | | 7615 | |
| ... | @@ -7429,13 +7617,17 @@ fn analyzeInlineCallArg( | ... | @@ -7429,13 +7617,17 @@ fn analyzeInlineCallArg( |
| 7429 | }, | 7617 | }, |
| 7430 | .param_anytype, .param_anytype_comptime => { | 7618 | .param_anytype, .param_anytype_comptime => { |
| 7431 | // No coercion needed. | 7619 | // No coercion needed. |
| 7432 | const uncasted_arg = uncasted_args[arg_i.*]; | 7620 | const uncasted_arg = try args_info.analyzeArg(ics.caller(), arg_block, arg_i.*, Type.generic_poison, func_ty_info, func_inst); |
| 7433 | new_param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern(); | 7621 | if (ics.caller().typeOf(uncasted_arg).zigTypeTag(mod) == .NoReturn) { |
| | 7622 | return uncasted_arg; |
| | 7623 | } |
| | 7624 | const arg_src = args_info.argSrc(arg_block, arg_i.*); |
| | 7625 | new_param_types[arg_i.*] = ics.caller().typeOf(uncasted_arg).toIntern(); |
| 7434 | | 7626 | |
| 7435 | if (is_comptime_call) { | 7627 | if (is_comptime_call) { |
| 7436 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); | 7628 | ics.callee().inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); |
| 7437 | const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| { | 7629 | const arg_val = ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| { |
| 7438 | if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err); | 7630 | if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(ics.caller(), ics.caller().err); |
| 7439 | return err; | 7631 | return err; |
| 7440 | }; | 7632 | }; |
| 7441 | switch (arg_val.toIntern()) { | 7633 | switch (arg_val.toIntern()) { |
| ... | @@ -7449,17 +7641,17 @@ fn analyzeInlineCallArg( | ... | @@ -7449,17 +7641,17 @@ fn analyzeInlineCallArg( |
| 7449 | // Needed so that lazy values do not trigger | 7641 | // Needed so that lazy values do not trigger |
| 7450 | // assertion due to type not being resolved | 7642 | // assertion due to type not being resolved |
| 7451 | // when the hash function is called. | 7643 | // when the hash function is called. |
| 7452 | const resolved_arg_val = try sema.resolveLazyValue(arg_val); | 7644 | const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val); |
| 7453 | should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod); | 7645 | should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod); |
| 7454 | memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(sema.typeOf(uncasted_arg), mod); | 7646 | memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(ics.caller().typeOf(uncasted_arg), mod); |
| 7455 | } else { | 7647 | } else { |
| 7456 | if (zir_tags[inst] == .param_anytype_comptime) { | 7648 | if (zir_tags[inst] == .param_anytype_comptime) { |
| 7457 | _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime"); | 7649 | _ = try ics.caller().resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime"); |
| 7458 | } | 7650 | } |
| 7459 | sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); | 7651 | ics.callee().inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg); |
| 7460 | } | 7652 | } |
| 7461 | | 7653 | |
| 7462 | if (try sema.resolveMaybeUndefVal(uncasted_arg)) |_| { | 7654 | if (try ics.caller().resolveMaybeUndefVal(uncasted_arg)) |_| { |
| 7463 | has_comptime_args.* = true; | 7655 | has_comptime_args.* = true; |
| 7464 | } | 7656 | } |
| 7465 | | 7657 | |
| ... | @@ -7467,6 +7659,8 @@ fn analyzeInlineCallArg( | ... | @@ -7467,6 +7659,8 @@ fn analyzeInlineCallArg( |
| 7467 | }, | 7659 | }, |
| 7468 | else => {}, | 7660 | else => {}, |
| 7469 | } | 7661 | } |
| | 7662 | |
| | 7663 | return null; |
| 7470 | } | 7664 | } |
| 7471 | | 7665 | |
| 7472 | fn analyzeCallArg( | 7666 | fn analyzeCallArg( |
| ... | @@ -7491,9 +7685,8 @@ fn instantiateGenericCall( | ... | @@ -7491,9 +7685,8 @@ fn instantiateGenericCall( |
| 7491 | func_src: LazySrcLoc, | 7685 | func_src: LazySrcLoc, |
| 7492 | call_src: LazySrcLoc, | 7686 | call_src: LazySrcLoc, |
| 7493 | ensure_result_used: bool, | 7687 | ensure_result_used: bool, |
| 7494 | uncasted_args: []const Air.Inst.Ref, | 7688 | args_info: CallArgsInfo, |
| 7495 | call_tag: Air.Inst.Tag, | 7689 | call_tag: Air.Inst.Tag, |
| 7496 | bound_arg_src: ?LazySrcLoc, | | |
| 7497 | call_dbg_node: ?Zir.Inst.Index, | 7690 | call_dbg_node: ?Zir.Inst.Index, |
| 7498 | ) CompileError!Air.Inst.Ref { | 7691 | ) CompileError!Air.Inst.Ref { |
| 7499 | const mod = sema.mod; | 7692 | const mod = sema.mod; |
| ... | @@ -7507,6 +7700,7 @@ fn instantiateGenericCall( | ... | @@ -7507,6 +7700,7 @@ fn instantiateGenericCall( |
| 7507 | else => unreachable, | 7700 | else => unreachable, |
| 7508 | }; | 7701 | }; |
| 7509 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; | 7702 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; |
| | 7703 | const generic_owner_ty_info = mod.typeToFunc(generic_owner_func.ty.toType()).?; |
| 7510 | | 7704 | |
| 7511 | // Even though there may already be a generic instantiation corresponding | 7705 | // Even though there may already be a generic instantiation corresponding |
| 7512 | // to this callsite, we must evaluate the expressions of the generic | 7706 | // to this callsite, we must evaluate the expressions of the generic |
| ... | @@ -7522,9 +7716,13 @@ fn instantiateGenericCall( | ... | @@ -7522,9 +7716,13 @@ fn instantiateGenericCall( |
| 7522 | const fn_zir = namespace.file_scope.zir; | 7716 | const fn_zir = namespace.file_scope.zir; |
| 7523 | const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst); | 7717 | const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst); |
| 7524 | | 7718 | |
| 7525 | const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len); | 7719 | const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count()); |
| 7526 | @memset(comptime_args, .none); | 7720 | @memset(comptime_args, .none); |
| 7527 | | 7721 | |
| | 7722 | // We may overestimate the number of runtime args, but this will definitely be sufficient. |
| | 7723 | const max_runtime_args = args_info.count() - @popCount(generic_owner_ty_info.comptime_bits); |
| | 7724 | var runtime_args = try std.ArrayListUnmanaged(Air.Inst.Ref).initCapacity(sema.arena, max_runtime_args); |
| | 7725 | |
| 7528 | // Re-run the block that creates the function, with the comptime parameters | 7726 | // Re-run the block that creates the function, with the comptime parameters |
| 7529 | // pre-populated inside `inst_map`. This causes `param_comptime` and | 7727 | // pre-populated inside `inst_map`. This causes `param_comptime` and |
| 7530 | // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a | 7728 | // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a |
| ... | @@ -7549,7 +7747,6 @@ fn instantiateGenericCall( | ... | @@ -7549,7 +7747,6 @@ fn instantiateGenericCall( |
| 7549 | .comptime_args = comptime_args, | 7747 | .comptime_args = comptime_args, |
| 7550 | .generic_owner = generic_owner, | 7748 | .generic_owner = generic_owner, |
| 7551 | .generic_call_src = call_src, | 7749 | .generic_call_src = call_src, |
| 7552 | .generic_bound_arg_src = bound_arg_src, | | |
| 7553 | .generic_call_decl = block.src_decl.toOptional(), | 7750 | .generic_call_decl = block.src_decl.toOptional(), |
| 7554 | .branch_quota = sema.branch_quota, | 7751 | .branch_quota = sema.branch_quota, |
| 7555 | .branch_count = sema.branch_count, | 7752 | .branch_count = sema.branch_count, |
| ... | @@ -7574,30 +7771,145 @@ fn instantiateGenericCall( | ... | @@ -7574,30 +7771,145 @@ fn instantiateGenericCall( |
| 7574 | | 7771 | |
| 7575 | try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); | 7772 | try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); |
| 7576 | | 7773 | |
| 7577 | for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| { | 7774 | for (fn_info.param_body[0..args_info.count()], 0..) |param_inst, arg_index| { |
| 7578 | // `child_sema` will use a different `inst_map` which means we have to | 7775 | const param_tag = fn_zir.instructions.items(.tag)[param_inst]; |
| 7579 | // convert from parent-relative `Air.Inst.Ref` to child-relative here. | 7776 | |
| 7580 | // Constants are simple; runtime-known values need a new instruction. | 7777 | const param_ty = switch (generic_owner_ty_info.param_types.get(ip)[arg_index]) { |
| 7581 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, if (try sema.resolveMaybeUndefVal(arg)) |val| | 7778 | else => |ty| ty.toType(), // parameter is not generic, so type is already resolved |
| 7582 | Air.internedToRef(val.toIntern()) | 7779 | .generic_poison_type => param_ty: { |
| 7583 | else | 7780 | // We have every parameter before this one, so can resolve this parameter's type now. |
| 7584 | // We insert into the map an instruction which is runtime-known | 7781 | // However, first check the param type, since it may be anytype. |
| 7585 | // but has the type of the argument. | 7782 | switch (param_tag) { |
| 7586 | try child_block.addInst(.{ | 7783 | .param_anytype, .param_anytype_comptime => { |
| | 7784 | // The parameter doesn't have a type. |
| | 7785 | break :param_ty Type.generic_poison; |
| | 7786 | }, |
| | 7787 | .param, .param_comptime => { |
| | 7788 | // We now know every prior parameter, so can resolve this |
| | 7789 | // parameter's type. The child sema has these types. |
| | 7790 | const param_data = fn_zir.instructions.items(.data)[param_inst].pl_tok; |
| | 7791 | const param_extra = fn_zir.extraData(Zir.Inst.Param, param_data.payload_index); |
| | 7792 | const param_ty_body = fn_zir.extra[param_extra.end..][0..param_extra.data.body_len]; |
| | 7793 | |
| | 7794 | // Make sure any nested instructions don't clobber our work. |
| | 7795 | const prev_params = child_block.params; |
| | 7796 | const prev_no_partial_func_ty = child_sema.no_partial_func_ty; |
| | 7797 | const prev_generic_owner = child_sema.generic_owner; |
| | 7798 | const prev_generic_call_src = child_sema.generic_call_src; |
| | 7799 | const prev_generic_call_decl = child_sema.generic_call_decl; |
| | 7800 | child_block.params = .{}; |
| | 7801 | child_sema.no_partial_func_ty = true; |
| | 7802 | child_sema.generic_owner = .none; |
| | 7803 | child_sema.generic_call_src = .unneeded; |
| | 7804 | child_sema.generic_call_decl = .none; |
| | 7805 | defer { |
| | 7806 | child_block.params = prev_params; |
| | 7807 | child_sema.no_partial_func_ty = prev_no_partial_func_ty; |
| | 7808 | child_sema.generic_owner = prev_generic_owner; |
| | 7809 | child_sema.generic_call_src = prev_generic_call_src; |
| | 7810 | child_sema.generic_call_decl = prev_generic_call_decl; |
| | 7811 | } |
| | 7812 | |
| | 7813 | const param_ty_inst = try child_sema.resolveBody(&child_block, param_ty_body, param_inst); |
| | 7814 | break :param_ty try child_sema.analyzeAsType(&child_block, param_data.src(), param_ty_inst); |
| | 7815 | }, |
| | 7816 | else => unreachable, |
| | 7817 | } |
| | 7818 | }, |
| | 7819 | }; |
| | 7820 | const arg_ref = try args_info.analyzeArg(sema, block, arg_index, param_ty, generic_owner_ty_info, func); |
| | 7821 | const arg_ty = sema.typeOf(arg_ref); |
| | 7822 | if (arg_ty.zigTypeTag(mod) == .NoReturn) { |
| | 7823 | // This terminates argument analysis. |
| | 7824 | return arg_ref; |
| | 7825 | } |
| | 7826 | |
| | 7827 | const arg_is_comptime = switch (param_tag) { |
| | 7828 | .param_comptime, .param_anytype_comptime => true, |
| | 7829 | .param, .param_anytype => try sema.typeRequiresComptime(arg_ty), |
| | 7830 | else => unreachable, |
| | 7831 | }; |
| | 7832 | |
| | 7833 | if (arg_is_comptime) { |
| | 7834 | if (try sema.resolveMaybeUndefVal(arg_ref)) |arg_val| { |
| | 7835 | comptime_args[arg_index] = arg_val.toIntern(); |
| | 7836 | child_sema.inst_map.putAssumeCapacityNoClobber( |
| | 7837 | param_inst, |
| | 7838 | Air.internedToRef(arg_val.toIntern()), |
| | 7839 | ); |
| | 7840 | } else switch (param_tag) { |
| | 7841 | .param_comptime, |
| | 7842 | .param_anytype_comptime, |
| | 7843 | => return sema.failWithOwnedErrorMsg(msg: { |
| | 7844 | const arg_src = args_info.argSrc(block, arg_index); |
| | 7845 | const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to comptime parameter", .{}); |
| | 7846 | errdefer msg.destroy(sema.gpa); |
| | 7847 | const param_src = switch (param_tag) { |
| | 7848 | .param_comptime => fn_zir.instructions.items(.data)[param_inst].pl_tok.src(), |
| | 7849 | .param_anytype_comptime => fn_zir.instructions.items(.data)[param_inst].str_tok.src(), |
| | 7850 | else => unreachable, |
| | 7851 | }; |
| | 7852 | try child_sema.errNote(&child_block, param_src, msg, "declared comptime here", .{}); |
| | 7853 | break :msg msg; |
| | 7854 | }), |
| | 7855 | |
| | 7856 | .param, |
| | 7857 | .param_anytype, |
| | 7858 | => return sema.failWithOwnedErrorMsg(msg: { |
| | 7859 | const arg_src = args_info.argSrc(block, arg_index); |
| | 7860 | const msg = try sema.errMsg(block, arg_src, "runtime-known argument passed to parameter of comptime-only type", .{}); |
| | 7861 | errdefer msg.destroy(sema.gpa); |
| | 7862 | const param_src = switch (param_tag) { |
| | 7863 | .param => fn_zir.instructions.items(.data)[param_inst].pl_tok.src(), |
| | 7864 | .param_anytype => fn_zir.instructions.items(.data)[param_inst].str_tok.src(), |
| | 7865 | else => unreachable, |
| | 7866 | }; |
| | 7867 | try child_sema.errNote(&child_block, param_src, msg, "declared here", .{}); |
| | 7868 | const src_decl = mod.declPtr(block.src_decl); |
| | 7869 | try sema.explainWhyTypeIsComptime(msg, arg_src.toSrcLoc(src_decl, mod), arg_ty); |
| | 7870 | break :msg msg; |
| | 7871 | }), |
| | 7872 | |
| | 7873 | else => unreachable, |
| | 7874 | } |
| | 7875 | } else { |
| | 7876 | // The parameter is runtime-known. |
| | 7877 | try sema.queueFullTypeResolution(arg_ty); |
| | 7878 | child_sema.inst_map.putAssumeCapacityNoClobber(param_inst, try child_block.addInst(.{ |
| 7587 | .tag = .arg, | 7879 | .tag = .arg, |
| 7588 | .data = .{ .arg = .{ | 7880 | .data = .{ .arg = .{ |
| 7589 | .ty = Air.internedToRef(sema.typeOf(arg).toIntern()), | 7881 | .ty = Air.internedToRef(arg_ty.toIntern()), |
| 7590 | .src_index = @intCast(i), | 7882 | .src_index = @intCast(arg_index), |
| 7591 | } }, | 7883 | } }, |
| 7592 | })); | 7884 | })); |
| | 7885 | const param_name: Zir.NullTerminatedString = switch (param_tag) { |
| | 7886 | .param_anytype => @enumFromInt(fn_zir.instructions.items(.data)[param_inst].str_tok.start), |
| | 7887 | .param => name: { |
| | 7888 | const inst_data = fn_zir.instructions.items(.data)[param_inst].pl_tok; |
| | 7889 | const extra = fn_zir.extraData(Zir.Inst.Param, inst_data.payload_index); |
| | 7890 | break :name @enumFromInt(extra.data.name); |
| | 7891 | }, |
| | 7892 | else => unreachable, |
| | 7893 | }; |
| | 7894 | try child_block.params.append(sema.arena, .{ |
| | 7895 | .ty = arg_ty.toIntern(), // This is the type after coercion |
| | 7896 | .is_comptime = false, // We're adding only runtime args to the instantiation |
| | 7897 | .name = param_name, |
| | 7898 | }); |
| | 7899 | runtime_args.appendAssumeCapacity(arg_ref); |
| | 7900 | } |
| 7593 | } | 7901 | } |
| 7594 | | 7902 | |
| 7595 | const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst); | 7903 | // We've already handled parameters, so don't resolve the whole body. Instead, just |
| | 7904 | // do the instructions after the params (i.e. the func itself). |
| | 7905 | const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body[args_info.count()..], fn_info.param_body_inst); |
| 7596 | const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern(); | 7906 | const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern(); |
| 7597 | | 7907 | |
| 7598 | const callee = mod.funcInfo(callee_index); | 7908 | const callee = mod.funcInfo(callee_index); |
| 7599 | callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota); | 7909 | callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota); |
| 7600 | | 7910 | |
| | 7911 | try sema.addReferencedBy(block, call_src, callee.owner_decl); |
| | 7912 | |
| 7601 | // Make a runtime call to the new function, making sure to omit the comptime args. | 7913 | // Make a runtime call to the new function, making sure to omit the comptime args. |
| 7602 | const func_ty = callee.ty.toType(); | 7914 | const func_ty = callee.ty.toType(); |
| 7603 | const func_ty_info = mod.typeToFunc(func_ty).?; | 7915 | const func_ty_info = mod.typeToFunc(func_ty).?; |
| ... | @@ -7615,33 +7927,7 @@ fn instantiateGenericCall( | ... | @@ -7615,33 +7927,7 @@ fn instantiateGenericCall( |
| 7615 | return error.GenericPoison; | 7927 | return error.GenericPoison; |
| 7616 | } | 7928 | } |
| 7617 | | 7929 | |
| 7618 | const runtime_args_len: u32 = func_ty_info.param_types.len; | 7930 | try sema.queueFullTypeResolution(func_ty_info.return_type.toType()); |
| 7619 | const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len); | | |
| 7620 | { | | |
| 7621 | var runtime_i: u32 = 0; | | |
| 7622 | for (uncasted_args, 0..) |uncasted_arg, total_i| { | | |
| 7623 | // In the case of a function call generated by the language, the LazySrcLoc | | |
| 7624 | // provided for `call_src` may not point to anything interesting. | | |
| 7625 | const arg_src: LazySrcLoc = if (total_i == 0 and bound_arg_src != null) | | |
| 7626 | bound_arg_src.? | | |
| 7627 | else if (call_src == .node_offset) .{ .call_arg = .{ | | |
| 7628 | .decl = block.src_decl, | | |
| 7629 | .call_node_offset = call_src.node_offset.x, | | |
| 7630 | .arg_index = @intCast(total_i - @intFromBool(bound_arg_src != null)), | | |
| 7631 | } } else .unneeded; | | |
| 7632 | | | |
| 7633 | const comptime_arg = callee.comptime_args.get(ip)[total_i]; | | |
| 7634 | if (comptime_arg == .none) { | | |
| 7635 | const param_ty = func_ty_info.param_types.get(ip)[runtime_i].toType(); | | |
| 7636 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); | | |
| 7637 | try sema.queueFullTypeResolution(param_ty); | | |
| 7638 | runtime_args[runtime_i] = casted_arg; | | |
| 7639 | runtime_i += 1; | | |
| 7640 | } | | |
| 7641 | } | | |
| 7642 | | | |
| 7643 | try sema.queueFullTypeResolution(func_ty_info.return_type.toType()); | | |
| 7644 | } | | |
| 7645 | | 7931 | |
| 7646 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | 7932 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 7647 | | 7933 | |
| ... | @@ -7653,18 +7939,17 @@ fn instantiateGenericCall( | ... | @@ -7653,18 +7939,17 @@ fn instantiateGenericCall( |
| 7653 | | 7939 | |
| 7654 | try mod.ensureFuncBodyAnalysisQueued(callee_index); | 7940 | try mod.ensureFuncBodyAnalysisQueued(callee_index); |
| 7655 | | 7941 | |
| 7656 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + | 7942 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + runtime_args.items.len); |
| 7657 | runtime_args_len); | | |
| 7658 | const result = try block.addInst(.{ | 7943 | const result = try block.addInst(.{ |
| 7659 | .tag = call_tag, | 7944 | .tag = call_tag, |
| 7660 | .data = .{ .pl_op = .{ | 7945 | .data = .{ .pl_op = .{ |
| 7661 | .operand = Air.internedToRef(callee_index), | 7946 | .operand = Air.internedToRef(callee_index), |
| 7662 | .payload = sema.addExtraAssumeCapacity(Air.Call{ | 7947 | .payload = sema.addExtraAssumeCapacity(Air.Call{ |
| 7663 | .args_len = runtime_args_len, | 7948 | .args_len = @intCast(runtime_args.items.len), |
| 7664 | }), | 7949 | }), |
| 7665 | } }, | 7950 | } }, |
| 7666 | }); | 7951 | }); |
| 7667 | sema.appendRefsAssumeCapacity(runtime_args); | 7952 | sema.appendRefsAssumeCapacity(runtime_args.items); |
| 7668 | | 7953 | |
| 7669 | if (ensure_result_used) { | 7954 | if (ensure_result_used) { |
| 7670 | try sema.ensureResultUsed(block, sema.typeOf(result), call_src); | 7955 | try sema.ensureResultUsed(block, sema.typeOf(result), call_src); |
| ... | @@ -7744,7 +8029,15 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -7744,7 +8029,15 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 7744 | fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 8029 | fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 7745 | const mod = sema.mod; | 8030 | const mod = sema.mod; |
| 7746 | const bin = sema.code.instructions.items(.data)[inst].bin; | 8031 | const bin = sema.code.instructions.items(.data)[inst].bin; |
| 7747 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); | 8032 | const operand = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) { |
| | 8033 | // Since this is a ZIR instruction that returns a type, encountering |
| | 8034 | // generic poison should not result in a failed compilation, but the |
| | 8035 | // generic poison type. This prevents unnecessary failures when |
| | 8036 | // constructing types at compile-time. |
| | 8037 | error.GenericPoison => return .generic_poison_type, |
| | 8038 | else => |e| return e, |
| | 8039 | }; |
| | 8040 | const indexable_ty = try sema.resolveTypeFields(operand); |
| 7748 | assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction | 8041 | assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction |
| 7749 | if (indexable_ty.zigTypeTag(mod) == .Struct) { | 8042 | if (indexable_ty.zigTypeTag(mod) == .Struct) { |
| 7750 | const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod); | 8043 | const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod); |
| ... | @@ -7763,6 +8056,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -7763,6 +8056,23 @@ fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 7763 | return sema.addType(ptr_ty.childType(mod)); | 8056 | return sema.addType(ptr_ty.childType(mod)); |
| 7764 | } | 8057 | } |
| 7765 | | 8058 | |
| | 8059 | fn zirVectorElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| | 8060 | const mod = sema.mod; |
| | 8061 | const un_node = sema.code.instructions.items(.data)[inst].un_node; |
| | 8062 | const vec_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) { |
| | 8063 | // Since this is a ZIR instruction that returns a type, encountering |
| | 8064 | // generic poison should not result in a failed compilation, but the |
| | 8065 | // generic poison type. This prevents unnecessary failures when |
| | 8066 | // constructing types at compile-time. |
| | 8067 | error.GenericPoison => return .generic_poison_type, |
| | 8068 | else => |e| return e, |
| | 8069 | }; |
| | 8070 | if (!vec_ty.isVector(mod)) { |
| | 8071 | return sema.fail(block, un_node.src(), "expected vector type, found '{}'", .{vec_ty.fmt(mod)}); |
| | 8072 | } |
| | 8073 | return sema.addType(vec_ty.childType(mod)); |
| | 8074 | } |
| | 8075 | |
| 7766 | fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 8076 | fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 7767 | const mod = sema.mod; | 8077 | const mod = sema.mod; |
| 7768 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 8078 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| ... | @@ -8588,20 +8898,17 @@ fn resolveGenericBody( | ... | @@ -8588,20 +8898,17 @@ fn resolveGenericBody( |
| 8588 | const prev_no_partial_func_type = sema.no_partial_func_ty; | 8898 | const prev_no_partial_func_type = sema.no_partial_func_ty; |
| 8589 | const prev_generic_owner = sema.generic_owner; | 8899 | const prev_generic_owner = sema.generic_owner; |
| 8590 | const prev_generic_call_src = sema.generic_call_src; | 8900 | const prev_generic_call_src = sema.generic_call_src; |
| 8591 | const prev_generic_bound_arg_src = sema.generic_bound_arg_src; | | |
| 8592 | const prev_generic_call_decl = sema.generic_call_decl; | 8901 | const prev_generic_call_decl = sema.generic_call_decl; |
| 8593 | block.params = .{}; | 8902 | block.params = .{}; |
| 8594 | sema.no_partial_func_ty = true; | 8903 | sema.no_partial_func_ty = true; |
| 8595 | sema.generic_owner = .none; | 8904 | sema.generic_owner = .none; |
| 8596 | sema.generic_call_src = .unneeded; | 8905 | sema.generic_call_src = .unneeded; |
| 8597 | sema.generic_bound_arg_src = null; | | |
| 8598 | sema.generic_call_decl = .none; | 8906 | sema.generic_call_decl = .none; |
| 8599 | defer { | 8907 | defer { |
| 8600 | block.params = prev_params; | 8908 | block.params = prev_params; |
| 8601 | sema.no_partial_func_ty = prev_no_partial_func_type; | 8909 | sema.no_partial_func_ty = prev_no_partial_func_type; |
| 8602 | sema.generic_owner = prev_generic_owner; | 8910 | sema.generic_owner = prev_generic_owner; |
| 8603 | sema.generic_call_src = prev_generic_call_src; | 8911 | sema.generic_call_src = prev_generic_call_src; |
| 8604 | sema.generic_bound_arg_src = prev_generic_bound_arg_src; | | |
| 8605 | sema.generic_call_decl = prev_generic_call_decl; | 8912 | sema.generic_call_decl = prev_generic_call_decl; |
| 8606 | } | 8913 | } |
| 8607 | | 8914 | |
| ... | @@ -9219,37 +9526,18 @@ fn finishFunc( | ... | @@ -9219,37 +9526,18 @@ fn finishFunc( |
| 9219 | return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty); | 9526 | return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty); |
| 9220 | } | 9527 | } |
| 9221 | | 9528 | |
| 9222 | fn genericArgSrcLoc(sema: *Sema, block: *Block, param_index: u32, param_src: LazySrcLoc) Module.SrcLoc { | | |
| 9223 | const mod = sema.mod; | | |
| 9224 | if (sema.generic_owner == .none) return param_src.toSrcLoc(mod.declPtr(block.src_decl), mod); | | |
| 9225 | const arg_decl = sema.generic_call_decl.unwrap().?; | | |
| 9226 | const arg_src: LazySrcLoc = if (param_index == 0 and sema.generic_bound_arg_src != null) | | |
| 9227 | sema.generic_bound_arg_src.? | | |
| 9228 | else | | |
| 9229 | .{ .call_arg = .{ | | |
| 9230 | .decl = arg_decl, | | |
| 9231 | .call_node_offset = sema.generic_call_src.node_offset.x, | | |
| 9232 | .arg_index = param_index - @intFromBool(sema.generic_bound_arg_src != null), | | |
| 9233 | } }; | | |
| 9234 | return arg_src.toSrcLoc(mod.declPtr(arg_decl), mod); | | |
| 9235 | } | | |
| 9236 | | | |
| 9237 | fn zirParam( | 9529 | fn zirParam( |
| 9238 | sema: *Sema, | 9530 | sema: *Sema, |
| 9239 | block: *Block, | 9531 | block: *Block, |
| 9240 | inst: Zir.Inst.Index, | 9532 | inst: Zir.Inst.Index, |
| 9241 | param_index: u32, | | |
| 9242 | comptime_syntax: bool, | 9533 | comptime_syntax: bool, |
| 9243 | ) CompileError!void { | 9534 | ) CompileError!void { |
| 9244 | const gpa = sema.gpa; | | |
| 9245 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; | 9535 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; |
| 9246 | const src = inst_data.src(); | 9536 | const src = inst_data.src(); |
| 9247 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); | 9537 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); |
| 9248 | const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name); | 9538 | const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name); |
| 9249 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 9539 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 9250 | | 9540 | |
| 9251 | // We could be in a generic function instantiation, or we could be evaluating a generic | | |
| 9252 | // function without any comptime args provided. | | |
| 9253 | const param_ty = param_ty: { | 9541 | const param_ty = param_ty: { |
| 9254 | const err = err: { | 9542 | const err = err: { |
| 9255 | // Make sure any nested param instructions don't clobber our work. | 9543 | // Make sure any nested param instructions don't clobber our work. |
| ... | @@ -9257,20 +9545,17 @@ fn zirParam( | ... | @@ -9257,20 +9545,17 @@ fn zirParam( |
| 9257 | const prev_no_partial_func_type = sema.no_partial_func_ty; | 9545 | const prev_no_partial_func_type = sema.no_partial_func_ty; |
| 9258 | const prev_generic_owner = sema.generic_owner; | 9546 | const prev_generic_owner = sema.generic_owner; |
| 9259 | const prev_generic_call_src = sema.generic_call_src; | 9547 | const prev_generic_call_src = sema.generic_call_src; |
| 9260 | const prev_generic_bound_arg_src = sema.generic_bound_arg_src; | | |
| 9261 | const prev_generic_call_decl = sema.generic_call_decl; | 9548 | const prev_generic_call_decl = sema.generic_call_decl; |
| 9262 | block.params = .{}; | 9549 | block.params = .{}; |
| 9263 | sema.no_partial_func_ty = true; | 9550 | sema.no_partial_func_ty = true; |
| 9264 | sema.generic_owner = .none; | 9551 | sema.generic_owner = .none; |
| 9265 | sema.generic_call_src = .unneeded; | 9552 | sema.generic_call_src = .unneeded; |
| 9266 | sema.generic_bound_arg_src = null; | | |
| 9267 | sema.generic_call_decl = .none; | 9553 | sema.generic_call_decl = .none; |
| 9268 | defer { | 9554 | defer { |
| 9269 | block.params = prev_params; | 9555 | block.params = prev_params; |
| 9270 | sema.no_partial_func_ty = prev_no_partial_func_type; | 9556 | sema.no_partial_func_ty = prev_no_partial_func_type; |
| 9271 | sema.generic_owner = prev_generic_owner; | 9557 | sema.generic_owner = prev_generic_owner; |
| 9272 | sema.generic_call_src = prev_generic_call_src; | 9558 | sema.generic_call_src = prev_generic_call_src; |
| 9273 | sema.generic_bound_arg_src = prev_generic_bound_arg_src; | | |
| 9274 | sema.generic_call_decl = prev_generic_call_decl; | 9559 | sema.generic_call_decl = prev_generic_call_decl; |
| 9275 | } | 9560 | } |
| 9276 | | 9561 | |
| ... | @@ -9282,11 +9567,6 @@ fn zirParam( | ... | @@ -9282,11 +9567,6 @@ fn zirParam( |
| 9282 | }; | 9567 | }; |
| 9283 | switch (err) { | 9568 | switch (err) { |
| 9284 | error.GenericPoison => { | 9569 | error.GenericPoison => { |
| 9285 | if (sema.inst_map.contains(inst)) { | | |
| 9286 | // A generic function is about to evaluate to another generic function. | | |
| 9287 | // Return an error instead. | | |
| 9288 | return error.GenericPoison; | | |
| 9289 | } | | |
| 9290 | // The type is not available until the generic instantiation. | 9570 | // The type is not available until the generic instantiation. |
| 9291 | // We result the param instruction with a poison value and | 9571 | // We result the param instruction with a poison value and |
| 9292 | // insert an anytype parameter. | 9572 | // insert an anytype parameter. |
| ... | @@ -9304,11 +9584,6 @@ fn zirParam( | ... | @@ -9304,11 +9584,6 @@ fn zirParam( |
| 9304 | | 9584 | |
| 9305 | const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) { | 9585 | const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) { |
| 9306 | error.GenericPoison => { | 9586 | error.GenericPoison => { |
| 9307 | if (sema.inst_map.contains(inst)) { | | |
| 9308 | // A generic function is about to evaluate to another generic function. | | |
| 9309 | // Return an error instead. | | |
| 9310 | return error.GenericPoison; | | |
| 9311 | } | | |
| 9312 | // The type is not available until the generic instantiation. | 9587 | // The type is not available until the generic instantiation. |
| 9313 | // We result the param instruction with a poison value and | 9588 | // We result the param instruction with a poison value and |
| 9314 | // insert an anytype parameter. | 9589 | // insert an anytype parameter. |
| ... | @@ -9323,46 +9598,6 @@ fn zirParam( | ... | @@ -9323,46 +9598,6 @@ fn zirParam( |
| 9323 | else => |e| return e, | 9598 | else => |e| return e, |
| 9324 | } or comptime_syntax; | 9599 | } or comptime_syntax; |
| 9325 | | 9600 | |
| 9326 | if (sema.inst_map.get(inst)) |arg| { | | |
| 9327 | if (is_comptime and sema.generic_owner != .none) { | | |
| 9328 | // We have a comptime value for this parameter so it should be elided from the | | |
| 9329 | // function type of the function instruction in this block. | | |
| 9330 | const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) { | | |
| 9331 | error.NeededSourceLocation => { | | |
| 9332 | // We are instantiating a generic function and a comptime arg | | |
| 9333 | // cannot be coerced to the param type, but since we don't | | |
| 9334 | // have the callee source location return `GenericPoison` | | |
| 9335 | // so that the instantiation is failed and the coercion | | |
| 9336 | // is handled by comptime call logic instead. | | |
| 9337 | assert(sema.generic_owner != .none); | | |
| 9338 | return error.GenericPoison; | | |
| 9339 | }, | | |
| 9340 | else => |e| return e, | | |
| 9341 | }; | | |
| 9342 | sema.inst_map.putAssumeCapacity(inst, coerced_arg); | | |
| 9343 | if (try sema.resolveMaybeUndefVal(coerced_arg)) |val| { | | |
| 9344 | sema.comptime_args[param_index] = val.toIntern(); | | |
| 9345 | return; | | |
| 9346 | } | | |
| 9347 | const msg = msg: { | | |
| 9348 | const src_loc = sema.genericArgSrcLoc(block, param_index, src); | | |
| 9349 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ | | |
| 9350 | @as([]const u8, "runtime-known argument passed to comptime parameter"), | | |
| 9351 | }); | | |
| 9352 | errdefer msg.destroy(gpa); | | |
| 9353 | | | |
| 9354 | if (sema.generic_call_decl != .none) { | | |
| 9355 | try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")}); | | |
| 9356 | } | | |
| 9357 | break :msg msg; | | |
| 9358 | }; | | |
| 9359 | return sema.failWithOwnedErrorMsg(msg); | | |
| 9360 | } | | |
| 9361 | // Even though a comptime argument is provided, the generic function wants to treat | | |
| 9362 | // this as a runtime parameter. | | |
| 9363 | assert(sema.inst_map.remove(inst)); | | |
| 9364 | } | | |
| 9365 | | | |
| 9366 | try block.params.append(sema.arena, .{ | 9601 | try block.params.append(sema.arena, .{ |
| 9367 | .ty = param_ty.toIntern(), | 9602 | .ty = param_ty.toIntern(), |
| 9368 | .is_comptime = comptime_syntax, | 9603 | .is_comptime = comptime_syntax, |
| ... | @@ -9388,75 +9623,10 @@ fn zirParamAnytype( | ... | @@ -9388,75 +9623,10 @@ fn zirParamAnytype( |
| 9388 | sema: *Sema, | 9623 | sema: *Sema, |
| 9389 | block: *Block, | 9624 | block: *Block, |
| 9390 | inst: Zir.Inst.Index, | 9625 | inst: Zir.Inst.Index, |
| 9391 | param_index: u32, | | |
| 9392 | comptime_syntax: bool, | 9626 | comptime_syntax: bool, |
| 9393 | ) CompileError!void { | 9627 | ) CompileError!void { |
| 9394 | const gpa = sema.gpa; | | |
| 9395 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; | 9628 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| 9396 | const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start); | 9629 | const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start); |
| 9397 | const src = inst_data.src(); | | |
| 9398 | | | |
| 9399 | if (sema.inst_map.get(inst)) |air_ref| { | | |
| 9400 | const param_ty = sema.typeOf(air_ref); | | |
| 9401 | // If we have a comptime value for this parameter, it should be elided | | |
| 9402 | // from the function type of the function instruction in this block. | | |
| 9403 | if (try sema.typeHasOnePossibleValue(param_ty)) |opv| { | | |
| 9404 | sema.comptime_args[param_index] = opv.toIntern(); | | |
| 9405 | return; | | |
| 9406 | } | | |
| 9407 | | | |
| 9408 | if (comptime_syntax) { | | |
| 9409 | if (try sema.resolveMaybeUndefVal(air_ref)) |val| { | | |
| 9410 | sema.comptime_args[param_index] = val.toIntern(); | | |
| 9411 | return; | | |
| 9412 | } | | |
| 9413 | const msg = msg: { | | |
| 9414 | const src_loc = sema.genericArgSrcLoc(block, param_index, src); | | |
| 9415 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ | | |
| 9416 | @as([]const u8, "runtime-known argument passed to comptime parameter"), | | |
| 9417 | }); | | |
| 9418 | errdefer msg.destroy(gpa); | | |
| 9419 | | | |
| 9420 | if (sema.generic_call_decl != .none) { | | |
| 9421 | try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")}); | | |
| 9422 | } | | |
| 9423 | break :msg msg; | | |
| 9424 | }; | | |
| 9425 | return sema.failWithOwnedErrorMsg(msg); | | |
| 9426 | } | | |
| 9427 | | | |
| 9428 | if (try sema.typeRequiresComptime(param_ty)) { | | |
| 9429 | if (try sema.resolveMaybeUndefVal(air_ref)) |val| { | | |
| 9430 | sema.comptime_args[param_index] = val.toIntern(); | | |
| 9431 | return; | | |
| 9432 | } | | |
| 9433 | const msg = msg: { | | |
| 9434 | const src_loc = sema.genericArgSrcLoc(block, param_index, src); | | |
| 9435 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ | | |
| 9436 | @as([]const u8, "runtime-known argument passed to comptime-only type parameter"), | | |
| 9437 | }); | | |
| 9438 | errdefer msg.destroy(gpa); | | |
| 9439 | | | |
| 9440 | if (sema.generic_call_decl != .none) { | | |
| 9441 | try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared here")}); | | |
| 9442 | } | | |
| 9443 | | | |
| 9444 | try sema.explainWhyTypeIsComptime(msg, src_loc, param_ty); | | |
| 9445 | | | |
| 9446 | break :msg msg; | | |
| 9447 | }; | | |
| 9448 | return sema.failWithOwnedErrorMsg(msg); | | |
| 9449 | } | | |
| 9450 | | | |
| 9451 | // The parameter is runtime-known. | | |
| 9452 | // The map is already populated but we do need to add a runtime parameter. | | |
| 9453 | try block.params.append(sema.arena, .{ | | |
| 9454 | .ty = param_ty.toIntern(), | | |
| 9455 | .is_comptime = false, | | |
| 9456 | .name = param_name, | | |
| 9457 | }); | | |
| 9458 | return; | | |
| 9459 | } | | |
| 9460 | | 9630 | |
| 9461 | // We are evaluating a generic function without any comptime args provided. | 9631 | // We are evaluating a generic function without any comptime args provided. |
| 9462 | | 9632 | |
| ... | @@ -18794,7 +18964,13 @@ fn zirStructInit( | ... | @@ -18794,7 +18964,13 @@ fn zirStructInit( |
| 18794 | const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; | 18964 | const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; |
| 18795 | const first_field_type_data = zir_datas[first_item.field_type].pl_node; | 18965 | const first_field_type_data = zir_datas[first_item.field_type].pl_node; |
| 18796 | const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data; | 18966 | const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data; |
| 18797 | const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type); | 18967 | const resolved_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) { |
| | 18968 | error.GenericPoison => { |
| | 18969 | // The type wasn't actually known, so treat this as an anon struct init. |
| | 18970 | return sema.structInitAnon(block, src, .typed_init, extra.data, extra.end, is_ref); |
| | 18971 | }, |
| | 18972 | else => |e| return e, |
| | 18973 | }; |
| 18798 | try sema.resolveTypeLayout(resolved_ty); | 18974 | try sema.resolveTypeLayout(resolved_ty); |
| 18799 | | 18975 | |
| 18800 | if (resolved_ty.zigTypeTag(mod) == .Struct) { | 18976 | if (resolved_ty.zigTypeTag(mod) == .Struct) { |
| ... | @@ -19037,26 +19213,57 @@ fn zirStructInitAnon( | ... | @@ -19037,26 +19213,57 @@ fn zirStructInitAnon( |
| 19037 | inst: Zir.Inst.Index, | 19213 | inst: Zir.Inst.Index, |
| 19038 | is_ref: bool, | 19214 | is_ref: bool, |
| 19039 | ) CompileError!Air.Inst.Ref { | 19215 | ) CompileError!Air.Inst.Ref { |
| 19040 | const mod = sema.mod; | | |
| 19041 | const gpa = sema.gpa; | | |
| 19042 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 19216 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 19043 | const src = inst_data.src(); | 19217 | const src = inst_data.src(); |
| 19044 | const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); | 19218 | const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); |
| 19045 | const types = try sema.arena.alloc(InternPool.Index, extra.data.fields_len); | 19219 | return sema.structInitAnon(block, src, .anon_init, extra.data, extra.end, is_ref); |
| | 19220 | } |
| | 19221 | |
| | 19222 | fn structInitAnon( |
| | 19223 | sema: *Sema, |
| | 19224 | block: *Block, |
| | 19225 | src: LazySrcLoc, |
| | 19226 | /// It is possible for a typed struct_init to be downgraded to an anonymous init due to a |
| | 19227 | /// generic poison type. In this case, we need to know to interpret the extra data differently. |
| | 19228 | comptime kind: enum { anon_init, typed_init }, |
| | 19229 | extra_data: switch (kind) { |
| | 19230 | .anon_init => Zir.Inst.StructInitAnon, |
| | 19231 | .typed_init => Zir.Inst.StructInit, |
| | 19232 | }, |
| | 19233 | extra_end: usize, |
| | 19234 | is_ref: bool, |
| | 19235 | ) CompileError!Air.Inst.Ref { |
| | 19236 | const mod = sema.mod; |
| | 19237 | const gpa = sema.gpa; |
| | 19238 | const zir_datas = sema.code.instructions.items(.data); |
| | 19239 | |
| | 19240 | const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len); |
| 19046 | const values = try sema.arena.alloc(InternPool.Index, types.len); | 19241 | const values = try sema.arena.alloc(InternPool.Index, types.len); |
| | 19242 | |
| 19047 | var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena); | 19243 | var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena); |
| 19048 | try fields.ensureUnusedCapacity(types.len); | 19244 | try fields.ensureUnusedCapacity(types.len); |
| 19049 | | 19245 | |
| 19050 | // Find which field forces the expression to be runtime, if any. | 19246 | // Find which field forces the expression to be runtime, if any. |
| 19051 | const opt_runtime_index = rs: { | 19247 | const opt_runtime_index = rs: { |
| 19052 | var runtime_index: ?usize = null; | 19248 | var runtime_index: ?usize = null; |
| 19053 | var extra_index = extra.end; | 19249 | var extra_index = extra_end; |
| 19054 | for (types, 0..) |*field_ty, i_usize| { | 19250 | for (types, 0..) |*field_ty, i_usize| { |
| 19055 | const i = @as(u32, @intCast(i_usize)); | 19251 | const i: u32 = @intCast(i_usize); |
| 19056 | const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index); | 19252 | const item = switch (kind) { |
| | 19253 | .anon_init => sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index), |
| | 19254 | .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index), |
| | 19255 | }; |
| 19057 | extra_index = item.end; | 19256 | extra_index = item.end; |
| 19058 | | 19257 | |
| 19059 | const name = sema.code.nullTerminatedString(item.data.field_name); | 19258 | const name = switch (kind) { |
| | 19259 | .anon_init => sema.code.nullTerminatedString(item.data.field_name), |
| | 19260 | .typed_init => name: { |
| | 19261 | // `item.data.field_type` references a `field_type` instruction |
| | 19262 | const field_type_data = zir_datas[item.data.field_type].pl_node; |
| | 19263 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index); |
| | 19264 | break :name sema.code.nullTerminatedString(field_type_extra.data.name_start); |
| | 19265 | }, |
| | 19266 | }; |
| 19060 | const name_ip = try mod.intern_pool.getOrPutString(gpa, name); | 19267 | const name_ip = try mod.intern_pool.getOrPutString(gpa, name); |
| 19061 | const gop = fields.getOrPutAssumeCapacity(name_ip); | 19268 | const gop = fields.getOrPutAssumeCapacity(name_ip); |
| 19062 | if (gop.found_existing) { | 19269 | if (gop.found_existing) { |
| ... | @@ -19129,10 +19336,13 @@ fn zirStructInitAnon( | ... | @@ -19129,10 +19336,13 @@ fn zirStructInitAnon( |
| 19129 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, | 19336 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19130 | }); | 19337 | }); |
| 19131 | const alloc = try block.addTy(.alloc, alloc_ty); | 19338 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 19132 | var extra_index = extra.end; | 19339 | var extra_index = extra_end; |
| 19133 | for (types, 0..) |field_ty, i_usize| { | 19340 | for (types, 0..) |field_ty, i_usize| { |
| 19134 | const i = @as(u32, @intCast(i_usize)); | 19341 | const i = @as(u32, @intCast(i_usize)); |
| 19135 | const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index); | 19342 | const item = switch (kind) { |
| | 19343 | .anon_init => sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index), |
| | 19344 | .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index), |
| | 19345 | }; |
| 19136 | extra_index = item.end; | 19346 | extra_index = item.end; |
| 19137 | | 19347 | |
| 19138 | const field_ptr_ty = try mod.ptrType(.{ | 19348 | const field_ptr_ty = try mod.ptrType(.{ |
| ... | @@ -19150,9 +19360,12 @@ fn zirStructInitAnon( | ... | @@ -19150,9 +19360,12 @@ fn zirStructInitAnon( |
| 19150 | } | 19360 | } |
| 19151 | | 19361 | |
| 19152 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, types.len); | 19362 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, types.len); |
| 19153 | var extra_index = extra.end; | 19363 | var extra_index = extra_end; |
| 19154 | for (types, 0..) |_, i| { | 19364 | for (types, 0..) |_, i| { |
| 19155 | const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index); | 19365 | const item = switch (kind) { |
| | 19366 | .anon_init => sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index), |
| | 19367 | .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index), |
| | 19368 | }; |
| 19156 | extra_index = item.end; | 19369 | extra_index = item.end; |
| 19157 | element_refs[i] = try sema.resolveInst(item.data.init); | 19370 | element_refs[i] = try sema.resolveInst(item.data.init); |
| 19158 | } | 19371 | } |
| ... | @@ -19175,14 +19388,21 @@ fn zirArrayInit( | ... | @@ -19175,14 +19388,21 @@ fn zirArrayInit( |
| 19175 | const args = sema.code.refSlice(extra.end, extra.data.operands_len); | 19388 | const args = sema.code.refSlice(extra.end, extra.data.operands_len); |
| 19176 | assert(args.len >= 2); // array_ty + at least one element | 19389 | assert(args.len >= 2); // array_ty + at least one element |
| 19177 | | 19390 | |
| 19178 | const array_ty = try sema.resolveType(block, src, args[0]); | 19391 | const array_ty = sema.resolveType(block, src, args[0]) catch |err| switch (err) { |
| | 19392 | error.GenericPoison => { |
| | 19393 | // The type wasn't actually known, so treat this as an anon array init. |
| | 19394 | return sema.arrayInitAnon(block, src, args[1..], is_ref); |
| | 19395 | }, |
| | 19396 | else => |e| return e, |
| | 19397 | }; |
| | 19398 | const is_tuple = array_ty.zigTypeTag(mod) == .Struct; |
| 19179 | const sentinel_val = array_ty.sentinel(mod); | 19399 | const sentinel_val = array_ty.sentinel(mod); |
| 19180 | | 19400 | |
| 19181 | const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @intFromBool(sentinel_val != null)); | 19401 | const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @intFromBool(sentinel_val != null)); |
| 19182 | defer gpa.free(resolved_args); | 19402 | defer gpa.free(resolved_args); |
| 19183 | for (args[1..], 0..) |arg, i| { | 19403 | for (args[1..], 0..) |arg, i| { |
| 19184 | const resolved_arg = try sema.resolveInst(arg); | 19404 | const resolved_arg = try sema.resolveInst(arg); |
| 19185 | const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct) | 19405 | const elem_ty = if (is_tuple) |
| 19186 | array_ty.structFieldType(i, mod) | 19406 | array_ty.structFieldType(i, mod) |
| 19187 | else | 19407 | else |
| 19188 | array_ty.elemType2(mod); | 19408 | array_ty.elemType2(mod); |
| ... | @@ -19195,6 +19415,18 @@ fn zirArrayInit( | ... | @@ -19195,6 +19415,18 @@ fn zirArrayInit( |
| 19195 | }, | 19415 | }, |
| 19196 | else => return err, | 19416 | else => return err, |
| 19197 | }; | 19417 | }; |
| | 19418 | if (is_tuple) if (try array_ty.structFieldValueComptime(mod, i)) |field_val| { |
| | 19419 | const init_val = try sema.resolveMaybeUndefVal(resolved_args[i]) orelse { |
| | 19420 | const decl = mod.declPtr(block.src_decl); |
| | 19421 | const elem_src = mod.initSrc(src.node_offset.x, decl, i); |
| | 19422 | return sema.failWithNeededComptime(block, elem_src, "value stored in comptime field must be comptime-known"); |
| | 19423 | }; |
| | 19424 | if (!field_val.eql(init_val, elem_ty, mod)) { |
| | 19425 | const decl = mod.declPtr(block.src_decl); |
| | 19426 | const elem_src = mod.initSrc(src.node_offset.x, decl, i); |
| | 19427 | return sema.failWithInvalidComptimeFieldStore(block, elem_src, array_ty, i); |
| | 19428 | } |
| | 19429 | }; |
| 19198 | } | 19430 | } |
| 19199 | | 19431 | |
| 19200 | if (sentinel_val) |some| { | 19432 | if (sentinel_val) |some| { |
| ... | @@ -19283,6 +19515,16 @@ fn zirArrayInitAnon( | ... | @@ -19283,6 +19515,16 @@ fn zirArrayInitAnon( |
| 19283 | const src = inst_data.src(); | 19515 | const src = inst_data.src(); |
| 19284 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); | 19516 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| 19285 | const operands = sema.code.refSlice(extra.end, extra.data.operands_len); | 19517 | const operands = sema.code.refSlice(extra.end, extra.data.operands_len); |
| | 19518 | return sema.arrayInitAnon(block, src, operands, is_ref); |
| | 19519 | } |
| | 19520 | |
| | 19521 | fn arrayInitAnon( |
| | 19522 | sema: *Sema, |
| | 19523 | block: *Block, |
| | 19524 | src: LazySrcLoc, |
| | 19525 | operands: []const Zir.Inst.Ref, |
| | 19526 | is_ref: bool, |
| | 19527 | ) CompileError!Air.Inst.Ref { |
| 19286 | const mod = sema.mod; | 19528 | const mod = sema.mod; |
| 19287 | | 19529 | |
| 19288 | const types = try sema.arena.alloc(InternPool.Index, operands.len); | 19530 | const types = try sema.arena.alloc(InternPool.Index, operands.len); |
| ... | @@ -23034,7 +23276,21 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -23034,7 +23276,21 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 23034 | const callee_ty = sema.typeOf(func); | 23276 | const callee_ty = sema.typeOf(func); |
| 23035 | const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false); | 23277 | const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false); |
| 23036 | const ensure_result_used = extra.flags.ensure_result_used; | 23278 | const ensure_result_used = extra.flags.ensure_result_used; |
| 23037 | return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null, .@"@call"); | 23279 | return sema.analyzeCall( |
| | 23280 | block, |
| | 23281 | func, |
| | 23282 | func_ty, |
| | 23283 | func_src, |
| | 23284 | call_src, |
| | 23285 | modifier, |
| | 23286 | ensure_result_used, |
| | 23287 | .{ .call_builtin = .{ |
| | 23288 | .call_node_offset = inst_data.src_node, |
| | 23289 | .args = resolved_args, |
| | 23290 | } }, |
| | 23291 | null, |
| | 23292 | .@"@call", |
| | 23293 | ); |
| 23038 | } | 23294 | } |
| 23039 | | 23295 | |
| 23040 | fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 23296 | fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |