False positive warning when downcasting to combined generic parameter type

I have a base class and a generic subclass of it:

class AnyPropertyBag
{
  func getValue<ownerT, valueT>(keyPath: KeyPath<ownerT, valueT>) -> valueT
  {
    if let genericSelf = self as? PropertyBag<ownerT> // warning here
    {
      
    }
  }
}


class PropertyBag<ownerT> : AnyPropertyBag
{
}

warning : "Cast from 'AnyPropertyBag' to unrelated type 'PropertyBag' always fails"

And yet they clearly are related by inheritance!

If I make the derived class non-generic, no problem:

class AnyPropertyBag
{
  func getValue<ownerT, valueT>(keyPath: KeyPath<ownerT, valueT>) -> valueT
  {
    if let genericSelf = self as? PropertyBag
    {
      
    }
  }
}

class PropertyBag : AnyPropertyBag
{
}

Is this yet another limitation of Swift generics, for which I'm going to have to find yet another hacky workaround? :open_mouth:}

This compiles for me in Xcode Version 10.1 (10B61).

Hmmm. My example was stripped down for simplicity and I hadn't checked if it gave the warning or not. The truth is more complicated and I think I've nailed it down a bit more:

There is a constraint on ownerT, which relies on two other types:

class Object
{

}

protocol KeyPathDeclaration
{
  static func keyPaths() -> [PartialKeyPath<Self>]
}
typealias OwnerType = … // see below

class AnyPropertyBag
{
  internal func getValue<ownerT : OwnerType, valueT>(keyPath: KeyPath<ownerT, valueT>) throws -> valueT?
  {
    if let genericSelf = self as? PropertyBag<ownerT>
    {
      print(genericSelf)
    }
    
    return nil
  }
}

class PropertyBag<ownerT : OwnerType> : AnyPropertyBag
{
}

If I set the typealias OwnerType to Object, no problem.

If I set typealias OwnerType to KeyPathDeclaration, no problem.

But, if I set it to Object & KeyPathDeclaration, it provokes the warning.

Does this still compile for you?

It does! :–)

With both types joined in the typealias? It is a warning, not an error.

If I implement KeyPathDeclaration directly on Object and remove it from the typealias, the warning goes away.

The problem is that KeyPathDeclaration is only ever meant to be implemented on certain subclasses of Object

Ugh, my bad, the warning was missing in the playground and only presented itself when compiling inside a regular project. Sorry. It works just as you described – no warning for Object or KeyPathDeclaration, warning for Object & KeyPathDeclaration.

Aaaarrrggghhh !!!!

Thanks for the confirmation. The only question now is, how on earth do I work around it?

Or do I have to put the project on hold until someone deigns to fix it in the compiler?

Mutter, mutter, mutter :face_with_raised_eyebrow:

Is this the same as SR-5252? My preferred solution would be to selectively silence the warning and move on, but that’s not yet possible in Swift, is it?

Yes, it looks similar and, when I ignore it, the code works exactly as expected.

This is really annoying as it seems this has been known about for some time and still no fix in sight. I've commented on SR-5252, citing this thread.

Terms of Service

Privacy Policy

Cookie Policy