Better error messages for (not) conforming to generic arguments

Hi All.

First of all, let me say that generics are my bane, and that every time I get involved with them, I burn a whole bunch of time. This one arose because I was converting an ObjC project to Swift, and forgot that the CoreData class generation subclasses only from NSManagedObject instead of my own custom subclass, HXManagedObject. It may have been made more difficult by the fact that I'm passing around KeyPaths, and the compiler has special knowledge of those. Here is a condensed code example:

import Foundation
import CoreData

class GenericTypeInference {
   
    open func updateEntity<E:HXManagedObject,K:Hashable>(keyPath:KeyPath<E,Optional<K>>) -> [K:E]? {
        return nil
    }
   
    func test1() {
        // Type '_' has no member 'feedCategoryID'
        _ = self.updateEntity(keyPath:\DWFeedCategory.feedCategoryID)
    }
    
    func test2() {
        let keyPath:KeyPath<DWFeedCategory,NSNumber?> = \DWFeedCategory.feedCategoryID
        // Cannot convert value of type 'KeyPath<DWFeedCategory, NSNumber?>' to expected argument type 'KeyPath<_, Optional<_>>'
        _ = self.updateEntity(keyPath:keyPath)
    }
    
    func test3() {
        // Had I tried to do this, I may have figured it out sooner.
        // Cannot convert value of type 'ReferenceWritableKeyPath<DWFeedCategory, NSNumber?>' to specified type 'KeyPath<HXManagedObject, NSNumber?>'
        let keyPath:KeyPath<HXManagedObject,NSNumber?> = \DWFeedCategory.feedCategoryID
        _ = self.updateEntity(keyPath:keyPath)
    }
}

// DW for "Don't Work"
// Change to inherit from NSManagedObject to exhibit errors
@objc(DWFeedCategory)
class DWFeedCategory : NSManagedObject {
    @NSManaged public var feedCategoryID: NSNumber?
}

@objc(HXManagedObject)
class HXManagedObject : NSManagedObject {
    @NSManaged public var feedCategoryID: NSNumber?
}

For test1, the error message seems really non-sensical, since \DWFeedCategory.feedCategoryID is definitely a valid KeyPath. It also took quite a while to understand that '_' means 'the generic type here'.

For test2, although it makes total sense in hindsight, and is completely accurate, it was also completely unhelpful. Something like, "DWFeedCategory does not conform to HXManagedObject" would have been very helpful. Same thing for test3. Would this be doable?

Thanks.

-Kenny

For the keypath in test1 I have an open bug [SR-7339] Incorrect keypath error for invalid typecast · Issue #49887 · apple/swift · GitHub with linked radar.

Just to be clear, is the following the issue that this bug is referring to?

struct Test<Root> {
    init<Value: FixedWidthInteger>(keyPath: WritableKeyPath<Root, Value>) {

    }
}

struct Tester {
    var i = 1
    var s = ""
}

let t1 = Test(keyPath: \Tester.i)
let t2 = Test(keyPath: \Tester.s)
let kp = \Tester.s
let t3 = Test(keyPath: kp)

With compile results:

keypath0.swift:13:32: error: type '_' has no member 's'
let t2 = Test(keyPath: \Tester.s)
                               ^
keypath0.swift:15:24: error: in argument type 'WritableKeyPath<Tester, String>', 'String' does not conform to expected type 'FixedWidthInteger'
let t3 = Test(keyPath: kp)
                       ^

Where the first error message should pretty much be the same as the second errror message?

That's right.

Cool. I ran in to this recently and couldn't figure out how to "trim it down" to have a good example for a bug ticket.