Sema: do not re-evaluate type of non-generic inline call parameters
Closes #13491
This commit is contained in:
11
src/Sema.zig
11
src/Sema.zig
@@ -6361,6 +6361,7 @@ fn analyzeCall(
|
||||
is_comptime_call,
|
||||
&should_memoize,
|
||||
memoized_call_key,
|
||||
func_ty_info.param_types,
|
||||
) catch |err| switch (err) {
|
||||
error.NeededSourceLocation => {
|
||||
_ = sema.inst_map.remove(inst);
|
||||
@@ -6376,6 +6377,7 @@ fn analyzeCall(
|
||||
is_comptime_call,
|
||||
&should_memoize,
|
||||
memoized_call_key,
|
||||
func_ty_info.param_types,
|
||||
);
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
@@ -6612,6 +6614,7 @@ fn analyzeInlineCallArg(
|
||||
is_comptime_call: bool,
|
||||
should_memoize: *bool,
|
||||
memoized_call_key: Module.MemoizedCall.Key,
|
||||
raw_param_types: []const Type,
|
||||
) !void {
|
||||
const zir_tags = sema.code.instructions.items(.tag);
|
||||
switch (zir_tags[inst]) {
|
||||
@@ -6622,8 +6625,12 @@ 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(param_block, param_body, inst);
|
||||
const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
|
||||
const param_ty = param_ty: {
|
||||
const raw_param_ty = raw_param_types[arg_i.*];
|
||||
if (raw_param_ty.tag() != .generic_poison) break :param_ty raw_param_ty;
|
||||
const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
|
||||
break :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(param_ty)) {
|
||||
|
||||
@@ -327,3 +327,20 @@ test "inline call preserves tail call" {
|
||||
S.foo();
|
||||
try expect(S.a == std.math.maxInt(u16));
|
||||
}
|
||||
|
||||
test "inline call doesn't re-evaluate non generic struct" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn foo(f: struct { a: u8, b: u8 }) !void {
|
||||
try expect(f.a == 123);
|
||||
try expect(f.b == 45);
|
||||
}
|
||||
};
|
||||
const ArgTuple = std.meta.ArgsTuple(@TypeOf(S.foo));
|
||||
try @call(.{ .modifier = .always_inline }, S.foo, ArgTuple{.{ .a = 123, .b = 45 }});
|
||||
comptime try @call(.{ .modifier = .always_inline }, S.foo, ArgTuple{.{ .a = 123, .b = 45 }});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user