Skip to content
Soutaro Matsumoto edited this page Jun 11, 2016 · 4 revisions

Nullarihyon has some assumptions on analysis to minimize number of false positives.

Variable Nullability Propagation

If local variable declaration is with initial value, and without explicit nullability annotation, the nullability of the variable is propagated from nullability of initial value.

NSNumber *x = @1;  // x is _Nonnull
NSNumber * _Nullable y = @3;  // y is _Nullable because the declaration has nullability annotation
NSNumber *z = y;  // z is _Nullable because y is _Nullable

This helps analyzing without nullability on variables. The following program would have warning on dictionary[key] without nullability propagation.

NSDictionary *dictionary;

NSNumber *key = condition ? @1 : @2;
NSString *value = dictionary[key];

The nullability propagation also would make extra warning however.

NSDictionary *dictionary;

NSString *name = @"initial value";
name = dictionary[@"name"];

The dictionary[@"name"] is _Nullable, and then name is assumed to be _Nonnull by nullability propagation, it would have an extra warning, which would not be reported without nullability propagation. For that case, you can explicitly declare variable with nullability.

NSDictionary *dictionary;

NSString * _Nullable name = @"initial value";
name = dictionary[@"name"];

self is _Nonnull, on RHS

self is assumed to be _Nonnull in Nullarihyon on right hand side. And on LHS, self is treated as _Nullable.

This assumption makes

  • Having _Nonnull returning method call _Nonnull
  • Assigning [super init] things to self without warning, even if it returns _Nullable

Assumption on class, alloc, and init

The following methods are assumed having _Nonnull return types, if no nullability is specified.

  • -[C init]
  • -[C class]
  • +[C alloc]
  • +[C class]

Loop variables are _Nonnull

Loop variables are assumed to be _Nonnull.

for (NSString *x in collection) {
  // x is _Nonnull
}

I believe this makes sense because most collections including NSArray and NSDictionary do not allow having nil. However, you can define custom collection which may contain nil. For that, just add nullability annotation.

for (NSString * _Nullable x in collection) {
  // x is _Nullable
}

if and logical and

When condition clause of if is reference to variable, the variable is treated as _Nonnull in then clause of the if.

NSString * _Nullable x;

if (x) {
  // x is _Nonnull
} else {
  // x is _Nullable
}

// x is _Nullable

This rule also applies to logical and && expression.

NSNumber * _Nullable x;
NSString * _Nullable y;

if (x && y) {
  // x and y are _Nonnull
}

BOOL flag = x && [y isEqualToString:[x stringValue]];   // [x stringValue] is _Nonnull

This makes a warning if you have assignment in then clause of if.

NSNumber * _Nullable x;
NSNumber * _Nullable y;

if (x) {
  x = y;  // Warning: x is _Nonnull here
}

Add cast for that case.

Clone this wiki locally