15

The Apple documentation TN2151 says this for a possible cause of a EXC_BREAKPOINT / SIGTRAP:

a non-optional type with a nil value

But code such as this won't compile:

var x = "hello"
x = nil

So under what circumstances can a non-optional obtain a nil value?

Hamish
  • 78,605
  • 19
  • 187
  • 280
Gruntcakes
  • 37,738
  • 44
  • 184
  • 378
  • 1
    Read this https://stackoverflow.com/questions/34644128/why-non-optional-any-can-hold-nil/34644243 . It gives a nice explanation. – Jen Jose Jul 21 '17 at 18:59

3 Answers3

21

Consider something like this in Objective-C bridged to Swift:

- (NSObject * _Nonnull)someObject {
    return nil;
}

The function is annotated as _Nonnull, but will return nil. This bridged as a non-optional object to Swift and will crash.

JAL
  • 41,701
  • 23
  • 172
  • 300
  • 4
    This is the commonest cause. There have been a bunch of iOS (and macOS) APIs incorrectly labelled `_Nonnull`. – rob mayoff Jul 21 '17 at 19:05
  • See for example the section titled “Nullability” in [AppKit Release Notes for macOS 10.13](https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKit/index.html): “We fixed a number of places where arguments and return values had incorrect nullability.” – rob mayoff Jul 21 '17 at 19:07
7

Contrived, but possible:

class C {}

let x: C? = nil
let y: C = unsafeBitCast(x, to: C.self)

print(y) // boom
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • 2
    Or just `unsafeBitCast(0, to: C.self)` – Hamish Jul 21 '17 at 19:05
  • 2
    Falling back on [Objective-]C casts to shoot yourself in the foot, always elegant :) – JAL Jul 21 '17 at 19:05
  • 3
    Just a remark: The unsafeBitCast succeeds because for a reference type, instances of `C` and `C?` are pointers and thus of the same size. With `struct C {}` the unsafeBitCast would already crash (can't unsafeBitCast between types of different sizes). – Martin R Jul 21 '17 at 19:09
  • @MartinR Yeah. That's something I really like, that `Optional` in the case of most structs is a tuple containing a discriminator and the payload struct, whereas `Optional` in the case of classes packs the `nil` value as a 0 pointer – Alexander Jul 21 '17 at 19:10
1

Happens when interoperating with Objective C. An objc-method could be annotated as nonnull, but nothing prevents it from returning nil anyways. The compiler catches only the most obvious cases and even then it only produces warnings (e.g. when you blatently return nil; in a method that is specified as not returning nil.)

Michael
  • 6,451
  • 5
  • 31
  • 53