Fatal error could not demangle keypath type

«  Fix sudo /etc/sudoers is owned by uid 502 Error
Cycle detection  »

When I tried to implement some KVO pattern in my personal project, I got some interesting error: Fatal Error: Could not demangle keypath type from xxx.

The test code is:

class A {
    static let valueDidChange = Notification.Name("valueDidChange")
        
    var val: String {
        willSet {
            NotificationCenter.default.post(name: Self.valueDidChange, object: self, userInfo: [\Self.val: newValue])
        }
    }
    
    init(val: String) {
        self.val = val
    }
}

class B {
    var observer: NSObjectProtocol?
    
    var a: A
    @objc dynamic var val: String
    
    init(a: A) {
        self.a = a
        self.observer = NotificationCenter.default.addObserver(forName: A.valueDidChange, object: nil, queue: nil, using: { [weak self] notice in
            self?.val = notice.userInfo?[\A.val] as? String ?? ""
        })
    }
}

For fixing this issue, if I change A.val willSet part as ⬇️, it will pass.

var val: String {
	willSet {
		NotificationCenter.default.post(name: A.valueDidChange, object: self, userInfo: [\A.val: newValue])
	}
}

It seems this is a compiler bug, which is not solved until I write this blog. -> https://bugs.swift.org/browse/SR-12428 Swift compiler was not properly handling key paths containing covariant Self type. So it’d be safer to use className rather than covariant Self type at here.

I’d like to paste someone’s answer at here:

the Swift compiler did not include any logic to handle dynamic Self when creating a key path. Under-the-hood, it essentially tried to emit a key path object of type ReferenceWritableKeyPath<Self, CGFloat>. The type system doesn’t allow you to use dynamic Self in that context, and the runtime was not expecting it. The strange error message you received was the result of trying to decode this unexpected object type, which was encoded as a 4-byte relative pointer to the metadata for your V class, followed by the suffix XD indicating a dynamic Self type (hence the error message containing 4 �’s followed by XD). By playing around with different ways to create key paths involving dynamic Self, I came across a number of different crashes at both compile-time and runtime.

Reference

Published on 22 Jan 2021 Find me on Facebook, Twitter!

«  Fix sudo /etc/sudoers is owned by uid 502 Error
Cycle detection  »

Comments

    Join the discussion for this article at here . Our comments is using Github Issues. All of posted comments will display at this page instantly.