Add SIL Pass for flow-sensitive, region-based Sendable checking #67172
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Under current strict concurrency checking, function calls that will execute in a different isolation domain than the caller are not allowed to be passed values whose type does not conform to the
Sendable
protocol. This model is difficult to code under, and is overly restrictive: values of arbitrary type may be safely passed to other isolation domains provided they are not aliased or otherwise accessed afterwards.This PR begins to implement a SIL pass that performs flow-sensitive checking to allow safe passing of non-
Sendable
values between isolation domains. Statically, values are grouped into "regions". Values in the same region may alias or point to each other in the heap, but values in different regions are guaranteed to be mutually inaccessible. A linear type system then tracks the regions that are accessible - marking regions "consumed" when any of their values are sent to other isolation domains. This is necessarily still an over-approximation - dynamically, it may be possible two values in the same region have nothing to do with each other - but still enables a much wider variety of local concurrent programming patterns than previously possible.At an implementation level, the key object is the
Partition
datatype defined inPartitionUtils.h
. ThePartitionAnalysis
engine inSendNonSendable.cpp
then implements an analysis that uses these partitions to divide allSILValue
s into the regions described above, consuming the regions when they are sent to other isolation domains and throwing diagnostics when values from a consumed region are accessed. To accomplish this, aPartitionOpTranslator
translates sequences ofSILInstruction
s into sequences ofPartitionOp
s.PartitionOp
s describe primitive transformations to the partition such as assigning indices to new regions, assigning indices to existing regions, merging regions, consuming regions, and requiring the existence of regions. Though it is not yet tested in this PR, the translation intoPartitionOp
s is followed by a fixpoint iteration algorithm that solves for the partitions at exit and entry to each basic block that respect the action of the generatedPartitionOp
s, and respect the structure of the CFG.region_based_sendability.swift
contains test cases highlighting the key functionality of this PR. Much more functionality, such as testing more general control flow, is not yet tested, but will be in followup PRs. Even more functionality, such as handling defer blocks and handling other concurrency primitives besides plain async/await, is not yet implemented and will also come in followup PRs.