Who benefits from the `indirect` keyword?

Good morning, Felicias,

I was thinking - what is the benefit of having an indirect keyword for enum cases? Apple's The Swift Programming Language says:

You indicate that an enumeration case is recursive by writing indirect before it, which tells the compiler to insert the necessary layer of indirection.

Does it have any benefit for a programmer to know that? Is there some risk of infinite loop or another danger? How are we telling compiler this, if compiler is able to know on its own if we forget to add the indirect keyword? That looks like it could be working just like it does now without this keyword.

Enums in Swift are really memory efficient(comparing to smth like java) while being remarkably powerful(one of the main Swift's selling point for me).
The problem with indirect cases is enum's memory layout. Having an indirect case in enum makes it's memory layout not trivial so it is representation becomes more complicated(correct me if I'm wrong).

Do you mean that the keyword has been introduced to remind programmers about the performance cost?

Yes, as we really don't need using try before each throwing function, we really don't need placing indirect before indirect enum rather than showing that this enum is not as simple as the other ones.

Here Is what I found on the forum:

Well the most common use case for indirect would be to allow for recursive enums I guess.

enum BinaryTree<T> {
   case empty
   indirect case node(left: BinaryTree, value: T, right: BinaryTree)
}

What is the allocation size for this enum type? You can't say without making the node case indirect (so only storing a reference).
I am pretty sure the compiler could infer the keyword (like possibly many other keywords by analyzing the code) but some of that analysis would be very time-consuming and non-trivial in many ways.

I didn't know about the "rare case" usecase. That's an interesting idea.

2 Likes

So are there times when the compiler doesn’t throw an error about missing indirect? There should be, to make the point about avoiding heavy compilation valid. Otherwise, if compiler always knows about something, that would make a keyword redundant from this point of view. Possibly valid from other points.

The compiler does not always know when indirect is necessary or desired. For example, Optional<T> is compiled as part of the standard library, and we wouldn't want Optional to always be indirect, because that would mean every Int? or String? requires an additional allocation to hold the indirect value. Nonetheless, code in another module could attempt to instantiate Optional in a way that would require indirect-ness to handle recursion:

struct Recursive {
  var value: Int
  var next: Recursive?
}

By not marking Optional or its cases indirect, we explicitly made the choice not to support recursion using Optional because we considered performance to be more important. You use indirect when you need recursion or want to favor data size over performance. These are judgments for which the compiler can't always make the right choice on its own, so it's up to the programmer to make them.

9 Likes
Terms of Service

Privacy Policy

Cookie Policy