From 2f34d06d01189ae6349e9c6341ba85ec50b92bb0 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 25 Jul 2022 13:48:21 +0300 Subject: [PATCH] Sema: `analyzeInlineCallArg` needs a block for the arg and the param --- src/Module.zig | 2 ++ src/Sema.zig | 54 ++++++++++++++++++++++++----------------- test/compile_errors.zig | 24 ++++++++++++++++++ 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index c144c9acbd..1e684f6ea1 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5940,7 +5940,9 @@ pub fn argSrc( gpa: Allocator, decl: *Decl, arg_i: usize, + bound_arg_src: ?LazySrcLoc, ) LazySrcLoc { + if (arg_i == 0 and bound_arg_src != null) return bound_arg_src.?; @setCold(true); const tree = decl.getFileScope().getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. diff --git a/src/Sema.zig b/src/Sema.zig index f32ba79d7b..ffe57c4a1b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5353,7 +5353,9 @@ fn zirCall( const func_type = sema.typeOf(func); // Desugar bound functions here + var bound_arg_src: ?LazySrcLoc = null; if (func_type.tag() == .bound_fn) { + bound_arg_src = func_src; const bound_func = try sema.resolveValue(block, .unneeded, func, undefined); const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data; func = bound_data.func_inst; @@ -5369,7 +5371,7 @@ fn zirCall( } } - return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args); + return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src); } const GenericCallAdapter = struct { @@ -5438,6 +5440,7 @@ fn analyzeCall( modifier: std.builtin.CallOptions.Modifier, ensure_result_used: bool, uncasted_args: []const Air.Inst.Ref, + bound_arg_src: ?LazySrcLoc, ) CompileError!Air.Inst.Ref { const mod = sema.mod; @@ -5532,6 +5535,7 @@ fn analyzeCall( ensure_result_used, uncasted_args, call_tag, + bound_arg_src, )) |some| { return some; } else |err| switch (err) { @@ -5654,6 +5658,7 @@ fn analyzeCall( var arg_i: usize = 0; for (fn_info.param_body) |inst| { sema.analyzeInlineCallArg( + block, &child_block, .unneeded, inst, @@ -5665,12 +5670,13 @@ fn analyzeCall( memoized_call_key, ) catch |err| switch (err) { error.NeededSourceLocation => { + sema.inst_map.clearRetainingCapacity(); const decl = sema.mod.declPtr(block.src_decl); + child_block.src_decl = block.src_decl; try sema.analyzeInlineCallArg( - // Intentionally use the wrong block here since we know it's - // going to fail and `argSrc` is relative to `block.src_decl`. block, - Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i), + &child_block, + Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src), inst, new_fn_info, &arg_i, @@ -5832,7 +5838,7 @@ fn analyzeCall( const decl = sema.mod.declPtr(block.src_decl); _ = try sema.analyzeCallArg( block, - Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i), + Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src), param_ty, uncasted_arg, ); @@ -5873,7 +5879,8 @@ fn analyzeCall( fn analyzeInlineCallArg( sema: *Sema, - block: *Block, + arg_block: *Block, + param_block: *Block, arg_src: LazySrcLoc, inst: Zir.Inst.Index, new_fn_info: Type.Payload.Function.Data, @@ -5892,19 +5899,19 @@ fn analyzeInlineCallArg( const param_src = pl_tok.src(); const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index); const param_body = sema.code.extra[extra.end..][0..extra.data.body_len]; - const param_ty_inst = try sema.resolveBody(block, param_body, inst); - const param_ty = try sema.analyzeAsType(block, param_src, param_ty_inst); + const param_ty_inst = try sema.resolveBody(param_block, param_body, inst); + const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst); new_fn_info.param_types[arg_i.*] = param_ty; const uncasted_arg = uncasted_args[arg_i.*]; - if (try sema.typeRequiresComptime(block, arg_src, param_ty)) { - _ = try sema.resolveConstMaybeUndefVal(block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known"); + if (try sema.typeRequiresComptime(arg_block, arg_src, param_ty)) { + _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known"); } - const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); + const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src); try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); if (is_comptime_call) { // TODO explain why function is being called at comptime - const arg_val = try sema.resolveConstMaybeUndefVal(block, arg_src, casted_arg, "argument to function being called at comptime must be comptime known"); + const arg_val = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime known"); switch (arg_val.tag()) { .generic_poison, .generic_poison_type => { // This function is currently evaluated as part of an as-of-yet unresolvable @@ -5915,7 +5922,7 @@ fn analyzeInlineCallArg( // Needed so that lazy values do not trigger // assertion due to type not being resolved // when the hash function is called. - try sema.resolveLazyValue(block, arg_src, arg_val); + try sema.resolveLazyValue(arg_block, arg_src, arg_val); }, } should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(); @@ -5935,7 +5942,7 @@ fn analyzeInlineCallArg( if (is_comptime_call) { // TODO explain why function is being called at comptime - const arg_val = try sema.resolveConstMaybeUndefVal(block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime known"); + const arg_val = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime known"); switch (arg_val.tag()) { .generic_poison, .generic_poison_type => { // This function is currently evaluated as part of an as-of-yet unresolvable @@ -5946,7 +5953,7 @@ fn analyzeInlineCallArg( // Needed so that lazy values do not trigger // assertion due to type not being resolved // when the hash function is called. - try sema.resolveLazyValue(block, arg_src, arg_val); + try sema.resolveLazyValue(arg_block, arg_src, arg_val); }, } should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(); @@ -6011,6 +6018,7 @@ fn instantiateGenericCall( ensure_result_used: bool, uncasted_args: []const Air.Inst.Ref, call_tag: Air.Inst.Tag, + bound_arg_src: ?LazySrcLoc, ) CompileError!Air.Inst.Ref { const mod = sema.mod; const gpa = sema.gpa; @@ -6070,7 +6078,7 @@ fn instantiateGenericCall( const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) { error.NeededSourceLocation => { const decl = sema.mod.declPtr(block.src_decl); - const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i); + const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src); _ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[i]); return error.AnalysisFail; }, @@ -6392,7 +6400,7 @@ fn instantiateGenericCall( const decl = sema.mod.declPtr(block.src_decl); _ = try sema.analyzeGenericCallArg( block, - Module.argSrc(call_src.node_offset.x, sema.gpa, decl, total_i), + Module.argSrc(call_src.node_offset.x, sema.gpa, decl, total_i, bound_arg_src), uncasted_args[total_i], comptime_args[total_i], runtime_args, @@ -14263,7 +14271,7 @@ fn analyzeRet( const ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty); const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); const args: [1]Air.Inst.Ref = .{err_return_trace}; - _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args); + _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args, null); } try sema.resolveTypeLayout(block, src, sema.fn_ret_ty); @@ -17880,7 +17888,9 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError var resolved_args: []Air.Inst.Ref = undefined; // Desugar bound functions here + var bound_arg_src: ?LazySrcLoc = null; if (sema.typeOf(func).tag() == .bound_fn) { + bound_arg_src = func_src; const bound_func = try sema.resolveValue(block, .unneeded, func, undefined); const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data; func = bound_data.func_inst; @@ -17896,7 +17906,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } } const ensure_result_used = extra.flags.ensure_result_used; - return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args); + return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src); } fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -19182,7 +19192,7 @@ fn panicWithMsg( Value.@"null", ); const args: [2]Air.Inst.Ref = .{ msg_inst, null_stack_trace }; - _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, &args); + _ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, &args, null); return always_noreturn; } @@ -19223,7 +19233,7 @@ fn panicUnwrapError( const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand); const err_return_trace = try sema.getErrorReturnTrace(&fail_block, src); const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; - _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args); + _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null); } } try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); @@ -19264,7 +19274,7 @@ fn panicIndexOutOfBounds( } else { const panic_fn = try sema.getBuiltin(&fail_block, src, "panicOutOfBounds"); const args: [2]Air.Inst.Ref = .{ index, len }; - _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args); + _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null); } } try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index fe6145cc12..180cf74bcb 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -183,6 +183,30 @@ pub fn addCases(ctx: *TestContext) !void { }); } + { + const case = ctx.obj("argument causes error ", .{}); + case.backend = .stage2; + + case.addSourceFile("b.zig", + \\pub const ElfDynLib = struct { + \\ pub fn lookup(self: *ElfDynLib, comptime T: type) ?T { + \\ _ = self; + \\ return undefined; + \\ } + \\}; + ); + + case.addError( + \\pub export fn entry() void { + \\ var lib: @import("b.zig").ElfDynLib = undefined; + \\ _ = lib.lookup(fn () void); + \\} + , &[_][]const u8{ + ":3:12: error: unable to resolve comptime value", + ":3:12: note: argument to function being called at comptime must be comptime known", + }); + } + // TODO test this in stage2, but we won't even try in stage1 //ctx.objErrStage1("inline fn calls itself indirectly", // \\export fn foo() void {