5

Does the Objective-C compiler actually warn you if it thinks that you may be passing nil to a parameter marked with _Nonnull?

Or is it merely a hint to whatever tool converts between Swift and Objective-C to better deal with Swift optionals?

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
iosdude
  • 1,131
  • 10
  • 27

1 Answers1

3

On its own, there is warning only in the extremely trivial case: when you pass nil to a function accepting _Nonnull value.

NSObject* _Nonnull test(NSObject* _Nonnull) {
    test(nil);  // warning

    NSObject* _Nullable f = nil;
    test(f); // no warning (passing _Nullable to _Nonnull), only warn in static analysis

    NSObject* _Nonnull g = [[NSObject alloc] init];
    g = nil; // no warning (!) (assigning nil to _Nonnull)

    if (g != nil) {  // no warning (unnecessary '!= nil' comparison)
        test(g);
    }

    return nil; // no warning (returning nil to _Nonnull)
}

The code above when compiled in Xcode 7

(There is a -Wnullable-to-nonnull-conversion flag but it doesn't seem to have any effect to the code above.)

As documented, the three attributes will not change the behavior of the code:

… Note that, unlike the declaration attribute nonnull, the presence of _Nonnull does not imply that passing null is undefined behavior: fetch is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null.

Beyond the compiler, it will also help the static analyzer, but again clang's static analyzer will only catch the trivial case where it knows for sure you are assigning a nil to a _Nonnull (i.e. the test(f) example above).

Nevertheless, it is still useful to mark a pointer _Nonnull/_Nullable as

  1. Documentation;
  2. Allow Swift developers to use your library better;
  3. The compiler will emit warnings everywhere if you don't add those annotations
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Should one use `_Nonnull` / `_Nullable` instead of `nonnull` / `nullable`? You seem to prefer the underscore variant, can you please tell why? I personally find `nonnull` and `nullable` easier to read and the following article in the Swift Blog seems to suggest the latter over the former as a nicer alternative: https://developer.apple.com/swift/blog/?id=25 – iosdude May 12 '16 at 06:12
  • I agree with the documentation point. Also another quick question: can these attributes be considered as an alternative to `NSParameterAssert(x != nil)` or does one use both of them together? – iosdude May 12 '16 at 06:16
  • @willcodeforf00d `nonnull` cannot be used outside of an Objective-C method declaration. The example I used is a C function. – kennytm May 12 '16 at 06:19
  • 1
    @willcodeforf00d You could use both of them together. `_Nonnull` itself does *not* assert that `x` is not nil. You still have to check if `x` is nil or not if you want to be safe. – kennytm May 12 '16 at 06:20