[Accepted] SE-0481: `weak let`

Hello, Swift community.

The review of SE-0481: weak let ran from April 30th through May 13th, 2025.

Feedback was generally positive.

Some reviewers expressed concern about a perceived shift in the meaning of let that allows the "mutation" of the weak reference becoming nil. The Language Steering Group is satisfied with the explanation in the proposal that the weak reference itself remains constant, and it's simply that the act of observing it will begin to yield nil after the referent is destroyed. The fact (as pointed out in the review) that weak vars do not trigger the observing willSet / didSet accessors when they become nil is also consistent with this way of understanding weak references. The LSG further notes that the mutability story of let in complex cases was recently complicated by the introduction of atomic values and mutexes, which must be declared with let, although we believe weak let can be more simply understood.

There was some discussion in the review about let property wrappers and computed let properties. The LSG does not see any reason to hold up or complicate this feature, where the interpretation of let is natural and immediately useful, over potential changes to other features. Community members interested in these ideas should pitch them separately.

Accordingly, SE-0481 is accepted.

As always, I'd like to thank the reviewers for their contributions; participating in open review is a key part of making Swift a better language.

John McCall
Review Manager

35 Likes

By any chance do we know if nonisolated lazy let will be possible? Or will that need to be a compiler error similar to nonisolated lazy var?

Ahh… maybe I misread the proposal… looks like this would be a different direction for another day maybe.

I don't really see the connection to SE-0481, but I'll try to answer it. A lazy var instance property of an actor cannot be safely nonisolated both because the lazy-initialization sequence is not thread-safe and because it is a mutable variable. lazy let would address the latter but not the former. The lazy-initialization sequence could theoretically be made thread-safe (as long as the initializer does not require isolation), the same way we do with globals, but it would require a significant per-property storage overhead in the actor. It might also need new runtime support.

1 Like

That makes total sense. I thought maybe we were chipping away at the formal definition of let to an extent that lazy let might begin to make sense… but that's on me for not reading the proposal close enough. There was no explicit discussion of lazy let so I understand that should not be part of the same discussion.

Nice, looking forward to using this.

Can we do lazy let now? :wink:

7 Likes

Or property wrappers on lets?

5 Likes

I directly addressed that in the announcement post (and the same applies to lazy let). The LSG is perfectly happy to see proposals that are narrowly focused on fixing specific problems.

1 Like

Hi, pardon my ignorance, I was reading swift-evolution/proposals/0481-weak-let.md at main · swiftlang/swift-evolution · GitHub

It was stated that the following code would throw the compilation error: error: reference to captured var 'c' in concurrently-executing code

However for me it compiles without any error

final class C: Sendable {
    func foo() {}
}

func makeClosure() -> @Sendable () -> Void {
    let c = C()
    return { [weak c] in
        c?.foo() // expected compilation error but no compilation error

        c = nil // allowed, but surprising and very rare
    }
}

Swift Version: Apple Swift version 6.1

This was mentioned in the review:

1 Like

Thanks a lot @ph1ps

Just to confirm my understanding:

  • Ideally this should be throwing a compilation error in Swift 6.1 but doesn't and that is a bug.
  • Once that bug is fixed, then we would know the importance of weak let or is there other scenarios that we can try out (with existing bug)?

Bug affects type checking of @Sendable closures, but does not affect checking of Sendable classes. So the difference is already visible there.

1 Like

Thank you so much @Nickolas_Pohilets for the clear explanation!

I missed the most obvious part of the class.