# \`inline fn\` vs \`callconv(.Inline)\` vs \`@call(.always\_inline, ...)\`

**URL:** <https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945>\
**Category:** Help\
**Tags:** language\
**Created:** [October 15, 2023, 1:51am UTC](https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945 "2023-10-15T01:51:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![VoilaNeighbor](https://ziggit.dev/user_avatar/ziggit.dev/voilaneighbor/32/745_2.png) [@VoilaNeighbor](https://ziggit.dev/u/VoilaNeighbor)\
**Post date:** [October 15, 2023, 1:51am UTC](https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945/1 "2023-10-15T01:51:57Z")

</div>

I believed that this was a trivial question but I failed to find any summary on Google, so sorry if the answer is already there but I overlooked.

But what are the commonalities and differences between the varied styles of declaring inline functions? By instinction it looks like the _callconv_ approach is an approximate of _force inline_.

From the document:

For `inline fn`:

> `inline` can be used to label a loop expression such that it will be unrolled at compile time. It can also be used to force a function to be inlined at all call sites.

For the callconv:

```zig
// The inline calling convention forces a function to be inlined at all call sites.
// If the function cannot be inlined, it is a compile-time error.
fn shiftLeftOne(a: u32) callconv(.Inline) u32 {
    return a << 1;
}

```

For the always inline modifier:

```zig
pub const CallModifier = enum {
    /// Guarantees that the call will inlined at the callsite.
    /// If this is not possible, a compile error is emitted instead.
    always_inline,

    ...
};

```

---

<div class="post-metadata">

**Author:** ![dude\_the\_builder](https://ziggit.dev/user_avatar/ziggit.dev/dude_the_builder/32/557_2.png) [@dude\_the\_builder](https://ziggit.dev/u/dude_the_builder)\
**Post date:** [October 15, 2023, 2:37am UTC](https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945/2 "2023-10-15T02:37:59Z")

</div>

Here’s a similar question: [Inlining functions](https://ziggit.dev/t/inlining-functions/1341)

---

<div class="post-metadata">

**Author:** ![VoilaNeighbor](https://ziggit.dev/user_avatar/ziggit.dev/voilaneighbor/32/745_2.png) [@VoilaNeighbor](https://ziggit.dev/u/VoilaNeighbor)\
**Post date:** [October 15, 2023, 4:02am UTC](https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945/3 "2023-10-15T04:02:04Z")

</div>

Thanks. It’s interesting that all three questions of my own are answered there. LoL.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [October 15, 2023, 4:08am UTC](https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945/4 "2023-10-15T04:08:34Z")

</div>

Inline line is one of those keywords that can mean so many things in different languages, so I think this question gives us a chance to explore a bit. @dude_the_builder gave a good link to read more about the convention itself, but I’d like to add something from the software design perspective.

There is a value in having all three types of conventions and they each give unique opportunities. Let’s look at one example…

* * *

Keyword vs Parameter…

The nice thing about having a parameter is that it is comptime flexible. That enum value is, well… just a value. We can take it in as a parameter in another function. This allows you to pass in different calling options and then parameterize your calls further - this could be good for bulk testing or even just exploring performance options. So for instance…

```zig
fn foo(x: i32, y: i32) i32 {
    return x + y;   
}
fn bar(x: i32, y: i32) i32 {
    return x - y;
}

const CallModifier = @import("std").builtin.CallModifier;

fn fooBar(comptime modifier: CallModifier, x: i32, y: i32) i32 {
    const a = @call(modifier, foo, .{x, y});
    const b = @call(modifier, bar, .{x, y});
    return a * b;
}

test "Parametric Call Modifier" {
    // always inline foo and bar
    _ = fooBar(.always_inline, 42, 43);

    // never inline foo and bar
    _ = fooBar(.never_inline, 42, 43);
}

```

You can see how we get to control more options here than we otherwise could. You can do a lot of performance tuning with this sort of thing (for instance, we many not want something like a Lippincott function being inlined).

I hope this gives you some more ideas to explore 🙂

---

<div class="post-metadata">

**Author:** ![VoilaNeighbor](https://ziggit.dev/user_avatar/ziggit.dev/voilaneighbor/32/745_2.png) [@VoilaNeighbor](https://ziggit.dev/u/VoilaNeighbor)\
**Post date:** [October 15, 2023, 4:22am UTC](https://ziggit.dev/t/inline-fn-vs-callconv-inline-vs-call-always-inline/1945/5 "2023-10-15T04:22:16Z")

</div>

It’s really innovative and refreshing that Zig tries to expose so much about the internals of the compiler, trying to reduce the size & volume of blackboxes, so that the flexibility in the language is greatly boosted. I am really enlightened by this point. I believe the excellent tool chain and the strong comptime capabilities are highly related, both rallied under the same philosophy.
