Swift final methods under the hood

In Swift you have many ways to mark your methods, you can make them: public, private, mutable, final and etc… On this post I’m going to investigate more deeply what happens when a method is marked as final. I’ll do it by looking into the Swift intermediate Language (SIL) code that is generated when a method is tagged as final and compare to when it’s not.

What the final keyword means?

If a method, property, or subscript is marked as final it cannot be overridden. Classes can also be marked as final. Any attempt to subclass a final class is reported as a compile-time error. On this post I will focus only on methods as I believe this is the most common use case. Here is Apple’s documentation on the topic.

Example:

Now without final

Let’s create a class with a method without final, call it and analyse it’s Swift intermediate Language code

Swift intermediate Language (SIL)

Swift has its own intermediate language, which is used by the Swift optimiser to perform specific language optimisations. — If you want to know more about SIL I recommend this blog.

Generating SIL code

$> swiftc -emit-silgen pony.swift | xcrun swift-demangle > pony.sil# 1. `-emit-silgen` will generate raw SIL mangled code.
# 2. `xcrun swift-demangle` to demangle.

Result

What’s going on?

  • (line 8) Main is the program entry point
  • (line 12) Allocating new Pony instance
  • (line 15) Accessing `genus()` method by it’s index on the virtual table
  • (line 16) Applying `genus()` to a pony instance
  • (line 34) Defining a virtual table function for Pony class methods

Adding final

I will add final on `genus()` and regenerate SIL.

Result

What changed?

Since the compiler knows that there is no other class that could override `genus()` it deletes the reference on the virtual table; Adds `function_ref` to access `genus()` method directly; And removes `class_method` that looks for a function by it’s offset on the virtual table.

Concluding

Adding final to your method it means more than just a compile time error. It will internally optimise your code, it will generate a more efficient representation, furthermore it can result into a faster execution. Next time that you create a method and you are not expecting to be overridden remember to mark as final.

References

Machina || Building Software for fun and profit

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store