Allow implicit self in escaping closures when self is explicitly captured

I'd reiterate that explicit self. does not indicate captured self. If one writes self. out of habit, they never see this warning. Making it an error adds to confusion.

+1

This is probably ok, but I think we should carefully evaluate the tradeoff in the case of value types that store references.

I agree.

Big +1 here. This hole leads to cycles in practice. It would be great to see it closed.

3 Likes

My question is how do we play "strong-weak-dance" with this new feature.

Specifically, if in a class, we write code like:

var x

func someMethod() {
  let block = { [weak self] in
    guard let self = self else { return } // <------- (1)
    print(x)     // <------- (2)
  }
}

My question is:
Is line (2) valid?
If it is, is self referenced weakly or strongly in line (2)?
If it is referenced weakly, how can compiler know that self should be captured strongly, after line (1) is executed and before line (2) is executed?
Does it mean the existence of line (1) will affect the semantics of line (2)?

Strong +1, but I think we should consider the [weak self] and [unowned self] cases.

class Foo {
    var x: Int

    func bar() {
        let block =  { [weak self] in
            let y = x // Int? ????
            baz(using: self) // allowed? will it error as self is weak?
            guard let self = self else { return } // Is it allowed?
            let y2 = x // Is it allowed?
        }
    }
}

func baz(using foo: Foo) { ... }

In the current state of the proposal/implementation, only a strong, unowned, or unowned(unsafe) capture of self will enable implicit self (EDIT: which is to say, none of the implicit usages of self in the examples of @CrystDragon or @GLanza would be valid under this proposal as it stands). Allowing more general self rebinding is something that could be interesting to pursue, but there are enough additional questions (e.g. if we are willing to look through the weak storage, what else are we willing to look through? Does it work with if let? What about let self = self!) that I think it makes sense to deal with this idea in a separate proposal. Would be interested to hear others’ input, though!

2 Likes

For those interested in this pitch, I have an implementation which addresses the first two of @dabrahams's suggestions above, but does not incorporate this one:

After my initial investigation work I hit a wall and have been unable to dedicate the time and effort necessary to adequately address this issue. The question I faced is summarized here for anyone that feels strongly about ensuring that this feature be included in the proposal, but absent some additional assistance I will likely have to move forward with the proposal excluding this aspect.

Explicit self. is not an adequate indicator of a captured reference. It is good that we are removing it from the compiler. In my view it is not worth the effort to introduce it again in other places. Leave it to linters.

1 Like

To be clear, nothing is being removed here. This is a strictly additive change that will only introduce an additional way to specify a capture of self. Writing self. explicitly will continue to capture self.

I am fully aware of that. From my perspective, this is a step in direction of removing self. as an indicator of captured reference completely, whatever the team view is today. I will fight the proposal introducing self. back on other elements.

See how this simple statement needs a side note not to be misunderstood.

1 Like

Frederick,

Thank you so much for your efforts! For the record, I don't feel strongly that the third suggestion be part of the proposal. The main argument for bundling it with the proposal would be to help satisfy reviewers who might think they are losing valuable protections. However, I think you could equally well just point to that suggestion as a future direction.

Is that quite true, if you implemented the first of my suggestions (Eliminate the need to even write β€œ [self] in ” when self is known to be a non-class type)?

Yeah, I will definitely note this possibility in the proposal as a future direction.

I was somewhat loose with my language thereβ€”I (mistakenly) understood @paiv's comment to imply that they took this proposal to remove the option to capture self just by writing self. explicitly. More precisely, I should have said that without your third suggestion, this proposal remains entirely source compatible, and will not make any currently valid code invalid.