Skip to content

C++ interop incorrectly exposes option sets when parameters in a closure property #79522

Open
@tomhamming

Description

@tomhamming

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

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c++ interopFeature: Interoperability with C++

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions