I am making this specific API since I am going to make it so that
SILIsolationInfo::get(SILInstruction *) can infer isolation info from self even
from functions that are not apply isolation crossing points. For example, in the
following, we need to understand that test is main actor isolated and we
shouldn't emit an error.
```swift
@MainActor func test(_ x: NonSendable) {}
@OtherActor func doSomething() {
let x = NonSendable()
Task.init { @MainActor in print(x) }
test(x)
}
```
Long term I would like to get region analysis and transfer non sendable out of
the business of directly interpreting the AST... but if we have to do it now, I
would rather us do it through a helper struct. At least the helper struct can be
modified later to work with additional SIL concurrency support when it is added.
I also eliminated the very basic "why is this task isolated" part of the warning
in favor of the larger, better, region history impl that I am going to land
soon. The diagnostic wasn't that good in the first place and also was fiddly. So
I removed it for now.
rdar://124960994
The reason why I am doing this is that:
1. function_extract_isolation can take as a parameter a non-Sendable function
today in SIL so in such a case, we crash.
2. It returns an Optional<any Actor> which always must be Sendable.
So it makes sense for it to just require that its non-Sendable parameter not be
transferred at that point.
This assert validates that look through parameters only have a single operand
(the one we are going to lookthrough). It did not take into account though that
some of these lookthrough instructions /do/ have type dependent operands (which
we should ignore for the assert). I changed the assert to ignore those.
The specific problem is that instead of just using the parent type of the
ref_element_addr (which is guaranteed to be a class), we used the base of the
storage... the base doesn't have to be the ref_element_addr's operand. The
crasher occured when that base was a class existential that we cast to a super
class whose field we access.
Some notes:
1. If the result is non-Sendable and we didn't infer something that is
transferring, we still emit the current sema error that says that one cannot
assign a non-Sendable value to an async let.
2. When region isolation is enabled, but transferring args and results are
disabled, we leave the async let semantics alone. This means that the async let
closure is still @Sendable and one cannot pass in non-Sendable values to it.
Otherwise, we get off by one errors.
NOTE: I removed the assert that this originally hit since it is possible for us
to perhaps hit other issues and it would be better to just emit a suboptimal
error than crashing. With time, I will probably make it so if we miss we emit a
"compiler couldn't understand error".
rdar://124478890
Now that we actually know the region that non transferrable things belong to, we
can use this information to give a better diagnostic here.
A really nice effect of this is that we now emit that actor isolated parameters
are actually actor isolated instead of task isolated.
In a subsequent commit, this is going to let me begin handling parameters with
actor regions in a nice way (and standardize all of the errors).
This is meant to be a refactoring commit that uses the current tests in tree to
make sure I did it correctly, so no tests need to be updated.
To keep this as an NFC commit, I only modeled initially actor isolated using
this. I am going to make it so that we properly treat global actor isolated
values as actor isolated/etc in a subsequent commit.
When we run RegionAnalysis, since it uses RPO order, we do not visit dead
blocks. This can create a problem when we emit diagnostics since we may merge in
a value into the region that was never actually defined. In this patch, if we
actually visit the block while performing dataflow, I mark a bit in its state
saying that it was live. Then when we emit diagnostics, I do not visit blocks
that were not marked live.
rdar://124042351
Before I couldn't do this since, @sil_isolated was not represented on
partial_applies. Since in the previous commit, I added support to the compiler
to represent this, I can now limit this query so now one can pass an actor
instance outside of its method to a nonisolated non-Sendable partial apply.
Since it is Sendable, it is always safe to do this since we are passing the
actor.
rdar://123881277
Previously, we assumed we would always have a partial_apply. In the case where
we do not capture any values this is not true since we instead have a
thin_to_thick_function.
Just noticed this while trying to write some tests that validated that we were
properly ignoring strict-concurrency features. I put in asserts to validate that
when either of these are enabled, we have strict-concurrency set as well.
Moved out of MemoryLocations.h and merged the implementations of <<,
keeping the version from MemoryLocations with its brackets and commas
available via a flag but defaulting the implementation previously in the
header.
We purposely do not treat a PartitionOpKind::Transfer as a require since that
would cause us to error when we weakly transfer the same parameter multiple
times to the same function. This is safe since all of the function parameters
will be in the same region.
To ensure that this fixed the multiple strong transferring issue (which is
exposed by requiring before transferring), I also had to muck around a little
with how we emit errors to ensure that we emit errors if the transfer
instruction is also the require.
Instead it is a bit on ParamDecl and SILParameterInfo. I preserve the consuming
behavior by making it so that the type checker changes the ParamSpecifier to
ImplicitlyCopyableConsuming if we have a default param specifier and
transferring is set. NOTE: The user can never write ImplicitlyCopyableConsuming.
NOTE: I had to expand the amount of flags that can be stored in ParamDecl so I
stole bits from TypeRepr and added some logic for packing option bits into
TyRepr and DefaultValue.
rdar://121324715
I thought that we would never actually hit this test case, but since we do not
have opaque values this pattern is treated like a projection in certain cases. I
updated the code as appropriate and added a test.
We should make this as a transfer... but this is just temporary until I get
around to it. For now this is always an out parameter, so we should be safe.
I was correct that it is lookthrough, but it has multiple parameters, so the
normal "baked" implementation cannot be used since the "baked" implementation
assumes that any insts it handles has a single operand.
I also made ref_to_unmanaged and unmanaged_to_ref look through. They should have
always been look through, but I believe early on they were marked assign and I
never touched fixed it. To get the test for strong_copy_unmanaged_value to work,
I needed them to obey these semantics so I fixed them at the same time.