Skip to content

Compiler assertion failure when attempting to use throwing functions inside a function passed to valueWithGradient(at: of:). #63331

@fibrechannelscsi

Description

@fibrechannelscsi

Description
The compiler crashes with an assertion failing when attempting to use throwing functions inside a function passed to valueWithGradient(at: of:).

Steps to reproduce
Paste the code below into a new project and attempt to compile it.

import Foundation
import _Differentiation
public struct SomeDifferentiableStruct: Differentiable {
    var a: Double = 0.0
    @noDerivative
    var bool: Bool = false
}
public protocol Cacheable
{
    mutating func setCache<V>(to value: V) throws
    func writeCache<R>(to root: inout R) throws
}
public struct Cacher<Root, Value: Equatable>: Cacheable
{
    public mutating func setCache<V>(to value: V) throws {}
    public func writeCache<R>(to root: inout R) throws {}
}
public func someFunction() throws {
    let aStruct = SomeDifferentiableStruct()
    var cacher = Cacher<SomeDifferentiableStruct, Double>()
    func setAndWrite(aStruct: SomeDifferentiableStruct, newValue: Double) -> Double {
        var aStruct = aStruct
        let newValue = newValue * 3.0
        try! cacher.setCache(to: newValue)
        try! cacher.writeCache(to: &aStruct)
        return aStruct.a
    }
    let valAndGrad = valueWithGradient(at: aStruct, 7.0, of: setAndWrite)
}

The failing assertion is:
Assertion failed: (hasVal), function value, file Optional.h, line 209.

Stack trace:

1.	Apple Swift version 5.9-dev (LLVM c48958355f7507c, Swift f26f810cc8406ef)
2.	Compiling with the current language version
3.	While evaluating request ExecuteSILPipelineRequest(Run pipelines { Mandatory Diagnostic Passes + Enabling Optimization Passes } on SIL for Project)
4.	While running pass #299 SILModuleTransform "Differentiation".
5.	While canonicalizing `differentiable_function` SIL node   %25 = differentiable_function [parameters 0 1] [results 0] %24 : $@callee_guaranteed (SomeDifferentiableStruct, Double) -> Double // users: %46, %26
6.	While ...in SIL function "@$s9Project12someFunctionyyKF".
 for 'someFunction()' (at /Users/user/playground/Project/Project/main.swift:18:8)
7.	While processing // differentiability witness for setAndWrite #1 (aStruct:newValue:) in someFunction()
sil_differentiability_witness private [reverse] [parameters 0 1] [results 0] @$s9Project12someFunctionyyKF11setAndWriteL_7aStruct8newValueSdAA018SomeDifferentiableH0V_SdtF : $@convention(thin) (SomeDifferentiableStruct, Double, @guaranteed { var Cacher<SomeDifferentiableStruct, Double> }) -> Double {
}

 on SIL function "@$s9Project12someFunctionyyKF11setAndWriteL_7aStruct8newValueSdAA018SomeDifferentiableH0V_SdtF".
 for 'setAndWrite(aStruct:newValue:)' (at /Users/user/playground/Project/Project/main.swift:21:5)
8.	While generating VJP for SIL function "@$s9Project12someFunctionyyKF11setAndWriteL_7aStruct8newValueSdAA018SomeDifferentiableH0V_SdtF".
 for 'setAndWrite(aStruct:newValue:)' (at /Users/user/playground/Project/Project/main.swift:21:5)
9.	While generating pullback for SIL function "@$s9Project12someFunctionyyKF11setAndWriteL_7aStruct8newValueSdAA018SomeDifferentiableH0V_SdtF".
 for 'setAndWrite(aStruct:newValue:)' (at /Users/user/playground/Project/Project/main.swift:21:5)
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           0x00000001071415c8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x000000010714084c llvm::sys::RunSignalHandlers() + 128
2  swift-frontend           0x0000000107141c08 SignalHandler(int) + 304
3  libsystem_platform.dylib 0x000000018d1314c4 _sigtramp + 56
4  libsystem_pthread.dylib  0x000000018d119ee0 pthread_kill + 288
5  libsystem_c.dylib        0x000000018d054340 abort + 168
6  libsystem_c.dylib        0x000000018d053754 err + 0
7  swift-frontend           0x0000000107278eec swift::autodiff::PullbackCloner::Implementation::getAdjointBuffer(swift::SILBasicBlock*, swift::SILValue) (.cold.1) + 0
8  swift-frontend           0x0000000102e6f7f0 swift::autodiff::PullbackCloner::Implementation::getTangentValueCategory(swift::SILValue) + 264
9  swift-frontend           0x0000000102e6d3f8 swift::autodiff::PullbackCloner::Implementation::run() + 2660
10 swift-frontend           0x0000000102e6c968 swift::autodiff::PullbackCloner::run() + 24
11 swift-frontend           0x0000000102e88058 swift::autodiff::VJPCloner::Implementation::run() + 1368
12 swift-frontend           0x0000000102e88644 swift::autodiff::VJPCloner::run() + 24
13 swift-frontend           0x0000000102f91b7c (anonymous namespace)::DifferentiationTransformer::canonicalizeDifferentiabilityWitness(swift::SILDifferentiabilityWitness*, swift::autodiff::DifferentiationInvoker, swift::IsSerialized_t) + 5328
14 swift-frontend           0x0000000102f95734 (anonymous namespace)::DifferentiationTransformer::promoteToDifferentiableFunction(swift::DifferentiableFunctionInst*, swift::SILBuilder&, swift::SILLocation, swift::autodiff::DifferentiationInvoker) + 7972
15 swift-frontend           0x0000000102f91e3c (anonymous namespace)::DifferentiationTransformer::processDifferentiableFunctionInst(swift::DifferentiableFunctionInst*) + 580
16 swift-frontend           0x0000000102f8fe24 (anonymous namespace)::Differentiation::run() + 1268
17 swift-frontend           0x00000001030170b0 swift::SILPassManager::runModulePass(unsigned int) + 984
18 swift-frontend           0x000000010301cd8c swift::SILPassManager::execute() + 624
19 swift-frontend           0x00000001030140bc swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 68
20 swift-frontend           0x0000000103014044 swift::ExecuteSILPipelineRequest::evaluate(swift::Evaluator&, swift::SILPipelineExecutionDescriptor) const + 68
21 swift-frontend           0x00000001030375e8 swift::SimpleRequest<swift::ExecuteSILPipelineRequest, std::__1::tuple<> (swift::SILPipelineExecutionDescriptor), (swift::RequestFlags)1>::evaluateRequest(swift::ExecuteSILPipelineRequest const&, swift::Evaluator&) + 28
22 swift-frontend           0x00000001030208e4 llvm::Expected<swift::ExecuteSILPipelineRequest::OutputType> swift::Evaluator::getResultUncached<swift::ExecuteSILPipelineRequest>(swift::ExecuteSILPipelineRequest const&) + 252
23 swift-frontend           0x00000001030142b8 swift::executePassPipelinePlan(swift::SILModule*, swift::SILPassPipelinePlan const&, bool, swift::irgen::IRGenModule*) + 84
24 swift-frontend           0x000000010302406c swift::runSILDiagnosticPasses(swift::SILModule&) + 92
25 swift-frontend           0x00000001029cff94 swift::CompilerInstance::performSILProcessing(swift::SILModule*) + 68
26 swift-frontend           0x000000010286619c 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*) + 716
27 swift-frontend           0x000000010286592c swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 576
28 swift-frontend           0x000000010287463c withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>, bool) + 160
29 swift-frontend           0x000000010286761c swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3204
30 swift-frontend           0x00000001026bd414 swift::mainEntry(int, char const**) + 3304
31 dyld                     0x000000010fecd088 start + 516

Expected behavior
The compiler should generate an error message indicating the current lack of support (if any) of such throwing functions in a differentiable context. If throws like this are supported sometime in the future, then the compilation should succeed.

Environment
Swift compiler version info:
Toolchains from 2022-05-23a to 2023-01-19a appear to be broken. Note that the error information above was retrieved from a build attempted on the 2023-01-19a toolchain.
Xcode 13.3, Build version 13E113
Deployment target: M1

Additional context
If we remove the requirement that setCache() and writeCache() throw, then the compiler will not crash, but will indicate that the function is not differentiable (in the line containing valueWithGradient().

Metadata

Metadata

Assignees

No one assigned

    Labels

    AutoDiffbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfcrashBug: A crash, i.e., an abnormal termination of softwareerror handlingswift 5.9type checkerArea → compiler: Semantic analysis

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions