Method dispatch for opaque types

Hello everyone,

Could anyone explain, please, what what kind of dispatching is used when I write something like the following?

protocol X {
    func doSomething()
}

func workWithSome(_ x: some X) {
    x.doSomething()
}

func workWithGeneric<T: X>(_ x: T) {
    x.doSomething()
}

My assumption is that both functions call doSomething() via virtual table, because, as I have heard, Swift doesn't generate copies of a class with generics for every T (as C++ does), so it seems impossible to use static dispatch here. But probably I'm wrong and the compiler manages to call doSomething() directly somehow.

I think the first function is just sugar for the second function.

2 Likes

I believe the answer is, it depends. If this is a public function in a library, you have no idea how it’s called, so it uses a vtable. But if it’s a private method and the compiler can see that it’s only ever called with T==Int or T==Double, it’ll just emit those two versions instead.

3 Likes

Both of the above replies are correct. One further detail: if you mark the public function in the library as "inlineable", it will be able to do specialized versions of it for calls from outside the library too, at the cost of limiting your ability to change the implementation in the future.

5 Likes

There is a brief explanation of how this works starting on page 19 of https://download.swift.org/docs/assets/generics.pdf.

3 Likes

I’ve been looking forward to binge-watching season 2 of this pdf, any estimate for the release date?

5 Likes

"when it's ready"

4 Likes

Oh, a really useful link, thank you!

Thank you for answers, guys! According to the link posted here, it works via witness tables