diff --git a/src/Sema.zig b/src/Sema.zig index d61aa52be4..87216348f2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1958,6 +1958,14 @@ fn zirRetPtr( .pointee_type = sema.fn_ret_ty, .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), }); + + if (block.inlining != null) { + // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr. + // TODO when functions gain result location support, the inlining struct in + // Block should contain the return pointer, and we would pass that through here. + return block.addTy(.alloc, ptr_type); + } + return block.addTy(.ret_ptr, ptr_type); } diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index b00c2f7a59..80f1f4d919 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -90,3 +90,34 @@ test "discard the result of a function that returns a struct" { S.entry(); comptime S.entry(); } + +test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" { + const S = struct { + field: u32, + + fn doTheTest() !void { + bar2 = actualFn; + const result = try foo(); + try expect(result.field == 1234); + } + + const Foo = struct { field: u32 }; + + fn foo() !Foo { + var res: Foo = undefined; + res.field = bar(); + return res; + } + + inline fn bar() u32 { + return bar2.?(); + } + + var bar2: ?fn () u32 = null; + + fn actualFn() u32 { + return 1234; + } + }; + try S.doTheTest(); +}