# Narrowing and `null`

[Narrowing](../narrowing.md) › null. The names in the examples are those of [section 2](../narrowing.md#2-the-names-in-the-examples).

In the specification's lattice `Null` is below every type, so `number` means "a number or `null`". In the analyzer's union (`Feel.Type.Union`) `Null` is an alternative of its own, present only when the value may be `null` ([type-system.md](../type-system.md), 3.2). A fact therefore has two jobs for every subject: to cut the alternatives of its kind, which the pages of the kinds describe, and to keep or remove `Null`. This page covers the second.

`null` determines how the two branches differ ([section 4](../narrowing.md#4-then-else-and-null)):

- an **ordering** (`< <= > >=`) with a `null` operand is `null`, and `null` is not `true`;
- **`=`** is `true` for two `null`s, and `false` for a `null` and a value;
- **`!=`** is `true` for a `null` and a value (`null != 5` is `true`) and `false` for two `null`s (Table 50, D-04);
- an operation with a `null` operand is `null`.

## When `Null` stays

| The condition | `Null` stays in `then` when | `Null` stays in `else` |
| --- | --- | --- |
| an ordering | never | always |
| `x = other` | `other` can be `null`, or its type is not known | unless `other` is only `null` |
| `x != other` | `other` is not only `null`: it has a kind, or is not known | when `other` can be `null`, or is not known |

And `else` can use the values for which the comparison is *false* only when the comparison cannot be `null`, that is, when the other side is of one kind and never `null`. That is the only difference between the rows below.

## Every operator against every other side

The four sides: `null` alone, a constant of the same kind (never `null`), a name of the same kind that can be `null` (`y`), and a name of type `Any` (`v`).

| Condition | `x` when true | `x` when not true |
| --- | --- | --- |
| `x = null` | `Null` | `number` |
| `x = 5` | `number = 5` | `number in [-max..5), (5..max] \| Null` |
| `x = y` | `number \| Null` | `number \| Null` |
| `x = v` | `number \| Null` | `number \| Null` |
| `x != null` | `number` | `Null` |
| `x != 5` | `number in [-max..5), (5..max] \| Null` | `number = 5` |
| `x != y` | `number \| Null` | `number \| Null` |
| `x != v` | `number \| Null` | `number \| Null` |
| `x > null` | — | `number \| Null` |
| `x > 5` | `number in (5..max]` | `number in [-max..5] \| Null` |
| `x > y` | `number in (-max..max]` | `number \| Null` |
| `x > v` | `number` | `number \| Null` |

- `x = null` is the **guard**. When it is not true, `x` is not `null`.
- `x = 5`: when true, `x` is `5`; when not true, `x` can still be `null`, because `null = 5` is `false`.
- `x != 5`: true for `null`, so `Null` stays in `then`; when not true, `x` is `5`.
- `x = y` and `x != y` learn nothing: `y` can be `null`, and then both are decided by two `null`s.
- `x > null` is `null` for every `x`, so the `then` branch cannot be taken.
- `x > y`: true means neither is `null`, and `x` is above the lowest possible `y`.
- `x > v`: true means `x` is not `null` and `v` is a number; `x`'s set learns nothing.

A condition with `null` on the left is the same: `null = x` is `x = null`, and `null < x` is `x > null`.

| Condition | `x` when true | `x` when not true |
| --- | --- | --- |
| `null = x` | `Null` | `number` |
| `null < x` | — | `number \| Null` |

## An operand that has no order, against `Any`

A boolean, a list, a context, a range and a function have no order (Table 55 lists none of them), so an ordering with one of them is `null` whatever the other operand is: at run time the result is `null` for a value of the same kind, for a value of another kind (a type mismatch) and for a `null`, and the type of `x > v` above is open only because a number has an order. The type says so for a name of type `Any` as for a known kind (D-193, D-196), and for `<=` and `>=` as for `<` and `>`: `true < v` and `true <= v` are `Null` with a `type_mismatch` warning for every `v`, and a condition made of them is never true, so the `then` branch cannot be taken. A union is typed pair by pair: it is `Null` only when every pair of its alternatives is, so `Any` minus all the kinds that have an order is `Null` against `Any`, and `Any` minus just one of those kinds is not.

| Expression | Type | Warnings |
| --- | --- | --- |
| `true < v` | `Null` | `type_mismatch` |
| `v >= {age: 20}` | `Null` | `type_mismatch` |
| `[1, 2] <= v` | `Null` | `type_mismatch` |
| `(function(a: number) a) < v` | `Null` | `type_mismatch` |
| `v < null` | `Null` | — |
| `x < v` | `boolean \| Null` | — |
| `v < v` | `boolean \| Null` | — |

| Condition | `v` when true | `v` when not true |
| --- | --- | --- |
| `true < v` | — | `Any \| Null` |
| `v > {age: 20}` | — | `Any \| Null` |
| `v <= true` | — | `Any \| Null` |
| `v >= []` | — | `Any \| Null` |

`<=` and `>=` follow the ordered-kind domain table, like `<` and `>` (D-196). The specification's alternative formula `a < b or a = b` would make `true <= true` true; the supported interpretation instead gives null. The runtime and inference use that same restriction, including against `Any`.

## An operand that has no operation, against `Any`

The same holds for `+ - * / **`: a boolean, a list, a context, a range and a function have no arithmetic (Tables 57 to 61 and 63 list none of them), a string has `+` and no other operation, a date, a time and a date and time have `+` and `-`, a duration has all but `**`, and only a number has `**`. An operation with an operand of a kind that its operator does not support is `null` whatever the other operand is; at run time this holds for a value of any kind (a type mismatch) and for a `null`, so the type says so for a name of type `Any` as for a known kind (D-203): `true + v` is `Null` with a `type_mismatch` warning for every `v`, and a condition that contains it is never true. `"a" + v`, `d + v` and `x + v` are not `Null`, since for each of them there is a `v` that gives a value, and their types are the kinds that the pairs give, plus `Null` (D-203): the run adds a string to a string only, so `s + v` is `string | Null`; `d + v` is `date | Null` (a date and a duration); `x + v` is `number | Null`; `x * v` is a number, or a duration that a number multiplies, or `null`; and `v + w` is one of the seven kinds that have a `+`, or `null`. A negation has only one operand, so there is no other operand that could make it `Null`, and at run time only a number or a duration can be negated (D-207): `-v` is `number | years and months duration | days and time duration | Null`, as it is for a `v` that is a number, a years and months duration, a days and time duration or `null` (`-b` and `-s` are `Null`, as always). One `v` read twice is not two values (D-170, D-207): for a value combined with itself, the run gives a number, a string or a duration for `v + v` (two dates are not added), `0` of a number, a years and months duration or a days and time duration for `v - v` (a date, a time and a date and time minus themselves are a days and time duration of `0`), a number for `v * v`, `v / v` and `v ** v` (a duration times itself is not defined, and a duration over itself is a number), and `null` for a `v` that is `null`; that is, the kinds of `v + w` (a second name of type `Any`) without the pairs of two different kinds (a date and a duration). A union is typed pair by pair, so it is `Null` only when every pair of its alternatives is.

| Expression | Type | Warnings |
| --- | --- | --- |
| `true + v` | `Null` | `type_mismatch` |
| `v + b` | `Null` | `type_mismatch` |
| `{a: 1} * v` | `Null` | `type_mismatch` |
| `[1] - v` | `Null` | `type_mismatch` |
| `v / b` | `Null` | `type_mismatch` |
| `s - v` | `Null` | `type_mismatch` |
| `d * v` | `Null` | `type_mismatch` |
| `v ** dd` | `Null` | `type_mismatch` |
| `s + v` | `string \| Null` | — |
| `d + v` | `date \| Null` | — |
| `x + v` | `number \| Null` | — |
| `x * v` | `number \| years and months duration \| days and time duration \| Null` | — |
| `ym + v` | `date \| date and time \| years and months duration \| Null` | — |
| `dd / v` | `number \| days and time duration \| Null` | — |
| `v + v` | `number \| string \| years and months duration \| days and time duration \| Null` | — |
| `v - v` | `number = 0 \| years and months duration = P0M \| days and time duration = PT0S \| Null` | — |
| `v * v` | `number in [0..max] \| Null` | — |
| `v / v` | `number = 1 \| Null` | — |
| `v ** v` | `number \| Null` | — |
| `-v` | `number \| years and months duration \| days and time duration \| Null` | — |
| `-(-v)` | `number \| years and months duration \| days and time duration \| Null` | — |
| `(v - v) + 1` | `number = 1 \| Null` | — |
| `(v / v) * 2` | `number = 2 \| Null` | — |
| `v + null` | `Null` | — |

| Condition | `v` when true | `v` when not true |
| --- | --- | --- |
| `true + v > 1` | — | `Any \| Null` |
| `s - v > 1` | — | `Any \| Null` |
| `s + v > 1` | — | `Any \| Null` |
| `d + v = 5` | — | `Any \| Null` |
| `-v = "a"` | — | `Any \| Null` |
| `-v > 1` | `number in [-max..-1)` | `Any \| Null` |
| `-v = 5` | `number = -5` | `Any \| Null` |
| `v - v = 0` | `number` | `Any \| Null` |
| `v + v = "aa"` | `string` | `Any \| Null` |
| `v * v = 4` | `number` | `Any \| Null` |
| `v / v = 1` | `number \| years and months duration \| days and time duration` | `Any \| Null` |

A condition that contains an operation that is `null` for every `v` has the type `Null`, so it is never true and the `then` branch cannot be taken (`if true + v > 1 then 1 else 2` is `number = 2` with a `decided_condition`). The same holds for `s + v > 1`: `s + v` is `string | Null` (D-203), which is never above a number, so the comparison is a mismatch and `Null`; it used to be `Any | Null`, with the comparison typed `boolean | Null`, where the run gives `null`.

A negation and one value read twice work the same way: the kinds of `-v`, `v - v`, `v + v` and the rest are the kinds that the run gives, so a comparison with a value of another kind is never true (`-v = "a"` leaves no `v`), and the kinds of `v` for which the comparison can be true are those in the rows above (`v / v = 1` can be true for a number and for a duration, since a duration divided by itself gives 1, but not for a date).

## `instance of`

`null` is an instance of `Null` only, so `x instance of T` is never true for a `null` unless `T` is `Null`, and is `false` for it, never `null` itself (D-23, D-194).

| Condition | `x` when true | `x` when not true |
| --- | --- | --- |
| `x instance of Null` | `Null` | `number` |
| `x instance of Any` | `number` | `Null` |
| `x instance of number` | `number` | `Null` |

| Condition | `v` when true | `v` when not true |
| --- | --- | --- |
| `v instance of Null` | `Null` | `Any` |
| `v != null` | `Any` | `Null` |
| `v = null` | `Null` | `Any` |

`Any` inside a union means *any value that is not `null`*; the specification's `Any` is `Any | Null`. That is why `v = null` leaves non-null `Any` where it is not true. Other comparisons and type tests can also keep more specific exclusions, such as `Any except number = 5 | Null` ([Any](any.md)).

## Tests with `null` in them

In an `in`, a `null` among the tests is the comparison with `null`. Joined in `then`, met in `else`:

| Condition | `x` when true | `x` when not true |
| --- | --- | --- |
| `x in (null, 5)` | `number = 5 \| Null` | `number in [-max..5), (5..max]` |
| `x in (null)` | `Null` | `number` |

| Condition | `s` when true | `s` when not true |
| --- | --- | --- |
| `s = null or s = "a"` | `string = "a" \| Null` | `string except "a"` |

`x in (null, 5)` is true for `null` and for `5`; when it is not true, `x` is neither, which removes `Null` from the other branch as well.

## A declared non-null name (`T!`)

Under `:enforce` or `:enforce_wide`, a name declared `number!` (D-48) has no `Null` to keep or remove: a bound null ends the run with an input error. Other stances keep null in the inferred input type. The expression type grammar also accepts this extension in parameters and `instance of` targets; this is not the same as marking the overall result type, which is not supported.

| Expression | Type | Warnings |
| --- | --- | --- |
| `k` | `number` | — |
| `k = null` | `boolean = false` | — |
| `null instance of number!` | `boolean = false` | — |
| `if k > 5 then k else 0` | `number in 0, (5..max]` | — |

## The guard in use

| Expression | Type | Warnings |
| --- | --- | --- |
| `if x = null then 0 else x + 1` | `number` | — |
| `if null = x then 0 else x` | `number` | — |
| `x != null and x > 5` | `boolean` | — |
| `x = null or x > 5` | `boolean` | — |
| `if x > null then x else 0` | `number = 0` | `decided_condition` |

- `x + 1` is a number, never `null`, once `x` is known not to be `null`: it does not overflow, since the run rounds `max + 1` to `max` (D-39).
- `x != null and x > 5` is `boolean`, never `null`: the right operand is read knowing the left is true, so `x` is not `null` there. The same for `x = null or x > 5`, read knowing the left is not true.
- `x > null` is `null`, never `true`, so the `then` branch cannot be taken and the warning says so.

See also: [number](number.md), [Any](any.md), [boolean](boolean.md).
