Skip to content

Compiler crash on main (6.5-dev): SIL verification error (debug_value undef) on Mutex captured in nested Task inside task group #90211

Description

@sebsto

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()
swift build

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    SILSIL ownershipArea → compiler → SIL: SIL ownershipconcurrencyFeature: umbrella label for concurrency language featuresswift 6.5-dev

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions