[swift-dev] id-as-Any and ObjC generic parameters
John McCall
rjmccall at apple.com
Thu Jul 7 19:26:14 CDT 2016
Suppose we are calling a function that is generic over T, where T: AnyObject. This comes up when e.g. calling an initializer for an ObjC generic class.
Today we allow conversions from [String] to [NSString], String to NSString, and [String] to [T], but we do not allow a conversion from String to T. The concrete conversions are allowed because there is a bridging conversion from String to NSString. The generic "scalar" conversion is not allowed because the type-checker's enumeration of possible supertypes does not consider bridged types. The generic array conversion is allowed because the special-case code that governs collection up-casting in the type-checker immediately turns the generic argument into its bridged type and so bypasses that flaw.
One goal of the id-as-Any import change is to remove the implicit bridging conversions and the widespread use of AnyObject constraints. As part of this, [U] will convert to [V] only when U is convertible to V. This implies that both of the generic conversions above would be rejected.
With no other changes, this means that when calling an ObjC generic initializer, e.g.:
@interface Generic<T>
- (id) initWithArray: (NSArray<T> *) array;
@end
it will not be possible to pass a [String] (inferring T == NSObject). This is technically a regression.
Well, maybe we don't care.
If we do care, one option is to try to bridge generic parameters and their constraints. Effectively, this would mean removing the implicitly AnyObject constraint on all ObjC generic parameters. If we did this, it would be possible to pass a [String] to the initializer of Generic, and inferring T == String; SILGen would then recognize the need to bridge to NSArray<NSString> when passing the argument. But this is a fair amount of work that I think is new to the plan.
Thoughts?
John.
More information about the swift-dev
mailing list