swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.25k stars 10.32k forks source link

[AutoDiff] Compiler crash when attempting to synthesize a derivative via `guard let` Optional unwrapping. #75280

Closed fibrechannelscsi closed 1 month ago

fibrechannelscsi commented 1 month ago

Description

The code below crashes the compiler when attempting to build in Debug or Release mode. The assertion failure is: Assertion failed: (insertion.second && "Adjoint buffer already exists"), function setAdjointBuffer, file PullbackCloner.cpp, line 690. The line number is based on the 2024-07-07a nightly toolchain.

Reproduction

Copy and paste this code into a new project, and build in either Debug or Release mode.

import _Differentiation
@differentiable(reverse) func a<F, A>(_ f: Optional<F>, c: @differentiable(reverse) (F) -> A) -> Optional<A> where F: Differentiable, A: Differentiable
{
    guard let f else {return nil}
    return c(f)
}

Stack dump

1.  Apple Swift version 6.0-dev (LLVM 5ed3fc3f662a007, Swift e2f80064508f3b5)
2.  Compiling with effective version 5.10
3.  While evaluating request ExecuteSILPipelineRequest(Run pipelines { Mandatory Diagnostic Passes + Enabling Optimization Passes } on SIL for aaa)
4.  While running pass #33 SILModuleTransform "Differentiation".
5.  While processing // differentiability witness for a<A, B>(_:c:)
sil_differentiability_witness [serialized] [reverse] [parameters 0] [results 0] <F, A where F : Differentiable, A : Differentiable> @$s16aaa1a_1cq_SgxSg_q_xYjrXEt16_Differentiation14DifferentiableRzAfGR_r0_lF : $@convention(thin) <F, A where F : Differentiable, A : Differentiable> (@in_guaranteed Optional<F>, @guaranteed @differentiable(reverse) @noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <F, A>) -> @out Optional<A> {
}

 on SIL function "@$s16aaa1a_1cq_SgxSg_q_xYjrXEt16_Differentiation14DifferentiableRzAfGR_r0_lF".
 for 'a(_:c:)' (at /Users/user/aaa/main.swift:2:26)
6.  While generating VJP for SIL function "@$s16aaa1a_1cq_SgxSg_q_xYjrXEt16_Differentiation14DifferentiableRzAfGR_r0_lF".
 for 'a(_:c:)' (at /Users/user/aaa/main.swift:2:26)
7.  While generating pullback for SIL function "@$s16aaa1a_1cq_SgxSg_q_xYjrXEt16_Differentiation14DifferentiableRzAfGR_r0_lF".
 for 'a(_:c:)' (at /Users/user/aaa/main.swift:2:26)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x0000000107c6fea8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x0000000107c6e674 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x0000000107c704f0 SignalHandler(int) + 304
