blob: 5d2f8fba86aa5222b8a6140b52a5a367e5a5f76a [file] [log] [blame]
// RUN: %target-swift-frontend -enable-experimental-forward-mode-differentiation -emit-sil -verify %s
// TODO: move these tests back into `autodiff_diagnostics.swift` once
// forward mode reaches feature parity with reverse mode.
//===----------------------------------------------------------------------===//
// Basic function
//===----------------------------------------------------------------------===//
func one_to_one_0(_ x: Float) -> Float {
return x + 2
}
_ = derivative(at: 0, in: one_to_one_0) // okay!
//===----------------------------------------------------------------------===//
// Function composition
//===----------------------------------------------------------------------===//
func base(_ x: Float) -> Float {
// expected-error @+2 2 {{expression is not differentiable}}
// expected-note @+1 2 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}}
return Float(Int(x))
}
// TODO: Fix nested differentiation diagnostics. Need to fix indirect differentiation invokers.
func nested(_ x: Float) -> Float {
// xpected-note @+1 {{when differentiating this function call}}
return base(x)
}
func middle(_ x: Float) -> Float {
// xpected-note @+1 {{when differentiating this function call}}
return nested(x)
}
func middle2(_ x: Float) -> Float {
// xpected-note @+1 {{when differentiating this function call}}
return middle(x)
}
func func_to_diff(_ x: Float) -> Float {
// xpected-note @+1 {{expression is not differentiable}}
return middle2(x)
}
func calls_diff_of_nested(_ x: Float) -> Float {
// xpected-error @+1 {{function is not differentiable}}
return derivative(at: x, in: func_to_diff)
}
//===----------------------------------------------------------------------===//
// Inout arguments
//===----------------------------------------------------------------------===//
func activeInoutArg(_ x: Float) -> Float {
var a = x
// expected-note @+1 {{cannot differentiate through 'inout' arguments}}
a += x
return a
}
// expected-error @+1 {{function is not differentiable}}
_ = differential(at: .zero, in: activeInoutArg(_:))
func activeInoutArgTuple(_ x: Float) -> Float {
var tuple = (x, x)
// expected-note @+1 {{cannot differentiate through 'inout' arguments}}
tuple.0 *= x
return x * tuple.0
}
// expected-error @+1 {{function is not differentiable}}
_ = differential(at: .zero, in: activeInoutArgTuple(_:))
//===----------------------------------------------------------------------===//
// Non-varied results
//===----------------------------------------------------------------------===//
func one() -> Float {
return 1
}
@differentiable
func nonVariedResult(_ x: Float) -> Float {
// TODO(TF-788): Re-enable non-varied result warning.
// xpected-warning @+1 2 {{result does not depend on differentiation arguments and will always have a zero derivative; do you want to use 'withoutDerivative(at:)'?}} {{10-10=withoutDerivative(at:}}
return one()
}
//===----------------------------------------------------------------------===//
// Subset parameters
//===----------------------------------------------------------------------===//
func nondiff(_ f: @differentiable (Float, @nondiff Float) -> Float) -> Float {
// expected-note @+2 {{cannot differentiate with respect to a '@nondiff' parameter}}
// expected-error @+1 {{function is not differentiable}}
return derivative(at: 2, 3) { (x, y) in f(x * x, y) }
}
//===----------------------------------------------------------------------===//
// Control flow
//===----------------------------------------------------------------------===//
// expected-error @+1 {{function is not differentiable}}
@differentiable
// expected-note @+2 {{when differentiating this function definition}}
// expected-note @+1 {{forward-mode differentiation does not yet support control flow}}
func cond(_ x: Float) -> Float {
if x > 0 {
return x * x
}
return x + x
}