The code below generates a runtime EXC_BAD_ACCESS when executed.
Reproduction
Copy and paste the following code into a new project, and build in Debug mode.
import Foundation; import _Differentiation
public protocol N {}
public protocol H: Differentiable {}
public protocol D: H & N where Self.TangentVector: N {}
public struct O<V> {var v: V}
extension O: Differentiable where V: Differentiable {}
public extension N {var d: [String : PartialKeyPath<Self>] {return self.e(i: self) as! [String : PartialKeyPath<Self>]}}
public extension H {var z: TangentVector {Self.TangentVector.zero}}
public struct R: D {public var a: Double = 7}
public struct B<F, G> {
@noDerivative public internal(set) var s: [String : WritableKeyPath<F, G>]
@noDerivative public var a: Set<WritableKeyPath<F, G>> {var a = Set<WritableKeyPath<F, G>>(); a.insert(self.s.values.first!); return a}
public init<S: Sequence>(to: S) where S.Element == WritableKeyPath<F, G> {self.s = ["0" : \R.a] as! [String : WritableKeyPath<F, G>]}
@differentiable(reverse where F: D, G: Differentiable) public func o(f i: F) -> O<G> {
var y: [G] = []
for k in self.a {y = y + [p(i, at: k)]}
var b = [O<G>]()
for i in 0 ..< withoutDerivative(at: y.count) {
b.append(O<G>(v: y[i]))
// b = b + [O<G>(v: y[i])]
}
if withoutDerivative(at: b.count) > 1 {return O<G>(v: b[0].v)}
else {return O<G>(v: y[0])}
}
}
@inlinable @differentiable(reverse where W: D, M: Differentiable) public func p<W, M>(_ o: W, at j: WritableKeyPath<W, M>) -> M {return o[keyPath: j]}
@inlinable @derivative(of: p) public func vjpP<O, M>(_ o: O, at m: WritableKeyPath<O, M>) -> (value: M, pullback: (M.TangentVector) -> O.TangentVector) where O: D, M: Differentiable
{
var z = o.z
let r = o.d.mapValues { $0 as? WritableKeyPath<O, M> }.compactMapValues { $0 }.filter { $0.value == m }.compactMap { $0.key }
let u = z.d.filter {r.first! == $0.key}.values.map { $0 } as! [WritableKeyPath<O.TangentVector, M.TangentVector>]
return (value: o[keyPath: m], pullback: { d in z[keyPath: u.first!] = d; return z})
}
extension N {func e(i: any N) -> [String : AnyKeyPath] {if g == 0 {g += 1; return ["a": \R.a]}; return ["a" : \R.TangentVector.a]}}
var g = 0;
let b = R(a: 9)
@differentiable(reverse) func s(b: R) -> Double {return B<R, Double>(to: [\R.a]).o(f: b).v * 3}
print(valueWithGradient(at: b, of: s))
If run in Xcode, the error will be highlighted in line 19, which contains b.append(O<G>(v: y[i])). Here, it will indicate an "index out of range" error.
If built via swift build and executed in lldb, an EXC_BAD_ACCESS will be triggered with an attempt to access 0x0. The stack trace for this is listed below.
Expected behavior
The program should print:
(value: 27.0, gradient: i2.R.TangentVector(a: 3.0))
and exit with an exit code of 0.
Here, i2 is the name of the current project.
Environment
M1 Mac
Every toolchain I've tried exhibits this, from 2023-07-10a nightly all the way to 2024-05-01a. I can even reproduce this with the 6.0 2024-04-29a snapshot.
Additional information
Stack trace when run in lldb. Note that the executable is simply called a.
Description
The code below generates a runtime
EXC_BAD_ACCESS
when executed.Reproduction
Copy and paste the following code into a new project, and build in Debug mode.
If run in Xcode, the error will be highlighted in line 19, which contains
b.append(O<G>(v: y[i]))
. Here, it will indicate an "index out of range" error. If built viaswift build
and executed inlldb
, anEXC_BAD_ACCESS
will be triggered with an attempt to access0x0
. The stack trace for this is listed below.Expected behavior
The program should print:
(value: 27.0, gradient: i2.R.TangentVector(a: 3.0))
and exit with an exit code of 0. Here,i2
is the name of the current project.Environment
M1 Mac Every toolchain I've tried exhibits this, from 2023-07-10a nightly all the way to 2024-05-01a. I can even reproduce this with the 6.0 2024-04-29a snapshot.
Additional information
Stack trace when run in
lldb
. Note that the executable is simply calleda
.If we perform the append operation via
b = b + [O<G>(v: y[i])]
, which is commented out in line 20, then the runtime error will not occur.