Does let work like const or constexpr?

When the values of let variables are known at compile time and they are guaranteed to be immutable, are there any guarantees about time they are evaluated?

For example, if a function defines a constant element (It probably should be defined outside), is it created every time the function is called, or there are some guarantees about compile time evaluation? And since compile time evaluation can be tricky, are there any guarantees that it is evaluated only once? If not - is it a common optimization the compiler is likely to perform?

let is initialized at runtime not compile time. It is evaluated when it’s first declared. There are a few pitches available for compile time evaluation.

2 Likes

The respective work is almost three years old now. It doesn't seem to be priority at this point of time.

There have been updates from those authors very recently: Compile-Time Values and Integer Generics

Doug

2 Likes

I stand corrected, thanks for the headsup. I wonder how I could have missed that.

This is just a guess but the compiler should be able to optimize function-local lets at some lower language-agnostic level (I think).

However, a non-private let in a class for example, can be potentially overridden and therefore can't be optimized.

As for the rest (let's in struct's, also static and global let's) what I think happens there is, constant expressions are evaluated at compile time however memory for the let's is still allocated and their values are loaded from memory at run time, whenever they are used.

Hoping some knowledgable people can comment on this, been also curious about this!

2 Likes

In the fully general case, static and global lets are lazy:

class Foo {
  static let a = { 
    print("evaluating a")
    return 1
  }()
}

print(1)
print(Foo.a)
1
evaluating a
1

(Swiftfiddle link)

To my surprise, even when LLVM can constant-fold the expression, the value is still loaded at runtime:

public let n = 2 + 2
main:
        mov     qword ptr [rip + (output.n : Swift.Int)], 4
        xor     eax, eax
        ret

output.n : Swift.Int:
        .zero   8

(Godbolt link)