Description
Description
Given a Swift class with a property that is a closure that takes an option set as a parameter, if C++ interop is enabled, the option set is exposed incorrectly when accessed from Objective-C++ or Objective-C.
I originally filed this as Feedback FB12244688 in June 2023 after talking about it with a couple of engineers in a WWDC lab. That feedback is currently marked as "Potential fix identified - in Xcode 15" but the issue still reproduces in 16.2 with a 6.1 Development swift toolchain.
Reproduction
@objc class TestButton : UIButton {
@objc var textColorResolver: ((UIControl.State) -> UIColor?)?
}
When using this from Objective-C without C++ interop enabled:
TestButton *button = [[TestButton alloc] init];
button.textColorResolver = ^UIColor * _Nullable(UIControlState) {
return [UIColor whiteColor];
};
This is correct. But if you enable C++ interop, you get this error:
Incompatible block pointer types assigning to 'UIColor * _Nullable (^ _Nullable)(int)' from 'UIColor * _Nullable (^)(UIControlState)'
And in the generated Swift header:
Unknown type name 'State'
Pointing at the property in this declaration:
@class UIColor;
@class NSCoder;
SWIFT_CLASS("_TtC16ConcurencyTester10TestButton")
@interface TestButton : UIButton
@property (nonatomic, copy) UIColor * _Nullable (^ _Nullable textColorResolver)(State);
- (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder OBJC_DESIGNATED_INITIALIZER;
@end
If I re-write the usage of TestButton
, Xcode autocompletes the property access like this:
TestButton *button = [[TestButton alloc] init];
button.textColorResolver = ^UIColor * _Nullable(int) {
return [UIColor whiteColor];
};
Expected behavior
I'd expect the way the closure property is exposed to not change between C++ interop and normal.
Environment
I reproduced this with Xcode 16.2, using the latest 6.1 Development toolchain snapshot from February 19, 2025.
Additional information
No response