During implementation, I’ve come up with some problems with SE-0033 <https://github.com/apple/swift-evolution/blob/master/proposals/0033-import-objc-constants.md> as written, and am proposing some changes to the proposal. I’d like to present them here for early discussion, and will write up a proposal amendment shortly.
The intent of this feature is to introduce a zero-cost type that serves as a source of safety and convenience, but has the same underlying storage as the typedef, and thus we pay no bridging cost.
The biggest issue with the proposal as written is with importing a typedef as an enum. Enums do not allow us to control the underlying storage, and thus we would constantly be paying a bridging cost in its use. The benefits of using enums was access to the switch/case syntax and the communication with the user that our intent is for there to be no new cases, that is, it’s non-extensible.
I propose that we import what were “struct” wrappers as structs whose raw-value initializer is implicitly labeled, that is init(_ rawValue: Type). What were “enum” wrappers have explicit labels, e.g. init(rawValue: Type). Otherwise, behavior is much the same, but we could think about enhanced warnings for the non-extensible case.
The second issue concerns importing bridged typedefs, e.g. NSString. In that case, we want the underlying storage to be NSString, but present it as a String to the users. I propose that for those we create a stored property _rawValue : NSString, and a computed property rawValue: String.
Third is common-word name stripping. I propose that we follow the common-prefix stripping logic that already exists for enum constants, albeit in this case it’s confined to common-prefix with the type name. This is a tradeoff in how much magic and heuristics the importer does, which can occasionally backfire. It’s worth noting that swift_name allows control of the name and importing a global as a member of the newly created type, e.g. swift_name(“MyTypedefStruct.globalValue”), if prefix-stripping is insufficient.
Due to these changes, I also propose to re-evaluate the attribute name and syntax. swift_wrapper(enum) doesn’t really make much sense. I propose that we use the name swift_struct and swift_struct(extensible), or something like that. The old attributes can stay around as aliases for now, and we can deprecate them later.