Skip to content

[6.0][transfer-non-sendable] Teach SILIsolationInfo how to handle "look through instructions" when finding actor instances. #74677

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 2 commits into from
Jun 25, 2024

Conversation

gottesmm
Copy link
Contributor

@gottesmm gottesmm commented Jun 25, 2024

Explanation: This PR fixes an issue where when we were trying to identify the specific actor instance that was being identified and we were not looking through instructions like copy_value/move_value which we should have. So we were saying that two SILIsolationInfo that should be identical were actually different since the underlying value was different.

By doing this, we fix two issues at least:

  1. We make it so that we do not emit an unknown pattern error:
actor MyActor {
  init() async {

  init(ns: NonSendableKlass) async {
    self.k = NonSendableKlass()
    self.helper(ns)
  }

  func helper(_ newK: NonSendableKlass) {}
}

the problem here was that we viewed the isolation of helper to be different than the isolation of ns even though they are the same.

  1. We also fix this error:
actor Test {

  @TaskLocal static var local: Int?

  func withTaskLocal(isolation: isolated (any Actor)? = #isolation,
                     _ body: (consuming NonSendableValue, isolated (any Actor)?) -> Void) async {
    Self.$local.withValue(12) {

      // We used to get these errors here since we thought that body's isolation
      // was different than the body's isolation.
      //
      //  warning: sending 'body' risks causing data races
      //  note: actor-isolated 'body' is captured by a actor-isolated closure...
      body(NonSendableValue(), isolation)
    }
  }
}

The problem in this case is that body is considered isolated to #isolation but there is a copy on it so we think it has different isolation from the closure whose isolation is straight up isolation.

Radars:

  • rdar://129400019

Original PRs:

Risk: Low.
Testing: Added tests to the compiler.
Reviewer: @ktoso

gottesmm added 2 commits June 24, 2024 23:36
…rough instructions" when finding actor instances.

From the perspective of the IR, we are changing SILIsolationInfo such that
inferring an actor instance means looking at equivalence classes of values where
we consider operands to look through instructions to be equivalent to their dest
value. The result is that cases where the IR maybe puts in a copy_value or the
like, we consider the copy_value to have the same isolation info as using the
actor directly. This prevents a class of crashes due to merge failings. Example:

```swift
actor MyActor {
  init() async {

  init(ns: NonSendableKlass) async {
    self.k = NonSendableKlass()
    self.helper(ns)
  }

  func helper(_ newK: NonSendableKlass) {}
}
```

Incidently, we already had a failing test case from this behavior rather than
the one that was the original genesis. Specifically:

1. If a function's SILIsolationInfo is the same as the isolation info of a
SILValue, we assume that no transfer actually occurs.

2. Since we were taking too static of a view of actor instances when comparing,
we would think that a SILIsolationInfo of a #isolation parameter to as an
argument would be different than the ambient's function isolation which is also
that same one. So we would emit a transfer non transferrable error if we pass in
any parameters of the ambient function into another isolated function. Example:

```swift
actor Test {

  @TaskLocal static var local: Int?

  func withTaskLocal(isolation: isolated (any Actor)? = #isolation,
                     _ body: (consuming NonSendableValue, isolated (any Actor)?) -> Void) async {
    Self.$local.withValue(12) {

      // We used to get these errors here since we thought that body's isolation
      // was different than the body's isolation.
      //
      //  warning: sending 'body' risks causing data races
      //  note: actor-isolated 'body' is captured by a actor-isolated closure...
      body(NonSendableValue(), isolation)
    }
  }
}
```

rdar://129400019
(cherry picked from commit c01f551)
@gottesmm gottesmm requested a review from a team as a code owner June 25, 2024 06:38
@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm gottesmm enabled auto-merge June 25, 2024 17:50
@gottesmm gottesmm merged commit c5e8601 into swiftlang:release/6.0 Jun 25, 2024
5 checks passed
@gottesmm gottesmm deleted the release/6.0-rdar129400019 branch June 25, 2024 18:38
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