Do I understand generics right?

If we write the function

func generic<First, Second>(first: First, second: Second) {}

And next in our code we write the next use of that function
generic(first: 0, second: "N")
generic(first: 10, second: 20)

Compiler make a file with the next code, before translate our code in machine language.
func generic(first: Int, second: String) {}
func generic(first: Int, second: Int) {}

I mean that compiler just write necessary code, and nothin else magic not happen?

Not quite. The compiler has a table for each type that has instructions for how generic code can manipulate that type. When you write a generic function the compiler creates a function that takes a pointer to each value as well as a pointer to the value witness table for each generic type, and then uses the witness table to do things to the values.

When the compiler knows what the generic types are and can see the definition of the generic function (because it's in the same module or @inlinable), it can optimize it into a regular function that takes the arguments directly. This is usually what happens in practice, but not always.

Here's a more detailed and accurate description of how this works: Implementing Swift Generics

6 Likes

Thanks. So if I a simple user and writing a two modules programm. I need use the @inlinable in a definition of my generics function or not?

As a rule of thumb, you really shouldn't need @inlinable unless you absolutely cannot pay the extra cost associated with generic dispatch. The extra cost usually amounts to:

  • Having to box the underlying value in a 3-word stack-allocated box
    • If the thing doesn't fit in 3 words, it's allocated on the heap and reference counted
  • Having to pass the type metadata of the generic type into the calling function
  • Having to copy the parameters around using special copy functions (called the 'value witness table') instead of just moving the memory directly.

For many applications, this penalty isn't substantial.

2 Likes

has @inlineable just completely superseded @_specialize(where:) ? idk

I wouldn't say so. @_specialize(where:) is still useful for specific known hot paths, and doesn't require inlining an implementation into user code. It dispatches at runtime vs. compile time.

2 Likes

<obligatory>…but it also isn't actually a supported feature yet. It may have bugs in its current form, and the syntax may change if it's ever officially added to the language.</obligatory>

4 Likes
Terms of Service

Privacy Policy

Cookie Policy