Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-10982] Objective-C generics specialised by block type drive Swift's type system crazy #53372

Open
swift-ci opened this issue Jun 20, 2019 · 0 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-10982
Radar None
Original Reporter mpokhylets (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 17f55c5b67f1ad92b957debf4917e9f4

Issue Description:

The following Objective-C code:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface BlockWrapper<BlockType> : NSObject<NSCopying>
@property(nonatomic, copy) BlockType block NS_REFINED_FOR_SWIFT;
- (instancetype) initWithBlock:(BlockType)block;
@end

@interface Foo: NSObject<NSCopying>
@property(nonatomic, readonly, copy) BlockWrapper<NSDate* _Nonnull (^)(NSString *)> *action;
@end

NS_ASSUME_NONNULL_END

Produces the following Swift interface:

import Foundation

open class BlockWrapper<BlockType> : NSObject, NSCopying where BlockType : AnyObject {
    @NSCopying open var __block: BlockType
    public init(block: BlockType)
}

open class Foo : NSObject, NSCopying {    
    @NSCopying open var action: BlockWrapper<@convention(block) (String) -> Date> { get }
}

But in Swift @convention(block) (String) -> Date does not conform to AnyObject, so when bridged to Swift, instances of Foo become unusable:

print(Foo().action.block("abc"))
error: 'BlockWrapper<@convention(block) (String) -> Date>' requires that '@convention(block) (String) -> Date' conform to 'AnyObject'

It is possible to workaround this using unsafeBitCast:

let untypedWrapper = (Foo().action as! BlockWrapper<AnyObject>)
typealias BlockType = @convention(block) (String) -> Date
print(unsafeBitCast(untypedWrapper.block, to: BlockType.self)("abc"))

But this workaround cannot be implemented generically:

func _getBlock<T, U>(_ block: BlockWrapper<T>) -> U {
    let untypedWrapper = (block as! BlockWrapper<AnyObject>)
    return unsafeBitCast(untypedWrapper.block, to: U.self)
}

let block: BlockType = _getBlock(Foo().action) as BlockType
error: Cannot convert value of type 'BlockWrapper<@convention(block) (String) -> Date>' to expected argument type 'BlockWrapper<_>'
@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

1 participant