Can anyone explain why the following code will result in a circular reference error while compiling?
class Foo {
let closure: ()->()
func someFunc() {}
init(closure: @escaping ()->()) {
self.closure = closure
}
}
class Bar {
lazy var foo = Foo { [weak self] in // Circular Reference error here!
self?.foo.someFunc()
}
}
However if I change it to:
class Bar {
lazy var foo: Foo = {
return Foo { [weak self] in
self?.foo.someFunc()
}
}()
}
then there is no circular reference error anymore.
I'm confused why one would cause an error, and the other would not.
Updated:
The circular reference is in the type inferencing: It's the fact that foo
's type depends on self.foo
's type, which depends on foo
's type, which depends on self.foo
's type etc..
Previous Answer:
I think I figured out the root cause here (Thanks to some of my coworkers!):
My coworker noticed that this code compiles fine, which points out it might be a type inference issue. I was being thrown off by the wrapping closure, which apparently has nothing to do with the real issue.
class Bar {
lazy var foo: Foo = Foo { [weak self] in
self?.foo.someFunc()
}
}
I think the in order for the compiler to evaluate Bar
it must do type inference on the property foo
, which requires the compiler to evaluate the property initialization code. However the property initialization code itself contains a reference to self
/Bar
, so in order for that code to be evaluated, Bar
must be evaluated first. And thus the circular reference.