Skip to content

Fix issue where implicit self was unexpectedly not allowed in nested weak self closure in Swift 6 mode #78738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 11, 2025

Conversation

calda
Copy link
Contributor

@calda calda commented Jan 19, 2025

This PR fixes an issue that @harlanhaskins reported where implicit self is unexpectedly rejected in Swift 6 mode:

func acceptsClosure(_ x: @escaping () -> Void) {}

@MainActor
final class A {
    func nonisolatedMethod() {}

    func createsNestedClosure() {
        acceptsClosure { [weak self] in
            Task { @MainActor [weak self] in
                guard let self else { return }
                nonisolatedMethod() // error: implicit use of 'self' in closure; use 'self.' to make capture semantics explicit
            }
        }
    }
}

This is allowed in Swift 5 mode and should continue being supported.

Please review: @hamishknight @xedin @Jumhyn

Comment on lines +521 to +526
doVoidStuff { [weak self] in
doVoidStuff { [self] in
guard let self else { return }
self.x += 1
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks funny but has been allowed since at least Swift 4.2: https://swiftfiddle.com/irzj67qcezajlj7u5hyq4te2fq

func withEscapingClosure(_ closure: @escaping () -> Void) { closure() }

class Test {
  var x = 0
  
  func test() {
    withEscapingClosure { [weak self] in
      withEscapingClosure { [self] in
        self?.x += 1
        guard let self = self else { return }
        self.x += 1
      }
    }
  }
}

@@ -670,7 +756,7 @@ final class AutoclosureTests {
doVoidStuff { [weak self] in
doVoidStuff { [self] in
guard let self else { return }
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explicit self version of this has been supported since at least Swift 4.2 so it seems perfectly fine for the implicit self version to be supported

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this seems reasonable to me, this is the case that came up last time

@hamishknight hamishknight self-requested a review January 19, 2025 11:22
@@ -670,7 +756,7 @@ final class AutoclosureTests {
doVoidStuff { [weak self] in
doVoidStuff { [self] in
guard let self else { return }
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this seems reasonable to me, this is the case that came up last time

…ftlang/swift into cal--fix-nested-weak-self-issue

Tag build swift-DEVELOPMENT-SNAPSHOT-2025-01-31-a
@calda calda force-pushed the cal--fix-nested-weak-self-issue branch 3 times, most recently from 02d0e9b to f55b571 Compare February 3, 2025 03:09
Comment on lines +970 to +982
actor TestActor {
func setUp() {
doVoidStuff { [weak self] in
Task { [weak self] in
guard let self else { return }
await test()
}
}
}

@MainActor
func test() { }
}
Copy link
Contributor Author

@calda calda Feb 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a test case from another issue that was filed recently about this same bug: #79014

@calda calda force-pushed the cal--fix-nested-weak-self-issue branch 2 times, most recently from 3708ef0 to b648b0c Compare February 3, 2025 03:28
@calda calda force-pushed the cal--fix-nested-weak-self-issue branch from b648b0c to be0e68e Compare February 3, 2025 03:28
Copy link
Contributor

@hamishknight hamishknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the additional tests!

Copy link
Contributor Author

@calda calda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated @hamishknight! -- simplified the code like you suggested while also making sure to reject these other cases we were talking about.

Copy link
Contributor

@hamishknight hamishknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think we can further simplify the logic here, but otherwise this is looking good!

@calda calda force-pushed the cal--fix-nested-weak-self-issue branch from b8e9c23 to 14632b7 Compare February 10, 2025 16:13
@calda
Copy link
Contributor Author

calda commented Feb 10, 2025

Ok should be good now @hamishknight, thanks for the great suggestions as always!

Copy link
Contributor

@hamishknight hamishknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thanks!

@hamishknight
Copy link
Contributor

@swift-ci please test

@hamishknight
Copy link
Contributor

@swift-ci please test source compatibility

@hamishknight hamishknight merged commit f828882 into swiftlang:main Feb 11, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants