Currently the Swift compiler makes these instructions with SILLocations marked
as autgenerated. While this allows for somewhat smoother stepping in some cases,
it can also make some debugging tasks harder due to missing source location
information, for example, when attributing memory allocations.
This patch makes these locations available again, based on that a debug info
consumer could consider filtering them out by recognizing that a source location
is on the opening `{` of a closure, but inside the scope of the function the
closure is defined in.
rdar://127095833
We now compute captures of functions and default arguments
lazily, instead of as a side effect of primary file checking.
Captures of closures are computed as part of the enclosing
context, not lazily, because the type checking of a single
closure body is not lazy.
This fixes a specific issue with the `-experimental-skip-*` flags,
where functions declared after a top-level `guard` statement are
considered to have local captures, but nothing was forcing these
captures to be computed.
Fixes rdar://problem/125981663.
To avoid breaking early adopters of this feature, accept attempts to `return`
a `let` binding in a noncopyable `switch` when it would be treated as a
borrow normally, with a warning that this behavior will change soon.
rdar://126775241
There's an unfortunate layering difference in the cleanup order between address-only
and loadable error values during `catch` pattern matching: for address-only values,
the value is copied into a temporary stack slot, and the stack slot is cleaned up
on exit from the pattern match, meaning the value must be moved into the error return
slot on the "no catch" case before cleanups run. But if it's a loadable value, then
we borrow it for the duration of the switch, and the borrow is released during cleanup
on exit from the pattern match, so the value must be forwarded after running cleanups.
The way the code is structured, it handles these cases properly when the convention of
the function being emitted is in sync with the fundamental properties of the error type
(when the error type is loadable and the error return is by value, or when the error
type is address-only and the error return is indirect, in other words). But when
a closure literal with a loadable error type is emitted in an argument context that
expects a function with an indirect error return, we would try to forward the loadable
error value into the error return slot while a borrow is still active on it, leading
to verifier errors. Defer forwarding the value into memory until after cleanups are
popped, fixing rdar://126576356.
A tidier solution might be to always emit the function body to use a bbarg on the
throw block to pass the error value from the body emission to the epilog when the
type is loadable, deferring the move into memory to the epilog block. This would
make the right behavior fall out of the existing implementation, but would require
a bit more invasive changes (pretty much everywhere that checks IndirectErrorReturn
would need to check a different-tracked AddressOnlyErrorType bit instead or in
addition). This change is more localized.
The fix for #72484 didn't properly handle the case of a "generic" context
where all the type parameters had concrete assignments. In this situation,
F.mapTypeIntoContext does not work because the function has no generic
environment.
Fixes rdar://126085573
Later analyses are too conservative to remove a copy, but it should be fairly safe to
elide the copy for noncopyable globals, since accesses are tightly scoped and dynamically checked,
so consumes aren't possible, and borrows and inout accesses of mutable globals are dynamically
guarded and not subject to exclusivity checks. rdar://114329759
It works well enough now that it should be an acceptable replacement for both
borrowing and consuming switches that works in more correct situations than the
previous implementation. This does however expose a few known issues that I'll
try to fix in follow ups:
- overconsumes cause verifier errors instead of raising diagnostics (rdar://125381446)
- cases with multiple pattern labels aren't yet supported (rdar://125188955)
- copyable types with the `borrowing` or `consuming` modifiers should probably use
noncopyable pattern matching.
The `BorrowingSwitch` flag is still necessary to enable the surface-level syntax
changes (switches without `consume` and the `_borrowing` modifier, for instance).
enabled. If two modules are in the same package and package cmo is enabled,
v-table or witness-table calls should not be generated at the use site in the
client module. Modified conformance serialization check to allow serializing
witness thunks.
Also reordered SIL functions bottom-up so the most nested referenced functions
can be serialized first. Allowed serializing a function if a shared definition
(e.g. function `print`). Added a check for resilient mode wrt struct instructions.
Added tests for SIL tables and resilient mode on/off.
rdar://124632670
Builds on https://github.com/apple/swift/pull/72286.
Use a more forgiving strategy when handling potentially invalid conformances
during SILGen. Conformances may be erroneously marked invalid during witness
resolution, even when they can still be successfully emitted, so we can't bail
out of witness table emission if the invalid bit is set. Instead, just ignore
placeholders and missing methods in the witness table emitter and trust that if
an error was diagnosed during resolution that compilation will be aborted.
Resolves rdar://125947349
This diagnostic is useful around silgen_name where it validates that we do not
have any weird collisions. Sadly, it just points where one of the conflicting
elements is... with this patch, we also emit an error on the other function if
we have a SILLocation.
When erasing a pseudogeneric value in SILGen, we actually treat
the value as if it had the type `any AnyObject`, while in Sema,
it's an archetype. This requires SILGen to look up conformances
again instead of using the ones in the ErasureExpr.
I fixed a bunch of small issues around here that resulted in a bunch of radars
being fixed. Specifically:
1. I made it so that we treat function_refs that are from an actor isolated
function as actor isolated instead of sendable.
2. I made it so that autoclosures which return global actor isolated functions
are treated as producing a global actor isolated function.
3. I made it so that we properly handle SILGen code patterns produced by
Sendable GlobalActor isolated things.
rdar://125452372
rdar://121954871
rdar://121955895
rdar://122692698
If an expression refers to noncopyable storage, then default to performing
a borrowing switch, where `let` bindings in patterns borrow out of the
matched value. If an expression refers to a temporary value or explicitly
uses the `consume` keyword, then perform a consuming switch, where
`let` bindings take ownership of corresponding parts of the matched value.
Allow `_borrowing` to still be used to explicitly bind a pattern variable
as a borrow, with no-implicit-copy semantics for copyable values.
* Allow normal function results of @yield_once coroutines
* Address review comments
* Workaround LLVM coroutine codegen problem: it assumes that unwind path never returns.
This is not true to Swift coroutines as unwind path should end with error result.
This issue can come up when a value is initially statically disconnected, but
after we performed dataflow, we discovered that it was actually actor isolated
at the transfer point, implying that we are not actually transferring.
Example:
```swift
@MainActor func testGlobalAndGlobalIsolatedPartialApplyMatch2() {
var ns = (NonSendableKlass(), NonSendableKlass())
// Regions: (ns.0, ns.1), {(mainActorIsolatedGlobal), @MainActor}
ns.0 = mainActorIsolatedGlobal
// Regions: {(ns.0, ns.1, mainActorIsolatedGlobal), @MainActor}
// This is not a transfer since ns is already main actor isolated.
let _ = { @MainActor in
print(ns)
}
useValue(ns)
}
```
To do this, I also added to SILFunction an actor isolation that SILGen puts on
the SILFunction during pre function visitation. We don't print it or serialize
it for now.
rdar://123474616
Failing to map the type of an isolation capture into context
caused assertions in type lowering. Fixes the build of the
swift-distributed-actors package.
The runtime function `swift_willThrowTyped` takes its argument
`@in_guaranteed`. In opaque values SIL, that's passed directly. Don't
store non-address errors before passing them to the function.
I'm not sure there's any way to test this right now. We don't naturally
emit multiple function conversions on a single operand, and the only way
to get a similar effect is to coerce, which interrupts the application of
`@_inheritActorContext`. So I think this is dead code until we add closure
isolation controls, and even then it might be dead unless we allow coercion
of isolated closures, which maybe we won't. But it's the right thing to do
in the abstract, and I was thinking of it now.
This allows us to propagate abstraction patterns from optional parameters
all the way to closure emission, which optimizes some code patterns but
(more importantly) propagates our knowledge that we're converting to an
`@isolated(any)` function type down to closure emission, allowing us to
set the isolation correctly.
There are still some conversion cases missing --- if we can't combine
conversions for whatever reason, we should at least shift our knowledge
that we need to produce an `@isolated(any)` type down, the same way that
we shift it when emitting a closure that we can't directly emit in the
target abstraction pattern. But this completes the obvious cases of
peepholing for closure emission.