Disable Objc bridging as Implicitly Unwrapped Optionals

I recently encountered a crash in our Swift code that was referencing an Objc class without any nullability annotations. The class was bridged to Swift with all properties as IUO e.g.:

@interface TestClass: NSObject
@property (nonatomic) OtherClass *testProp;
@end
// in Swift
let cls = TestClass()
let p = cls.testProp.otherProp // CRASH

I manually make testProp an optional to fix this:

let p = cls.testProp?.otherProp // OK

How can we get the compiler to either bridge un-annotated Objc code a nullable, or force the use of unwrapping? Our Objc is very big and there are probably hundreds of classes without nullability annotations, making it more dangerous to introduce Swift than stick with Objc.

1 Like

People have asked about this before. I think it wouldn't be hard to add a flag that controls this (to the point that a fairly new contributor could do it), but some people (me) don't love the idea of "language mode flags" (beyond the major -swift-version 4, -swift-version 5, etc), with the concern being that it conceptually fractures the language into different dialects and makes it harder for someone reading a source file to necessarily know what's going on. This one seems pretty safe, though, since everything you can do with an Optional you can also do with an IUO, so maybe?

1 Like

Yeah, I think as far as language-mode flags go, the possible confusion here is pretty minimal: "I wasn't sure what was going on, so I thought it might be an IUO import, but it wasn't because those were turned off".

1 Like

Could this be, in lieu of a flag, controlled by something in the source code similar to ‘testable’?

1 Like

Would we require that on every import?

For Swift code in a mixed module, there is no import.

2 Likes

Good point. So if we wanted to cover that, we would need something beyond an import modifier.

Paradoxically, adopting a safety-focused language like Swift in a project with legacy Objc code actually makes the project less safe. I'm surprised that "I don't know" could ever mean "Non-optional", but I see it was done to make Apple's iOS frameworks easier to use while they added annotations. Now that they have, it seems like the right choice is the more logical and safer "I don't know == Optional".

There will always be C libraries that people want to use but can't modify the source of, so there will always be "I don't know" cases where Optional is (arguably) a distraction in practice.

I don't think I'd say "adopting a safety-focused language like Swift in a project with legacy ObjC code actually makes the project less safe". Objective-C doesn't force you to check something for nil/NULL either.

1 Like

Obj-c can message nil, whereas the same in Swift with an IUO is a crash.

:-) You'll find that discussion repeatedly on this site, but the view of most Swift contributors is that it's better ("safer") to crash deterministically than to silently do nothing and maybe crash or leak secure data later.

2 Likes

Perhaps turn C headers into IUO, and Obj-c headers into optionals?

There's not really a way to tell C and ObjC headers apart, unfortunately. Besides, one of the things we discovered in auditing Apple's frameworks was that most Objective-C parameters or return values cannot be nil in practice.

I think your idea of a mode to disable IUO importing makes sense, but I don't think we're going to change the default behavior at this point.

1 Like
Terms of Service

Privacy Policy

Cookie Policy