Skip to content

[region-isolation] Ensure that if a var is captured by reference in a closure that we do not allow for later accesses to sendableFields #70171

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

Conversation

gottesmm
Copy link
Contributor

@gottesmm gottesmm commented Dec 1, 2023

This PR contains two different commits and a utility commit:

  1. In the first commit, I change the pass to no longer allow for sendableFields of vars to be used after the var is transferred if the var is captured by reference in a closure. The reason that we must do this is that even if the sendable field is safe, we may race against a load/write to the field itself in the var. I implemented this by adding an early dataflow that the later region dataflow uses to determine if a value is reachable from a closure capture.
  2. In this commit, I refactored ImmutablePointerSetFactory to no longer require its generic operand to be an actual pointer. Instead we now require T to have a PointerLikeTypeTraits implementation. This lets one use SILValue and more importantly TransferringOperand (which I need in the next commit). I did this separately from the next commit so that I could use the other places we use ImmutablePointerSetFactory for correctness.
  3. In this commit I changed the pass to track all transfer instructions instead of just the first that we saw. Previously I avoided doing this since the only problem would be that in a case where we had two transfer instructions that were in an if-else block, we would just emit an error for one. But in the case where some transfer instructions were impacted by a closure capture and others are not, we actually need to track both since their behaviors are different.

rdar://119048779
rdar://115124361

… of a non-Sendable typed var and the var is captured in a closure

If the var is captured in a closure before it is transferred, it is not safe to
access the Sendable field since we may race on accessing the field with an
assignment to the field in another concurrency domain.

rdar://115124361
…t require T to conform to PointerLikeTypeTraits.

This allows one to place types like PointerIntPair and value types that wrap a
pointer into the pointer set.

I am making this change before I use this data structure in TransferNonSendable
and using ARC to validate that I haven't broken anything.
…truction, track all of them.

Previously I avoided doing this since the only problem would be that in a case
where we had two transfer instructions that were in an if-else block, we would
just emit an error for one:

```swift
if boolValue {
  transfer(x)
} else {
  transfer(x) // Only emit error for this transfer!
}

useValue(x)
```

Now that we are tracking at the transfer point if any element in the transfer
was captured in a closure, this becomes an actual semantic issue since if we
track the transfer instruction that isn't reachable from the closure capture, we
will not become more pessimistic:

```swift
if boolValue {
  closure = { useInOut(&x) }
  transfer(x)
} else {
  transfer(x)
}

// Since we grab from the else block, sendableField is allowed to be accessed
// since we do not track that x was captured by reference in a closure.
x.sendableField
useValue(x)
```

To be truly safe, we need to emit both errors.

rdar://119048779
@gottesmm gottesmm requested review from ktoso and kavon as code owners December 1, 2023 21:58
@gottesmm gottesmm requested a review from slavapestov December 1, 2023 21:58
@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 1, 2023

@swift-ci smoke test

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 1, 2023

@swift-ci smoke test

@gottesmm
Copy link
Contributor Author

gottesmm commented Dec 1, 2023

@swift-ci build toolchain

@gottesmm gottesmm merged commit 4c754ae into swiftlang:main Dec 3, 2023
@gottesmm gottesmm deleted the pr-b349a91e3e11b734533ef6be6960d755ed783b71 branch December 3, 2023 03:47
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.

1 participant