Okay, why @objc @cdecl together? When thinking this through, I considered several options:
-
@cdecland@objcare both valid on top-level functions, but behave differently:@objcallows using ObjC-only types and@cdecldoes not.- Upside: better checking of accidental reliance on ObjC interop.
- Downside: easy to use the wrong one, in theory.
- Downside: we may eventually want to allow
@cdeclon member functions as well, the same way we have import-as-member for C functions, but@objcalready means something there.
-
@cdecland@objcare interchangeable on Apple platforms, i.e. you can use ObjC-only types in@cdeclfunctions.- Downside: accidental reliance on ObjC interop
- Downside: same thing about member functions
-
@cdeclallows using ObjC-only types on Apple platforms and you can't write@objcon a top-level function at all- Downside: accidental reliance on ObjC interop
-
@cdecldoes not allow ObjC-only types, and you can't write@objcon a top-level function at all- Downside: seems like an artificial limitation - what if you want a top-level C-style function that takes an NSString? Or a CF type?
- This is my second choice, though, and it's easy to expand it to my original proposal later.
-
@cdecldoes not allow ObjC-only types, but@objc @cdecldoes- Downside: verbose and a little weird-looking
- Upside: better checking of accidental reliance on ObjC interop
- Easy to have the compiler help you if you need both but only have one
- This is my preferred option.
I also thought about increasing interop capabilities so that anything that Swift can expose to Objective-C can be exposed to C as well with some sort of opaque struct pointer type—then there are no more types requiring ObjC interop! Sadly, I came to the conclusion that it was just a dream, because you'd still expose them differently on platforms with/without ObjC interop, and it's unclear whether you'd even be able to tell what to expose from Swift when there's no such thing as "ObjC ancestry". (And you can't expose everything because Swift allows naming conflicts that C does not, thanks to modules and nesting. Additionally, exposing more things than @objc does today would change the behavior of the "infer-@objc-for-me" annotation @objcMembers, which makes it a source-breaking change.)