Constant 'aClass' inferred to have type 'AnyObject.Type', which may be unexpected?

func getClass(_ object: AnyObject) -> AnyObject.Type { ... }

// Warning: Constant 'aClass' inferred to have type 'AnyObject.Type', which
// may be unexpected
let aClass = getClass(NSObject())
  • Why is the compiler emitting this warning so excessively? (Xcode 13)
  • What is it about the custom getClass function that makes the compiler assume the type is possibly inferred incorrectly?
2 Likes

I am not sure why the warning is shown in the original code

My Observation
When explicitly specifying the type, the warning is not shown

let aClass: AnyObject.Type = getClass(NSObject()) //No warning

Right, the compiler suggests that as well, but I‘m still very surprised that I‘m forced to suppress this warning manually for so many times when working with AnyObject.Type.

There is no warning when a generic function is used

func getClass<T>(_ object: T) -> T.Type { type(of: object) }

let aClass = getClass(NSObject())

That‘s neither an answer the main problem nor an option as the types I‘m working with are dynamic and always erased into the existential. On top of that, your example explicitly sets the type for the constant. I appreciate your effort though. :slightly_smiling_face:

So far my gut feeling tells me that the analysis around AnyObject.Type are just too aggressive or there is some hidden bug here.

2 Likes

AnyObject.Type / AnyClass has the same "magic" behavior that AnyObject does on Apple platforms: you can invoke arbitrary Objective-C methods on it. To keep you from doing this accidentally, the compiler warns about values typed as AnyObject.Type / AnyClass like it does for AnyObject.

I think you'd be fully justified in calling this a band-aid on a bad feature, especially since it doesn't matter on non-Apple platforms, but that's why it's there.

5 Likes

Thank you for shining a bit more light on to this, although I still don‘t really understand how message sending would be related to static type definition. My initial thought was the trap that (almost?) everything can be casted into an AnyObject on Darwin platforms, which can be really painful to work with. Gladly at least the dynamic is operation over metatypes gets the expected result in such situations.