3  libsystem_platform.dylib 0x0000000188935a24 _sigtramp + 56
4  libsystem_pthread.dylib  0x0000000188905cc0 pthread_kill + 288
5  libsystem_c.dylib        0x0000000188811a40 abort + 180
6  libsystem_c.dylib        0x0000000188810d30 err + 0
7  swift-frontend           0x0000000107e7441c swift::autodiff::PullbackCloner::Implementation::setAdjointBuffer(swift::SILBasicBlock*, swift::SILValue, swift::SILValue) (.cold.2) + 0
8  swift-frontend           0x0000000103031338 swift::autodiff::PullbackCloner::Implementation::createFunctionLocalAllocation(swift::SILType, swift::SILLocation, bool, std::__1::optional<swift::SILDebugVariable>) + 0
9  swift-frontend           0x000000010303ed10 swift::autodiff::PullbackCloner::Implementation::visitInjectEnumAddrInst(swift::InjectEnumAddrInst*) + 1104
10 swift-frontend           0x0000000103035fac swift::autodiff::PullbackCloner::Implementation::visit(swift::SILInstruction*) + 200
11 swift-frontend           0x0000000103031d98 swift::autodiff::PullbackCloner::Implementation::visitSILBasicBlock(swift::SILBasicBlock*) + 648
12 swift-frontend           0x000000010302efb8 swift::autodiff::PullbackCloner::Implementation::run() + 5416
13 swift-frontend           0x000000010302da58 swift::autodiff::PullbackCloner::run() + 24
14 swift-frontend           0x000000010304d554 swift::autodiff::VJPCloner::Implementation::run() + 1264
15 swift-frontend           0x000000010304dc9c swift::autodiff::VJPCloner::run() + 24
16 swift-frontend           0x00000001031aae14 (anonymous namespace)::DifferentiationTransformer::canonicalizeDifferentiabilityWitness(swift::SILDifferentiabilityWitness*, swift::autodiff::DifferentiationInvoker, swift::SerializedKind_t) + 6020
17 swift-frontend           0x00000001031a8cb8 (anonymous namespace)::Differentiation::run() + 1060
18 swift-frontend           0x00000001032514dc swift::SILPassManager::runModulePass(unsigned int) + 856
19 swift-frontend           0x00000001032538d4 swift::SILPassManager::execute() + 624
20 swift-frontend           0x000000010324e15c swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 72
21 swift-frontend           0x000000010324e0dc swift::ExecuteSILPipelineRequest::evaluate(swift::Evaluator&, swift::SILPipelineExecutionDescriptor) const + 68
22 swift-frontend           0x000000010329d9dc swift::SimpleRequest<swift::ExecuteSILPipelineRequest, std::__1::tuple<> (swift::SILPipelineExecutionDescriptor), (swift::RequestFlags)1>::evaluateRequest(swift::ExecuteSILPipelineRequest const&, swift::Evaluator&) + 28
23 swift-frontend           0x000000010326aa58 swift::ExecuteSILPipelineRequest::OutputType swift::Evaluator::getResultUncached<swift::ExecuteSILPipelineRequest, swift::ExecuteSILPipelineRequest::OutputType swift::evaluateOrFatal<swift::ExecuteSILPipelineRequest>(swift::Evaluator&, swift::ExecuteSILPipelineRequest)::'lambda'()>(swift::ExecuteSILPipelineRequest const&, swift::ExecuteSILPipelineRequest::OutputType swift::evaluateOrFatal<swift::ExecuteSILPipelineRequest>(swift::Evaluator&, swift::ExecuteSILPipelineRequest)::'lambda'()) + 204
24 swift-frontend           0x000000010324e338 swift::executePassPipelinePlan(swift::SILModule*, swift::SILPassPipelinePlan const&, bool, swift::irgen::IRGenModule*) + 64
25 swift-frontend           0x000000010327fd04 swift::runSILDiagnosticPasses(swift::SILModule&) + 192
26 swift-frontend           0x0000000102a84d34 swift::CompilerInstance::performSILProcessing(swift::SILModule*) + 80
27 swift-frontend           0x0000000102842894 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 796
28 swift-frontend           0x0000000102841f54 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 656
29 swift-frontend           0x000000010284dcf4 withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>, bool) + 160
30 swift-frontend           0x0000000102843e38 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 708
31 swift-frontend           0x000000010284350c swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2344
32 swift-frontend           0x000000010264cdb0 swift::mainEntry(int, char const**) + 3112
33 dyld                     0x00000001885850e0 start + 2360

Expected behavior

The compilation should succeed.

Environment

This compiles with a much older toolchain: 2023-07-10a. This fails with both 2023-12-07a and the more recent 2024-07-07a. This also fails with both the most recent 2024-07-15a nightly and 6.0 snapshot.

Additional information

Specifying a derivative manually will cause the compilation to succeed on an affected toolchain. For example, if we add:

@derivative(of: a, wrt: (f)) func e<F, A>(f: Optional<F>, c: @differentiable(reverse) (F) -> A) ->
(value: Optional<A>, pullback: (Optional<A>.TangentVector) -> (Optional<F>.TangentVector)) {
    return (value: a(f, c: c), pullback: { tangentVector in return (.init(nil))})
}

then the compilation will succeed.

fibrechannelscsi commented 1 month ago

@asl