• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #38162

06 Aug 2025 08:25PM UTC coverage: 25.688% (-43.6%) from 69.336%
#38162

push

local

web-flow
fix runtime cglobal builtin function implementation (#59210)

This had failed to be updated for the LazyLibrary changes to codegen.

12976 of 50513 relevant lines covered (25.69%)

676965.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.49
/base/missing.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
# Missing, missing and ismissing are defined in essentials.jl
4

5
show(io::IO, x::Missing) = print(io, "missing")
×
6

7
"""
8
    MissingException(msg)
9

10
Exception thrown when a [`missing`](@ref) value is encountered in a situation
11
where it is not supported. The error message, in the `msg` field
12
may provide more specific details.
13
"""
14
struct MissingException <: Exception
15
    msg::AbstractString
16
end
17

18
showerror(io::IO, ex::MissingException) =
×
19
    print(io, "MissingException: ", ex.msg)
20

21
"""
22
    nonmissingtype(T::Type)
23

24
If `T` is a union of types containing `Missing`, return a new type with
25
`Missing` removed.
26

27
# Examples
28
```jldoctest
29
julia> nonmissingtype(Union{Int64,Missing})
30
Int64
31

32
julia> nonmissingtype(Any)
33
Any
34
```
35

36
!!! compat "Julia 1.3"
37
    This function is exported as of Julia 1.3.
38
"""
39
nonmissingtype(@nospecialize(T::Type)) = typesplit(T, Missing)
68✔
40

41
function nonmissingtype_checked(T::Type)
×
42
    R = nonmissingtype(T)
×
43
    R >: T && error("could not compute non-missing type")
×
44
    R <: Union{} && error("cannot convert a value to missing for assignment")
×
45
    return R
×
46
end
47

48
promote_rule(T::Type{Missing}, S::Type) = Union{S, Missing}
×
49
promote_rule(T::Type{Union{Nothing, Missing}}, S::Type) = Union{S, Nothing, Missing}
×
50
function promote_rule(T::Type{>:Union{Nothing, Missing}}, S::Type)
51
    R = nonnothingtype(T)
×
52
    R >: T && return Any
×
53
    T = R
×
54
    R = nonmissingtype(T)
×
55
    R >: T && return Any
×
56
    T = R
×
57
    R = promote_type(T, S)
×
58
    return Union{R, Nothing, Missing}
×
59
end
60
function promote_rule(T::Type{>:Missing}, S::Type)
×
61
    R = nonmissingtype(T)
×
62
    R >: T && return Any
×
63
    T = R
×
64
    R = promote_type(T, S)
×
65
    return Union{R, Missing}
×
66
end
67

68
convert(::Type{T}, x::T) where {T>:Missing} = x
×
69
convert(::Type{T}, x::T) where {T>:Union{Missing, Nothing}} = x
×
70
convert(::Type{T}, x) where {T>:Missing} = convert(nonmissingtype_checked(T), x)
×
71
convert(::Type{T}, x) where {T>:Union{Missing, Nothing}} = convert(nonmissingtype_checked(nonnothingtype_checked(T)), x)
×
72

73
# Comparison operators
74
==(::Missing, ::Missing) = missing
×
75
==(::Missing, ::Any) = missing
×
76
==(::Any, ::Missing) = missing
×
77
# To fix ambiguity
78
==(::Missing, ::WeakRef) = missing
×
79
==(::WeakRef, ::Missing) = missing
×
80
isequal(::Missing, ::Missing) = true
×
81
isequal(::Missing, ::Any) = false
×
82
isequal(::Any, ::Missing) = false
×
83
<(::Missing, ::Missing) = missing
×
84
<(::Missing, ::Any) = missing
×
85
<(::Any, ::Missing) = missing
×
86
isless(::Missing, ::Missing) = false
×
87
isless(::Missing, ::Any) = false
×
88
isless(::Any, ::Missing) = true
×
89
ispositive(::Missing) = missing
×
90
isnegative(::Missing) = missing
×
91
isapprox(::Missing, ::Missing; kwargs...) = missing
×
92
isapprox(::Missing, ::Any; kwargs...) = missing
×
93
isapprox(::Any, ::Missing; kwargs...) = missing
×
94

95
# Unary operators/functions
96
for f in (:(!), :(~), :(+), :(-), :(*), :(&), :(|), :(xor),
97
          :(zero), :(one), :(oneunit),
98
          :(isfinite), :(isinf), :(isodd),
99
          :(isinteger), :(isreal), :(isnan),
100
          :(iszero), :(transpose), :(adjoint), :(float), :(complex), :(conj),
101
          :(abs), :(abs2), :(iseven), :(ispow2),
102
          :(real), :(imag), :(sign), :(inv))
103
    @eval ($f)(::Missing) = missing
×
104
end
105
for f in (:(Base.zero), :(Base.one), :(Base.oneunit))
106
    @eval ($f)(::Type{Missing}) = missing
×
107
    @eval function $(f)(::Type{Union{T, Missing}}) where T
×
108
        T === Any && throw(MethodError($f, (Any,)))  # To prevent StackOverflowError
×
109
        $f(T)
×
110
    end
111
end
112
for f in (:(Base.float), :(Base.complex))
113
    @eval $f(::Type{Missing}) = Missing
×
114
    @eval function $f(::Type{Union{T, Missing}}) where T
×
115
        T === Any && throw(MethodError($f, (Any,)))  # To prevent StackOverflowError
×
116
        Union{$f(T), Missing}
×
117
    end
118
end
119

120
# Binary operators/functions
121
for f in (:(+), :(-), :(*), :(/), :(^), :(mod), :(rem))
122
    @eval begin
123
        # Scalar with missing
124
        ($f)(::Missing, ::Missing) = missing
×
125
        ($f)(::Missing, ::Number)  = missing
×
126
        ($f)(::Number,  ::Missing) = missing
×
127
    end
128
end
129

130
div(::Missing, ::Missing, r::RoundingMode) = missing
×
131
div(::Missing, ::Number, r::RoundingMode) = missing
×
132
div(::Number, ::Missing, r::RoundingMode) = missing
×
133

134
min(::Missing, ::Missing) = missing
×
135
min(::Missing, ::Any)     = missing
×
136
min(::Any,     ::Missing) = missing
×
137
max(::Missing, ::Missing) = missing
×
138
max(::Missing, ::Any)     = missing
×
139
max(::Any,     ::Missing) = missing
×
140
clamp(::Missing, lo, hi) = missing
×
141

142
missing_conversion_msg(@nospecialize T) =
×
143
    LazyString("cannot convert a missing value to type ", T, ": use Union{", T, ", Missing} instead")
144

145
# Rounding and related functions
146
round(::Missing, ::RoundingMode=RoundNearest; sigdigits::Integer=0, digits::Integer=0, base::Integer=0) = missing
×
147
round(::Type{>:Missing}, ::Missing, ::RoundingMode=RoundNearest) = missing
×
148
round(::Type{T}, ::Missing, ::RoundingMode=RoundNearest) where {T} =
×
149
    throw(MissingException(missing_conversion_msg(T)))
150
round(::Type{T}, x::Any, r::RoundingMode=RoundNearest) where {T>:Missing} = round(nonmissingtype_checked(T), x, r)
×
151
# to fix ambiguities
152
round(::Type{T}, x::Real, r::RoundingMode=RoundNearest) where {T>:Missing} = round(nonmissingtype_checked(T), x, r)
×
153
round(::Type{T}, x::Rational{Tr}, r::RoundingMode=RoundNearest) where {T>:Missing,Tr} = round(nonmissingtype_checked(T), x, r)
×
154
round(::Type{T}, x::Rational{Bool}, r::RoundingMode=RoundNearest) where {T>:Missing} = round(nonmissingtype_checked(T), x, r)
×
155

156
# to avoid ambiguity warnings
157
(^)(::Missing, ::Integer) = missing
×
158

159
# Bit operators
160
(&)(::Missing, ::Missing) = missing
×
161
(&)(a::Missing, b::Bool) = ifelse(b, missing, false)
×
162
(&)(b::Bool, a::Missing) = ifelse(b, missing, false)
×
163
(&)(::Missing, ::Integer) = missing
×
164
(&)(::Integer, ::Missing) = missing
×
165
(|)(::Missing, ::Missing) = missing
×
166
(|)(a::Missing, b::Bool) = ifelse(b, true, missing)
×
167
(|)(b::Bool, a::Missing) = ifelse(b, true, missing)
×
168
(|)(::Missing, ::Integer) = missing
×
169
(|)(::Integer, ::Missing) = missing
×
170
xor(::Missing, ::Missing) = missing
×
171
xor(a::Missing, b::Bool) = missing
×
172
xor(b::Bool, a::Missing) = missing
×
173
xor(::Missing, ::Integer) = missing
×
174
xor(::Integer, ::Missing) = missing
×
175

176
*(d::Missing, x::Union{AbstractString,AbstractChar}) = missing
×
177
*(d::Union{AbstractString,AbstractChar}, x::Missing) = missing
×
178

179
function float(A::AbstractArray{Union{T, Missing}}) where {T}
×
180
    U = typeof(float(zero(T)))
×
181
    convert(AbstractArray{Union{U, Missing}}, A)
×
182
end
183
float(A::AbstractArray{Missing}) = A
×
184

185
"""
186
    skipmissing(itr)
187

188
Return an iterator over the elements in `itr` skipping [`missing`](@ref) values.
189
The returned object can be indexed using indices of `itr` if the latter is indexable.
190
Indices corresponding to missing values are not valid: they are skipped by [`keys`](@ref)
191
and [`eachindex`](@ref), and a `MissingException` is thrown when trying to use them.
192

193
Use [`collect`](@ref) to obtain an `Array` containing the non-`missing` values in
194
`itr`. Note that even if `itr` is a multidimensional array, the result will always
195
be a `Vector` since it is not possible to remove missings while preserving dimensions
196
of the input.
197

198
See also [`coalesce`](@ref), [`ismissing`](@ref), [`something`](@ref).
199

200
# Examples
201
```jldoctest
202
julia> x = skipmissing([1, missing, 2])
203
skipmissing(Union{Missing, Int64}[1, missing, 2])
204

205
julia> sum(x)
206
3
207

208
julia> x[1]
209
1
210

211
julia> x[2]
212
ERROR: MissingException: the value at index (2,) is missing
213
[...]
214

215
julia> argmax(x)
216
3
217

218
julia> collect(keys(x))
219
2-element Vector{Int64}:
220
 1
221
 3
222

223
julia> collect(skipmissing([1, missing, 2]))
224
2-element Vector{Int64}:
225
 1
226
 2
227

228
julia> collect(skipmissing([1 missing; 2 missing]))
229
2-element Vector{Int64}:
230
 1
231
 2
232
```
233
"""
234
skipmissing(itr) = SkipMissing(itr)
×
235

236
struct SkipMissing{T}
237
    x::T
238
end
239
IteratorSize(::Type{<:SkipMissing}) = SizeUnknown()
×
240
IteratorEltype(::Type{SkipMissing{T}}) where {T} = IteratorEltype(T)
×
241
eltype(::Type{SkipMissing{T}}) where {T} = nonmissingtype(eltype(T))
×
242

243
function iterate(itr::SkipMissing, state...)
×
244
    y = iterate(itr.x, state...)
×
245
    y === nothing && return nothing
×
246
    item, state = y
×
247
    while ismissing(item)
×
248
        y = iterate(itr.x, state)
×
249
        y === nothing && return nothing
×
250
        item, state = y
×
251
    end
×
252
    item, state
×
253
end
254

255
IndexStyle(::Type{<:SkipMissing{T}}) where {T} = IndexStyle(T)
×
256
eachindex(itr::SkipMissing) =
×
257
    Iterators.filter(i -> !ismissing(@inbounds(itr.x[i])), eachindex(itr.x))
×
258
keys(itr::SkipMissing) =
×
259
    Iterators.filter(i -> !ismissing(@inbounds(itr.x[i])), keys(itr.x))
×
260
@propagate_inbounds function getindex(itr::SkipMissing, I...)
×
261
    v = itr.x[I...]
×
262
    ismissing(v) && throw(MissingException(LazyString("the value at index ", I, " is missing")))
×
263
    v
×
264
end
265

266
function show(io::IO, s::SkipMissing)
×
267
    print(io, "skipmissing(")
×
268
    show(io, s.x)
×
269
    print(io, ')')
×
270
end
271

272
# Optimized mapreduce implementation
273
# The generic method is faster when !(eltype(A) >: Missing) since it does not need
274
# additional loops to identify the two first non-missing values of each block
275
mapreduce(f, op, itr::SkipMissing{<:AbstractArray}) =
×
276
    _mapreduce(f, op, IndexStyle(itr.x), eltype(itr.x) >: Missing ? itr : itr.x)
277

278
function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray})
×
279
    A = itr.x
