Otherwise, we will assume that an async let autoclosure infers isolation from
its DeclContext... which we do not want. An async let autoclosure should always
be nonisolated + sending.
The diagnostic change that I mentioned in the header is that we were emitting
unfortunate "sending task or actor isolated could result in races" error. I
eliminated this by adding a new diagnostic for transfer non transferrable errors
happening in autoclosures. So now we emit this:
```swift
func asyncLetInferAsNonIsolated<T : Actor>(
isolation actor: isolated T
) async throws {
async let subTask: Void = {
await useValueAsyncNoReturnWithInstance(self, actor)
// expected-warning @-1:47 {{sending 'self' risks causing data races}}
// expected-note @-2 {{sending 'actor'-isolated 'self' into async let risks causing data races between nonisolated and 'actor'-isolated uses}}
}()
await subTask
```
I also noticed that we did not have enough test cases for autoclosures in
general so I also added a bunch of tests just so we can see what the current
behavior is. I think there are a few issues therein (I believe some may have
been reported due to '??').
rdar://130151318
This is triggered by the test case in the next commit. The problem is anonymous
closures can be passed here and they do not have a ValueDecl so there isn't a
decl for us to use.
Otherwise IRGen would crash.
It needs a bit of work to support alloc_box of generic non-copyable structs/enums with deinit, because we need to specialize the deinit functions, though they are not explicitly referenced in SIL.
Until this is supported, give an error in such cases.
Fixes a compiler crash in IRGen
rdar://130283111
We are already using this routine in other parts of TransferNonSendable to
ensure that we look through common insts that SILGen inserts that do not change
the actual underlying actor instance that we are using. In this case, I added
support for casts, optional formation, optional extraction, existential ref
initialization.
As an example of where this came up is the following test case where we fail to
look through an init_existential_ref.
```swift
public actor MyActor {
private var intDict: [Int: Int] = [:]
public func test() async {
await withTaskGroup(of: Void.self) { taskGroup in
for (_, _) in intDict {}
await taskGroup.waitForAll() // Isolation merge failure happens here
}
}
}
```
I also added the ability to at the SIL level actual test out this merge
condition using the analysis test runner. I used this to validate that this
functionality works as expected in a precise way.
rdar://130113744
Before we wouldn't print them in all situations and even more so a few of the
printing routines did not have it at all. This just adds a centralized
SILIsolationInfo::dumpOptions() method and then goes through all of the printing
helpers and changes them to use them as appropriate.
Given a function or a partial_apply with an isolated parameter, we do not know
immediately what the actual isolation is of the function or partial_apply since
we do not know which instance will be applied to the function or partial_apply.
In this commit, I introduce a new bit into SILIsolationInfo that tracks this
information upon construction and allows for it to merge with ownership that has
the appropriate type and a specific instance. Since the values that created the
two isolations, will be in the same region this should ensure that the value is
only ever in a flow sensitive manner in a region with only one actor instance
(since regions with isolations with differing actor instances are illegal).
Before this change in the following code, we would say that message is isolated to the actor instead of the global actor isolation of the actor's method:
```swift
class Message { ... }
actor MessageHolder {
@MainActor func hold(_ message: Message) { ... }
}
@MainActor
func sendMessage() async {
let messageHolder = MessageHolder()
let message = Message()
// We identified messageHolder.hold as being MessageHolder isolated
// instead of main actor isolated.
messageHolder.hold(message)
Task { @MainActor in print(message) }
}
```
I also used this as an opportunity to simplify the logic in this part of the
code. Specifically, I had made it so that multiple interesting cases were
handled in the same conditional statement in a manner that it made it hard to
know which cases were actually being handled and why it was correct. Now I split
that into two separate if statements with comments that make it clear what we
are actually trying to pattern match against.
rdar://130980933
Replace the assert-check if a vtable is available with a regular error message.
This cannot occur in regular builds - only if built with embedded swift and without wmo.
The command line compiler prevents this combination, but it can happen in SourceKit.
rdar://130167087
Specifically:
1. We error now if one transfers an 'inout sending' parameter and does not
reinitialize it before the end of the function.
2. We error now if one merges an 'inout sending' parameter into an actor
isolated region and do not reinitialize it with a non-actor isolated value
before the end of the function.
rdar://126303739
The reason why I am doing this is that I am adding support for failing to
reinitialize an inout sending parameter that was transferred. To make it really
easy to do I am just going to explicitly represent this on the RequireInst and
let the decision on what diagnostic to be done to be represented in the
pseudo-IR instead of trying to just infer it straight from the type of require
inst. This keeps all of the logic in the same place and attempts to keep the
diagnostic emitter not use logic and instead just emit.
This is NFC so I can make sure that things work before adding the additional code.
This was causing us to emit old style diagnostics in certain cases.
Just doing a walk through of the diagnostics and fixing issues while I
am here sprucing up sending diagnostics.
rdar://130915737
This asserts only option is an option to make it quicker/easier to triage
unknown pattern match errors by aborting when we emit it (allowing one to
immediately drop into the debugger at that point).
Previously, it only happened for errors in RegionAnalysis not in
TransferNonSendable itself.
SILInstruction::clone doesn't know how to clone instructions that produce
the archetype uuid. SILCloner is equipped to handle such instructions.
Optimizations like LoopRotate use SILInstruction::clone and will be
incorrect for such instructions.
rdar://130047619