Swift: Self.init is called several times in the initializer

I have me at a standstill. I cannot understand why Swift complains that self.init is called more than once in this code:

public init(body: String) { let parser = Gravl.Parser() if let node = parser.parse(body) { super.init(document: self, gravlNode: node) } else { // Swift complains with the mentioned error on this line (it doesn't matter what "whatever" is): super.init(document: self, gravlNode: whatever) } } 

If something is missing for me, it is very obvious that it only calls init once. Oddly enough, if I comment on the second line, Swift complains that Super.init is not called on all paths, lol.

What am I missing?

Update:

Ok, so the problem was definitely trying to pass self in a super.init call. I completely forgot that I do this, ha. I think I wrote it experimentally and got it for compilation and thought it could really work, but it looks like it’s actually a mistake that it compiled in general.

In any case, since passing self to the initializer is redundant, since it is the same object, I changed the parent initializer to accept an optional document parameter (this is just an internal initializer, so it doesn't really matter), and if it is nil I just set it to self in the parent initializer.

For the curious, this looks like a parent initializer (now):

 internal init(document: Document?, gravlNode: Gravl.Node) { self.value = gravlNode.value super.init() self.document = document ?? self as! Document // other stuff... } 
+5
source share
1 answer

I suspect this is a bad diagnosis (invalid error message). It would be very useful if you had a complete example with which we could experiment, but this line does not make sense (and I suspect that this is the main problem):

  super.init(document: self, gravlNode: node) 

You cannot pass self to super.init . You are not initialized yet (you are not initialized until you call super.init ). For example, consider the following simplified code:

 class S { init(document: AnyObject) {} } class C: S { public init() { super.init(document: self) } } 

This results in error: 'self' used before super.init call , which, in my opinion, is the correct error.

EDIT: I believe that Hamish definitely detected a compiler error. You can use it this way in Xcode 8.3.1 (not yet tested yet 8.3.2):

 class S { var x: Int init(document: S) { self.x = document.x } } class C: S { public init() { super.init(document: self) } } let c = C() // malloc: *** error for object 0x600000031244: Invalid pointer dequeued from free list 
+3
source

Source: https://habr.com/ru/post/1267313/


All Articles