×
280
    ai = missing
×
281
    inds = LinearIndices(A)
×
282
    i = first(inds)
×
283
    ilast = last(inds)
×
284
    for outer i in i:ilast
×
285
        @inbounds ai = A[i]
×
286
        !ismissing(ai) && break
×
287
    end
×
288
    ismissing(ai) && return mapreduce_empty(f, op, eltype(itr))
×
289
    a1::eltype(itr) = ai
×
290
    i == typemax(typeof(i)) && return mapreduce_first(f, op, a1)
×
291
    i += 1
×
292
    ai = missing
×
293
    for outer i in i:ilast
×
294
        @inbounds ai = A[i]
×
295
        !ismissing(ai) && break
×
296
    end
×
297
    ismissing(ai) && return mapreduce_first(f, op, a1)
×
298
    # We know A contains at least two non-missing entries: the result cannot be nothing
299
    something(mapreduce_impl(f, op, itr, first(inds), last(inds)))
×
300
end
301

302
_mapreduce(f, op, ::IndexCartesian, itr::SkipMissing) = mapfoldl(f, op, itr)
×
303

304
mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) =
×
305
    mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op))
306

307
# Returns nothing when the input contains only missing values, and Some(x) otherwise
308
@noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray},
×
309
                                  ifirst::Integer, ilast::Integer, blksize::Int)
