Itâ€™s a little verbose, but instead consider

```
function and_then(f, x::Nullable)
if isnull(x)
S = Base.Broadcast._nullable_eltype(f, x)
if isleaftype(S)
Nullable{S}()
else
Nullable()
end
else
Nullable(f(unsafe_get(x)))
end
end
```

This is better for performance. Among possible inferred results `Union{Nullable{Int}, Nullable{Union{}}}`

we prefer `Nullable{Int}`

, so if inference can return a leaf type, then thatâ€™s what we return. Among possible inferred results `Union{Nullable{Int}, Nullable{Union{}}}`

and `Union{Nullable{Int}, Nullable{Integer}}`

, we prefer `Union{Nullable{Int}, Nullable{Union{}}}`

, because this prevents type instability from propagating very far (since `get`

can be inferred to return `Int`

on that).

In summary:

- Only use the result of type inference for the empty case
- Only use the result of type inference if it is a leaf type; otherwise use
`Union{}`

Note that this is the behavior also of `broadcast`

: we guarantee that we never return a `Nullable{T}`

where `T`

is abstract. This is very important for performance.

By the way, you should not use anything that calls inference from generated functions. This includes `broadcast`

and the implementations of `and_then`

in this thread. There is no workaround besides avoiding the use of generating functions.

(Of course, in this particular case, just use `broadcast`

)