Overview
swift-frontend crashes (SIL verification failure) on current main (6.5-dev) when compiling an async throws function that, inside a task group child task, runs a for loop whose body spawns a Task capturing both the loop variable and a Mutex declared in the enclosing scope. The same code compiles fine on 6.4.
The verifier rejects a debug_value instruction referencing undef for the captured Mutex:
debug_value [moveable_value_debuginfo] undef : ${ let Mutex<Int> }, let, name "counter", type $Mutex<Int>
Reproduce
// swift-tools-version:6.0 ; swiftLanguageMode(.v6)
import Synchronization
func outer() async throws {
try await withThrowingTaskGroup(of: Void.self) { group in
group.addTask {
let counter = Mutex<Int>(0)
for i in 1...5 {
let task = Task { @Sendable in
do {
try await Task.sleep(for: .seconds(1))
_ = i
} catch is CancellationError {
counter.withLock { $0 += 1 }
}
}
_ = task
}
_ = counter.withLock { $0 }
}
try await group.next()
}
}
try await outer()
Both captures are required to trigger it: removing the Mutex capture, the loop-variable capture, or the surrounding task group all make the crash disappear.
Crash
1. Swift version 6.5-dev (LLVM 18d2bfb70c14d89, Swift c13d82e5987aecb)
3. While evaluating request ExecuteSILPipelineRequest(... Rest of Onone ...)
4. While running pass #137 SILModuleTransform "OwnershipModelEliminator".
5. Found verification error when verifying before lowering ownership.
6. While verifying SIL function "@$s8CrashMin5outeryyYaKFyScgyyts5Error_pGzYaKXEfU_yyYacfU_".
...
#8 SILVerifierBase<SILVerifier>::visitDebugValueInst(swift::DebugValueInst*)
#9 SILVerifier::visitSILBasicBlock(swift::SILBasicBlock*)
#11 OwnershipModelEliminator::run()
*** Signal 6: Aborted ***
The offending SIL (the captured Mutex box becomes undef before OwnershipModelEliminator):
undef<${ let Mutex<Int> }>
-> debug_value [moveable_value_debuginfo] undef : ${ let Mutex<Int> }, let, name "counter", type $Mutex<Int>
%5 = alloc_box ${ let Mutex<Int> }, let, name "counter"
%84 = function_ref @...U_yyYaYbKcfU_ : $@convention(thin) @Sendable @async @substituted <τ_0_0> (@guaranteed Optional<any Actor>, Int, @guaranteed { let Mutex<Int> }) -> ...
Expected
Compiles without crashing, as on 6.4.
Environment
| Toolchain |
Result |
swiftlang/swift:nightly-main-jammy (6.5-dev, LLVM 18d2bfb, Swift c13d82e) |
crash (SIGABRT) |
swiftlang/swift:nightly-6.4.x-jammy (6.4-dev) |
builds successfully |
Targets aarch64-unknown-linux-gnu. Originally hit in CI for awslabs/swift-aws-lambda-runtime#567, where it crashed compiling a test using this pattern.
Overview
swift-frontendcrashes (SIL verification failure) on currentmain(6.5-dev) when compiling anasync throwsfunction that, inside a task group child task, runs aforloop whose body spawns aTaskcapturing both the loop variable and aMutexdeclared in the enclosing scope. The same code compiles fine on 6.4.The verifier rejects a
debug_valueinstruction referencingundeffor the capturedMutex:Reproduce
Both captures are required to trigger it: removing the
Mutexcapture, the loop-variable capture, or the surrounding task group all make the crash disappear.Crash
The offending SIL (the captured
Mutexbox becomesundefbeforeOwnershipModelEliminator):Expected
Compiles without crashing, as on 6.4.
Environment
swiftlang/swift:nightly-main-jammy(6.5-dev, LLVM18d2bfb, Swiftc13d82e)swiftlang/swift:nightly-6.4.x-jammy(6.4-dev)Targets
aarch64-unknown-linux-gnu. Originally hit in CI for awslabs/swift-aws-lambda-runtime#567, where it crashed compiling a test using this pattern.