310
    A = itr.x
×
311
    if ifirst > ilast
×
312
        return nothing
×
313
    elseif ifirst == ilast
×
314
        @inbounds a1 = A[ifirst]
×
315
        if ismissing(a1)
×
316
            return nothing
×
317
        else
318
            return Some(mapreduce_first(f, op, a1))
×
319
        end
320
    elseif ilast - ifirst < blksize
×
321
        # sequential portion
322
        ai = missing
×
323
        i = ifirst
×
324
        for outer i in i:ilast
×
325
            @inbounds ai = A[i]
×
326
            !ismissing(ai) && break
×
327
        end
×
328
        ismissing(ai) && return nothing
×
329
        a1 = ai::eltype(itr)
×
330
        i == typemax(typeof(i)) && return Some(mapreduce_first(f, op, a1))
×
331
        i += 1
×
332
        ai = missing
×
333
        for outer i in i:ilast
×
334
            @inbounds ai = A[i]
×
335
            !ismissing(ai) && break
×
336
        end
×
337
        ismissing(ai) && return Some(mapreduce_first(f, op, a1))
×
338
        a2 = ai::eltype(itr)
×
339
        i == typemax(typeof(i)) && return Some(op(f(a1), f(a2)))
×
340
        i += 1
×
341
        v = op(f(a1), f(a2))
