mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Sema: analyzeInlineCallArg needs a block for the arg and the param
This commit is contained in:
parent
370793a36b
commit
2f34d06d01
3 changed files with 58 additions and 22 deletions
|
|
@ -5940,7 +5940,9 @@ pub fn argSrc(
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
decl: *Decl,
|
decl: *Decl,
|
||||||
arg_i: usize,
|
arg_i: usize,
|
||||||
|
bound_arg_src: ?LazySrcLoc,
|
||||||
) LazySrcLoc {
|
) LazySrcLoc {
|
||||||
|
if (arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
const tree = decl.getFileScope().getTree(gpa) catch |err| {
|
const tree = decl.getFileScope().getTree(gpa) catch |err| {
|
||||||
// In this case we emit a warning + a less precise source location.
|
// In this case we emit a warning + a less precise source location.
|
||||||
|
|
|
||||||
54
src/Sema.zig
54
src/Sema.zig
|
|
@ -5353,7 +5353,9 @@ fn zirCall(
|
||||||
const func_type = sema.typeOf(func);
|
const func_type = sema.typeOf(func);
|
||||||
|
|
||||||
// Desugar bound functions here
|
// Desugar bound functions here
|
||||||
|
var bound_arg_src: ?LazySrcLoc = null;
|
||||||
if (func_type.tag() == .bound_fn) {
|
if (func_type.tag() == .bound_fn) {
|
||||||
|
bound_arg_src = func_src;
|
||||||
const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);
|
const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);
|
||||||
const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
|
const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
|
||||||
func = bound_data.func_inst;
|
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 {
|
const GenericCallAdapter = struct {
|
||||||
|
|
@ -5438,6 +5440,7 @@ fn analyzeCall(
|
||||||
modifier: std.builtin.CallOptions.Modifier,
|
modifier: std.builtin.CallOptions.Modifier,
|
||||||
ensure_result_used: bool,
|
ensure_result_used: bool,
|
||||||
uncasted_args: []const Air.Inst.Ref,
|
uncasted_args: []const Air.Inst.Ref,
|
||||||
|
bound_arg_src: ?LazySrcLoc,
|
||||||
) CompileError!Air.Inst.Ref {
|
) CompileError!Air.Inst.Ref {
|
||||||
const mod = sema.mod;
|
const mod = sema.mod;
|
||||||
|
|
||||||
|
|
@ -5532,6 +5535,7 @@ fn analyzeCall(
|
||||||
ensure_result_used,
|
ensure_result_used,
|
||||||
uncasted_args,
|
uncasted_args,
|
||||||
call_tag,
|
call_tag,
|
||||||
|
bound_arg_src,
|
||||||
)) |some| {
|
)) |some| {
|
||||||
return some;
|
return some;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5654,6 +5658,7 @@ fn analyzeCall(
|
||||||
var arg_i: usize = 0;
|
var arg_i: usize = 0;
|
||||||
for (fn_info.param_body) |inst| {
|
for (fn_info.param_body) |inst| {
|
||||||
sema.analyzeInlineCallArg(
|
sema.analyzeInlineCallArg(
|
||||||
|
block,
|
||||||
&child_block,
|
&child_block,
|
||||||
.unneeded,
|
.unneeded,
|
||||||
inst,
|
inst,
|
||||||
|
|
@ -5665,12 +5670,13 @@ fn analyzeCall(
|
||||||
memoized_call_key,
|
memoized_call_key,
|
||||||
) catch |err| switch (err) {
|
) catch |err| switch (err) {
|
||||||
error.NeededSourceLocation => {
|
error.NeededSourceLocation => {
|
||||||
|
sema.inst_map.clearRetainingCapacity();
|
||||||
const decl = sema.mod.declPtr(block.src_decl);
|
const decl = sema.mod.declPtr(block.src_decl);
|
||||||
|
child_block.src_decl = block.src_decl;
|
||||||
try sema.analyzeInlineCallArg(
|
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,
|
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,
|
inst,
|
||||||
new_fn_info,
|
new_fn_info,
|
||||||
&arg_i,
|
&arg_i,
|
||||||
|
|
@ -5832,7 +5838,7 @@ fn analyzeCall(
|
||||||
const decl = sema.mod.declPtr(block.src_decl);
|
const decl = sema.mod.declPtr(block.src_decl);
|
||||||
_ = try sema.analyzeCallArg(
|
_ = try sema.analyzeCallArg(
|
||||||
block,
|
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,
|
param_ty,
|
||||||
uncasted_arg,
|
uncasted_arg,
|
||||||
);
|
);
|
||||||
|
|
@ -5873,7 +5879,8 @@ fn analyzeCall(
|
||||||
|
|
||||||
fn analyzeInlineCallArg(
|
fn analyzeInlineCallArg(
|
||||||
sema: *Sema,
|
sema: *Sema,
|
||||||
block: *Block,
|
arg_block: *Block,
|
||||||
|
param_block: *Block,
|
||||||
arg_src: LazySrcLoc,
|
arg_src: LazySrcLoc,
|
||||||
inst: Zir.Inst.Index,
|
inst: Zir.Inst.Index,
|
||||||
new_fn_info: Type.Payload.Function.Data,
|
new_fn_info: Type.Payload.Function.Data,
|
||||||
|
|
@ -5892,19 +5899,19 @@ fn analyzeInlineCallArg(
|
||||||
const param_src = pl_tok.src();
|
const param_src = pl_tok.src();
|
||||||
const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
|
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_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_inst = try sema.resolveBody(param_block, param_body, inst);
|
||||||
const param_ty = try sema.analyzeAsType(block, param_src, param_ty_inst);
|
const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
|
||||||
new_fn_info.param_types[arg_i.*] = param_ty;
|
new_fn_info.param_types[arg_i.*] = param_ty;
|
||||||
const uncasted_arg = uncasted_args[arg_i.*];
|
const uncasted_arg = uncasted_args[arg_i.*];
|
||||||
if (try sema.typeRequiresComptime(block, arg_src, param_ty)) {
|
if (try sema.typeRequiresComptime(arg_block, arg_src, param_ty)) {
|
||||||
_ = try sema.resolveConstMaybeUndefVal(block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known");
|
_ = 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);
|
try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
|
||||||
|
|
||||||
if (is_comptime_call) {
|
if (is_comptime_call) {
|
||||||
// TODO explain why function is being called at comptime
|
// 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()) {
|
switch (arg_val.tag()) {
|
||||||
.generic_poison, .generic_poison_type => {
|
.generic_poison, .generic_poison_type => {
|
||||||
// This function is currently evaluated as part of an as-of-yet unresolvable
|
// 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
|
// Needed so that lazy values do not trigger
|
||||||
// assertion due to type not being resolved
|
// assertion due to type not being resolved
|
||||||
// when the hash function is called.
|
// 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();
|
should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
|
||||||
|
|
@ -5935,7 +5942,7 @@ fn analyzeInlineCallArg(
|
||||||
|
|
||||||
if (is_comptime_call) {
|
if (is_comptime_call) {
|
||||||
// TODO explain why function is being called at comptime
|
// 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()) {
|
switch (arg_val.tag()) {
|
||||||
.generic_poison, .generic_poison_type => {
|
.generic_poison, .generic_poison_type => {
|
||||||
// This function is currently evaluated as part of an as-of-yet unresolvable
|
// 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
|
// Needed so that lazy values do not trigger
|
||||||
// assertion due to type not being resolved
|
// assertion due to type not being resolved
|
||||||
// when the hash function is called.
|
// 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();
|
should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
|
||||||
|
|
@ -6011,6 +6018,7 @@ fn instantiateGenericCall(
|
||||||
ensure_result_used: bool,
|
ensure_result_used: bool,
|
||||||
uncasted_args: []const Air.Inst.Ref,
|
uncasted_args: []const Air.Inst.Ref,
|
||||||
call_tag: Air.Inst.Tag,
|
call_tag: Air.Inst.Tag,
|
||||||
|
bound_arg_src: ?LazySrcLoc,
|
||||||
) CompileError!Air.Inst.Ref {
|
) CompileError!Air.Inst.Ref {
|
||||||
const mod = sema.mod;
|
const mod = sema.mod;
|
||||||
const gpa = sema.gpa;
|
const gpa = sema.gpa;
|
||||||
|
|
@ -6070,7 +6078,7 @@ fn instantiateGenericCall(
|
||||||
const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) {
|
const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) {
|
||||||
error.NeededSourceLocation => {
|
error.NeededSourceLocation => {
|
||||||
const decl = sema.mod.declPtr(block.src_decl);
|
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]);
|
_ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[i]);
|
||||||
return error.AnalysisFail;
|
return error.AnalysisFail;
|
||||||
},
|
},
|
||||||
|
|
@ -6392,7 +6400,7 @@ fn instantiateGenericCall(
|
||||||
const decl = sema.mod.declPtr(block.src_decl);
|
const decl = sema.mod.declPtr(block.src_decl);
|
||||||
_ = try sema.analyzeGenericCallArg(
|
_ = try sema.analyzeGenericCallArg(
|
||||||
block,
|
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],
|
uncasted_args[total_i],
|
||||||
comptime_args[total_i],
|
comptime_args[total_i],
|
||||||
runtime_args,
|
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 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 err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||||
const args: [1]Air.Inst.Ref = .{err_return_trace};
|
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);
|
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;
|
var resolved_args: []Air.Inst.Ref = undefined;
|
||||||
|
|
||||||
// Desugar bound functions here
|
// Desugar bound functions here
|
||||||
|
var bound_arg_src: ?LazySrcLoc = null;
|
||||||
if (sema.typeOf(func).tag() == .bound_fn) {
|
if (sema.typeOf(func).tag() == .bound_fn) {
|
||||||
|
bound_arg_src = func_src;
|
||||||
const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);
|
const bound_func = try sema.resolveValue(block, .unneeded, func, undefined);
|
||||||
const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
|
const bound_data = &bound_func.cast(Value.Payload.BoundFn).?.data;
|
||||||
func = bound_data.func_inst;
|
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;
|
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 {
|
fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
|
|
@ -19182,7 +19192,7 @@ fn panicWithMsg(
|
||||||
Value.@"null",
|
Value.@"null",
|
||||||
);
|
);
|
||||||
const args: [2]Air.Inst.Ref = .{ msg_inst, null_stack_trace };
|
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;
|
return always_noreturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19223,7 +19233,7 @@ fn panicUnwrapError(
|
||||||
const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
|
const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
|
||||||
const err_return_trace = try sema.getErrorReturnTrace(&fail_block, src);
|
const err_return_trace = try sema.getErrorReturnTrace(&fail_block, src);
|
||||||
const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
|
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);
|
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
|
||||||
|
|
@ -19264,7 +19274,7 @@ fn panicIndexOutOfBounds(
|
||||||
} else {
|
} else {
|
||||||
const panic_fn = try sema.getBuiltin(&fail_block, src, "panicOutOfBounds");
|
const panic_fn = try sema.getBuiltin(&fail_block, src, "panicOutOfBounds");
|
||||||
const args: [2]Air.Inst.Ref = .{ index, len };
|
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);
|
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
|
||||||
|
|
|
||||||
|
|
@ -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
|
// TODO test this in stage2, but we won't even try in stage1
|
||||||
//ctx.objErrStage1("inline fn calls itself indirectly",
|
//ctx.objErrStage1("inline fn calls itself indirectly",
|
||||||
// \\export fn foo() void {
|
// \\export fn foo() void {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue