How do I safely cast a `_Nullable` to a `_Nonnull` in Objective-C?

Michael Ochs' answer was basically correct, but I've since run into some static analyzer warnings because of lack of hard _Nonnull guarantees within. In short, we must abort if we receive a nil or else when we do an assignment like this:

@interface Foo : NSObject
+ (NSString * _Nullable)bar;
@end

int main(int argc, char * argv[]) {
  NSString * _Nonnull bar = RBBNotNil([Foo bar]);
}

In a Release configuration (in my case, when Archiving), the static analyzer will complain that you're attempting to assign a _Nullable value to a _Nonnull lvalue. I received warnings like this:

nil assigned to a pointer which is expected to have non-null value

This is my updated version:

// We purposefully don't have a matching @implementation.
// We don't want +asNonnull to ever actually be called
// because that will add a lot of overhead to every RBBNotNil
// and we want RBBNotNil to be very cheap.
// If there is no @implementation, then if the +asNonnull is
// actually called, we'll get a linker error complaining about
// the lack of @implementation.
@interface RBBBox <__covariant Type>

// This as a class method so you don't need to
// declare an unused lvalue just for a __typeof
+ (Type _Nonnull)asNonnull;

@end

/*!
 * @define RBBNotNil(V)
 * Converts an Objective-C object expression from _Nullable to _Nonnull. 
 * Crashes if it receives a nil! We must crash or else we'll receive
 * static analyzer warnings when archiving. I think in Release mode,
 * the compiler ignores the _Nonnull cast.
 * @param V a _Nullable Objective-C object expression
 */
#define RBBNotNil(V) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wgnu-statement-expression\"") \
({ \
__typeof__(V) __nullableV = V; \
NSCAssert(__nullableV, @"Expected '%@' not to be nil.", @#V); \
if (!__nullableV) { \
    abort(); \
} \
(__typeof([RBBNotNil<__typeof(V)> asNonnull]))__nullableV; \
}) \
_Pragma("clang diagnostic pop")

The best I found so far is a trick with generics.

Essentially you define an interface that uses generics and has a method that returns the generic type as nonnull. Then in your macro you use typeof but on the generic type, and this gives you the correct type.

Note that the generic class is never instantiated, it's just used to get the correct type.

@interface RBBBox<__covariant Type>

- (nonnull Type)asNonNull;

@end

#define RBBNotNil(V) \
    ({ \
        NSCAssert(V, @"Expected '%@' not to be nil.", @#V); \
        RBBBox<__typeof(V)> *type; \
        (__typeof(type.asNonNull))V; \
    })

This is not my idea, though. Source: https://gist.github.com/robb/d55b72d62d32deaee5fa


I use this macro:

#define assumeNotNull(_value) \
    ({ if (!_value) abort(); __auto_type const _temp = _value; _temp; })

Of course, only after an appropriate test in code:

if (parameters) {
    [obj processParameters:assumeNotNull(parameters)];
}

Leaving out the macro the compiler would tell me that parameters might be NULL but processParameters requires a non-NULL argument. In my case that is even configured to be an error, not just a warning.

Leaving out the if check, the code will compile but if I ever feed in NULL, the application will crash on spot. So one should only use the macro after a test or if one is absolutely sure that the value cannot be NULL for some reason and you are so sure about that, that you are willing to bet your app stability on it.

If in doubt, always test and keep in mind, that if a test is clearly unnecessary (e.g. the condition was tested before and the code will never be reached if the value was NULL), the compiler will detect that during the optimization phase and remove the test for you. Unnecessary testing is hardly ever a performance problem, especially not with a test that cheap.