×
342
        @simd for i = i:ilast
×
343
            @inbounds ai = A[i]
×
344
            if !ismissing(ai)
×
345
                v = op(v, f(ai))
×
346
            end
347
        end
×
348
        return Some(v)
×
349
    else
350
        # pairwise portion
351
        imid = ifirst + (ilast - ifirst) >> 1
×
352
        v1 = mapreduce_impl(f, op, itr, ifirst, imid, blksize)
×
353
        v2 = mapreduce_impl(f, op, itr, imid+1, ilast, blksize)
×
354
        if v1 === nothing && v2 === nothing
×
355
            return nothing
×
356
        elseif v1 === nothing
×
357
            return v2
×
358
        elseif v2 === nothing
×
359
            return v1
×
360
        else
361
            return Some(op(something(v1), something(v2)))
×
362
        end
363
    end
364
end
365

366
"""
367
    filter(f, itr::SkipMissing{<:AbstractArray})
368

369
Return a vector similar to the array wrapped by the given `SkipMissing` iterator
370
but with all missing elements and those for which `f` returns `false` removed.
371

372
!!! compat "Julia 1.2"
373
    This method requires Julia 1.2 or later.
374

375
# Examples
376
```jldoctest
377
julia> x = [1 2; missing 4]
378
2×2 Matrix{Union{Missing, Int64}}:
379
 1         2
380
  missing  4
381

382
julia> filter(isodd, skipmissing(x))
383
1-element Vector{Int64}:
384
 1
385
```
386
"""
387
function filter(f, itr::SkipMissing{<:AbstractArray})
×
388
    y = similar(itr.x, eltype(itr), 0)
×
389
    for xi in itr.x
×
390
        if !ismissing(xi) && f(xi)
×
391
            push!(y, xi)
×
392
        end
393
    end
×
394
    y
×
395
end
396

397
"""
398
    coalesce(x...)
399

400
Return the first value in the arguments which is not equal to [`missing`](@ref),
401
if any. Otherwise return `missing`.
402

403
See also [`skipmissing`](@ref), [`something`](@ref), [`@coalesce`](@ref).
404

405
# Examples
406

407
```jldoctest
408
julia> coalesce(missing, 1)
409
1
410

411
julia> coalesce(1, missing)
412
1
413

414
julia> coalesce(nothing, 1)  # returns `nothing`
415

416
julia> coalesce(missing, missing)
417
missing
418
```
419
"""
420
function coalesce end
421

422
coalesce() = missing
×
423
coalesce(x::Missing, y...) = coalesce(y...)
×
424
coalesce(x::Any, y...) = x
×
425

426

427
"""
428
    @coalesce(x...)
429

430
Short-circuiting version of [`coalesce`](@ref).
431

432
# Examples
433
```jldoctest
434
julia> f(x) = (println("f(\$x)"); missing);
435

436
julia> a = 1;
437

438
julia> a = @coalesce a f(2) f(3) error("`a` is still missing")
439
1
440

441
julia> b = missing;
442

443
julia> b = @coalesce b f(2) f(3) error("`b` is still missing")
444
f(2)
445
f(3)
446
ERROR: `b` is still missing
447
[...]
448
```
449

450
!!! compat "Julia 1.7"
451
    This macro is available as of Julia 1.7.
452
"""
453
macro coalesce(args...)
454
    expr = :(missing)
455
    for arg in reverse(args)
456
        expr = :(!ismissing((val = $(esc(arg));)) ? val : $expr)
457
    end
458
    return :(let val; $expr; end)
459
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc