Some more context: TF-123 tracks this issue.
Simple reproducer (calling print involves opaque abstraction patterns because it has Any arguments):
let fn: @differentiable (Float) -> (Float) = { $0 }
print(fn)
// SIL verification failed: Unexpected JVP function type: expectedJVPType == jvpType
// Actual (1) vs expected (2):
// (sil_function_type type=@callee_guaranteed (@in_guaranteed Float) -> @out (Float, @callee_guaranteed (@in_guaranteed Float) -> @out Float))
// (sil_function_type type=@callee_guaranteed (@in_guaranteed Float) -> (@out Float, @owned @callee_guaranteed (@in_guaranteed Float) -> @out Float))
Testing SGF.getTypeLowering with opaque abstraction pattern + normal tuple-returning function-typed value: there doesn't appear to be a problem.
let fn2: (Float) -> (Float, Float) = { ($0, $0) }
print(fn2)
// (Function)
-emit-silgen reveals fn2 is being thunked to a maximally indirect (@in_guaranteed Float) -> @out (Float, Float) value:
// thunk for @escaping @callee_guaranteed (@unowned Float) -> (@unowned Float, @unowned Float)
sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$sS3fIegydd_S2f_SftIegnr_TR : $@convention(thin) (@in_guaranteed Float, @guaranteed @callee_guaranteed (Float) -> (Float, Float)) -> @out (Float, Float) {
// %0 // users: %5, %4
// %1 // user: %3
// %2 // user: %6
bb0(%0 : $*(Float, Float), %1 : $*Float, %2 : @guaranteed $@callee_guaranteed (Float) -> (Float, Float)):
%3 = load [trivial] %1 : $*Float // user: %6
%4 = tuple_element_addr %0 : $*(Float, Float), 0 // user: %9
%5 = tuple_element_addr %0 : $*(Float, Float), 1 // user: %10
%6 = apply %2(%3) : $@callee_guaranteed (Float) -> (Float, Float) // user: %7
(%7, %8) = destructure_tuple %6 : $(Float, Float) // users: %9, %10
store %7 to [trivial] %4 : $*Float // id: %9
store %8 to [trivial] %5 : $*Float // id: %10
%11 = tuple () // user: %12
return %11 : $() // id: %12
} // end sil function '$sS3fIegydd_S2f_SftIegnr_TR'
So the @differentiable function thunking problem appears to be just a type calculation inconsistency between (1) and (2). Changing (2) to be maximally indirect like (1) should fix the issue, but I wonder if there are alternatives.