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

JuliaLang / julia / #37594

pending completion
#37594

push

local

web-flow
Move `round(T::Type, x)` docstring above `round(z::Complex, ...)` docstring (#50775)

73676 of 84540 relevant lines covered (87.15%)

32579691.71 hits per line

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

93.12
/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")
31✔
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
8✔
16
end
17

18
showerror(io::IO, ex::MissingException) =
1✔
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(::Type{T}) where {T} = typesplit(T, Missing)
153,117✔
40

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

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

68
convert(::Type{T}, x::T) where {T>:Missing} = x
131,514✔
69
convert(::Type{T}, x::T) where {T>:Union{Missing, Nothing}} = x
2✔
70
convert(::Type{T}, x) where {T>:Missing} = convert(nonmissingtype_checked(T), x)
151,925✔
71
convert(::Type{T}, x) where {T>:Union{Missing, Nothing}} = convert(nonmissingtype_checked(nonnothingtype_checked(T)), x)
4✔
72

73
# Comparison operators
74
==(::Missing, ::Missing) = missing
34✔
75
==(::Missing, ::Any) = missing
23✔
76
==(::Any, ::Missing) = missing
10✔
77
# To fix ambiguity
78
==(::Missing, ::WeakRef) = missing
1✔
79
==(::WeakRef, ::Missing) = missing
1✔
80
isequal(::Missing, ::Missing) = true
7,518✔
81
isequal(::Missing, ::Any) = false
25✔
82
isequal(::Any, ::Missing) = false
10✔
83
<(::Missing, ::Missing) = missing
2✔
84
<(::Missing, ::Any) = missing
2✔
85
<(::Any, ::Missing) = missing
8✔
86
isless(::Missing, ::Missing) = false
93✔
87
isless(::Missing, ::Any) = false
47✔
88
isless(::Any, ::Missing) = true
41✔
89
isapprox(::Missing, ::Missing; kwargs...) = missing
2✔
90
isapprox(::Missing, ::Any; kwargs...) = missing
2✔
91
isapprox(::Any, ::Missing; kwargs...) = missing
2✔
92

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

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

128
div(::Missing, ::Missing, r::RoundingMode) = missing
2✔
129
div(::Missing, ::Number, r::RoundingMode) = missing
2✔
130
div(::Number, ::Missing, r::RoundingMode) = missing
2✔
131

132
min(::Missing, ::Missing) = missing
6,652✔
133
min(::Missing, ::Any)     = missing
444,440✔
134
min(::Any,     ::Missing) = missing
5,757✔
135
max(::Missing, ::Missing) = missing
6,651✔
136
max(::Missing, ::Any)     = missing
444,441✔
137
max(::Any,     ::Missing) = missing
5,756✔
138

139
missing_conversion_msg(@nospecialize T) =
4✔
140
    LazyString("cannot convert a missing value to type ", T, ": use Union{", T, ", Missing} instead")
141

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

153
# Handle ceil, floor, and trunc separately as they have no RoundingMode argument
154
for f in (:(ceil), :(floor), :(trunc))
155
    @eval begin
156
        ($f)(::Missing; sigdigits::Integer=0, digits::Integer=0, base::Integer=0) = missing
18✔
157
        ($f)(::Type{>:Missing}, ::Missing) = missing
3✔
158
        ($f)(::Type{T}, ::Missing) where {T} = throw(MissingException(missing_conversion_msg(T)))
3✔
159
        ($f)(::Type{T}, x::Any) where {T>:Missing} = $f(nonmissingtype_checked(T), x)
×
160
        # to fix ambiguities
161
        ($f)(::Type{T}, x::Rational) where {T>:Missing} = $f(nonmissingtype_checked(T), x)
×
162
        ($f)(::Type{T}, x::Real) where {T>:Missing} = $f(nonmissingtype_checked(T), x)
3✔
163
    end
164
end
165

166
# to avoid ambiguity warnings
167
(^)(::Missing, ::Integer) = missing
1✔
168

169
# Bit operators
170
(&)(::Missing, ::Missing) = missing
1✔
171
(&)(a::Missing, b::Bool) = ifelse(b, missing, false)
6✔
172
(&)(b::Bool, a::Missing) = ifelse(b, missing, false)
20✔
173
(&)(::Missing, ::Integer) = missing
3✔
174
(&)(::Integer, ::Missing) = missing
3✔
175
(|)(::Missing, ::Missing) = missing
×
176
(|)(a::Missing, b::Bool) = ifelse(b, true, missing)
8✔
177
(|)(b::Bool, a::Missing) = ifelse(b, true, missing)
9,624✔
178
(|)(::Missing, ::Integer) = missing
3✔
179
(|)(::Integer, ::Missing) = missing
3✔
180
xor(::Missing, ::Missing) = missing
1✔
181
xor(a::Missing, b::Bool) = missing
2✔
182
xor(b::Bool, a::Missing) = missing
2✔
183
xor(::Missing, ::Integer) = missing
1✔
184
xor(::Integer, ::Missing) = missing
1✔
185

186
*(d::Missing, x::Union{AbstractString,AbstractChar}) = missing
2✔
187
*(d::Union{AbstractString,AbstractChar}, x::Missing) = missing
2✔
188

189
function float(A::AbstractArray{Union{T, Missing}}) where {T}
6✔
190
    U = typeof(float(zero(T)))
6✔
191
    convert(AbstractArray{Union{U, Missing}}, A)
6✔
192
end
193
float(A::AbstractArray{Missing}) = A
2✔
194

195
"""
196
    skipmissing(itr)
197

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

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

208
See also [`coalesce`](@ref), [`ismissing`](@ref), [`something`](@ref).
209

210
# Examples
211
```jldoctest
212
julia> x = skipmissing([1, missing, 2])
213
skipmissing(Union{Missing, Int64}[1, missing, 2])
214

215
julia> sum(x)
216
3
217

218
julia> x[1]
219
1
220

221
julia> x[2]
222
ERROR: MissingException: the value at index (2,) is missing
223
[...]
224

225
julia> argmax(x)
226
3
227

228
julia> collect(keys(x))
229
2-element Vector{Int64}:
230
 1
231
 3
232

233
julia> collect(skipmissing([1, missing, 2]))
234
2-element Vector{Int64}:
235
 1
236
 2
237

238
julia> collect(skipmissing([1 missing; 2 missing]))
239
2-element Vector{Int64}:
240
 1
241
 2
242
```
243
"""
244
skipmissing(itr) = SkipMissing(itr)
369✔
245

246
struct SkipMissing{T}
247
    x::T
369✔
248
end
249
IteratorSize(::Type{<:SkipMissing}) = SizeUnknown()
252✔
250
IteratorEltype(::Type{SkipMissing{T}}) where {T} = IteratorEltype(T)
268✔
251
eltype(::Type{SkipMissing{T}}) where {T} = nonmissingtype(eltype(T))
696✔
252

253
function iterate(itr::SkipMissing, state...)
98,546✔
254
    y = iterate(itr.x, state...)
98,814✔
255
    y === nothing && return nothing
98,546✔
256
    item, state = y
98,282✔
257
    while item === missing
126,678✔
258
        y = iterate(itr.x, state)
28,412✔
259
        y === nothing && return nothing
28,402✔
260
        item, state = y
28,396✔
261
    end
28,396✔
262
    item, state
98,276✔
263
end
264

265
IndexStyle(::Type{<:SkipMissing{T}}) where {T} = IndexStyle(T)
×
266
eachindex(itr::SkipMissing) =
4✔
267
    Iterators.filter(i -> @inbounds(itr.x[i]) !== missing, eachindex(itr.x))
11✔
268
keys(itr::SkipMissing) =
30✔
269
    Iterators.filter(i -> @inbounds(itr.x[i]) !== missing, keys(itr.x))
74✔
270
@propagate_inbounds function getindex(itr::SkipMissing, I...)
16✔
271
    v = itr.x[I...]
16✔
272
    v === missing && throw(MissingException(LazyString("the value at index ", I, " is missing")))
9✔
273
    v
6✔
274
end
275

276
function show(io::IO, s::SkipMissing)
4✔
277
    print(io, "skipmissing(")
4✔
278
    show(io, s.x)
4✔
279
    print(io, ')')
4✔
280
end
281

282
# Optimized mapreduce implementation
283
# The generic method is faster when !(eltype(A) >: Missing) since it does not need
284
# additional loops to identify the two first non-missing values of each block
285
mapreduce(f, op, itr::SkipMissing{<:AbstractArray}) =
114✔
286
    _mapreduce(f, op, IndexStyle(itr.x), eltype(itr.x) >: Missing ? itr : itr.x)
287

288
function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray})
72✔
289
    A = itr.x
72✔
290
    ai = missing
72✔
291
    inds = LinearIndices(A)
72✔
292
    i = first(inds)
72✔
293
    ilast = last(inds)
72✔
294
    for outer i in i:ilast
139✔
295
        @inbounds ai = A[i]
35,234✔
296
        ai !== missing && break
35,234✔
297
    end
35,188✔
298
    ai === missing && return mapreduce_empty(f, op, eltype(itr))
72✔
299
    a1::eltype(itr) = ai
46✔
300
    i == typemax(typeof(i)) && return mapreduce_first(f, op, a1)
46✔
301
    i += 1
45✔
302
    ai = missing
45✔
303
    for outer i in i:ilast
86✔
304
        @inbounds ai = A[i]
58✔
305
        ai !== missing && break
58✔
306
    end
18✔
307
    ai === missing && return mapreduce_first(f, op, a1)
45✔
308
    # We know A contains at least two non-missing entries: the result cannot be nothing
309
    something(mapreduce_impl(f, op, itr, first(inds), last(inds)))
40✔
310
end
311

312
_mapreduce(f, op, ::IndexCartesian, itr::SkipMissing) = mapfoldl(f, op, itr)
×
313

314
mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) =
40✔
315
    mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op))
316

317
# Returns nothing when the input contains only missing values, and Some(x) otherwise
318
@noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray},
402✔
319
                                  ifirst::Integer, ilast::Integer, blksize::Int)
320
    A = itr.x
402✔
321
    if ifirst > ilast
402✔
322
        return nothing
×
323
    elseif ifirst == ilast
402✔
324
        @inbounds a1 = A[ifirst]
×
325
        if a1 === missing
×
326
            return nothing
×
327
        else
328
            return Some(mapreduce_first(f, op, a1))
×
329
        end
330
    elseif ilast - ifirst < blksize
402✔
331
        # sequential portion
332
        ai = missing
221✔
333
        i = ifirst
221✔
334
        for outer i in i:ilast
442✔
335
            @inbounds ai = A[i]
33,350✔
336
            ai !== missing && break
33,350✔
337
        end
33,177✔
338
        ai === missing && return nothing
221✔
339
        a1 = ai::eltype(itr)
173✔
340
        i == typemax(typeof(i)) && return Some(mapreduce_first(f, op, a1))
173✔
341
        i += 1
173✔
342
        ai = missing
173✔
343
        for outer i in i:ilast
346✔
344
            @inbounds ai = A[i]
323✔
345
            ai !== missing && break
323✔
346
        end
150✔
347
        ai === missing && return Some(mapreduce_first(f, op, a1))
173✔
348
        a2 = ai::eltype(itr)
173✔
349
        i == typemax(typeof(i)) && return Some(op(f(a1), f(a2)))
173✔
350
        i += 1
172✔
351
        v = op(f(a1), f(a2))
172✔
352
        @simd for i = i:ilast
174✔
353
            @inbounds ai = A[i]
100,509✔
354
            if ai !== missing
100,509✔
355
                v = op(v, f(ai))
51,435✔
356
            end
357
        end
×
358
        return Some(v)
172✔
359
    else
360
        # pairwise portion
361
        imid = ifirst + (ilast - ifirst) >> 1
181✔
362
        v1 = mapreduce_impl(f, op, itr, ifirst, imid, blksize)
181✔
363
        v2 = mapreduce_impl(f, op, itr, imid+1, ilast, blksize)
181✔
364
        if v1 === nothing && v2 === nothing
181✔
365
            return nothing
42✔
366
        elseif v1 === nothing
139✔
367
            return v2
6✔
368
        elseif v2 === nothing
133✔
369
            return v1
×
370
        else
371
            return Some(op(something(v1), something(v2)))
133✔
372
        end
373
    end
374
end
375

376
"""
377
    filter(f, itr::SkipMissing{<:AbstractArray})
378

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

382
!!! compat "Julia 1.2"
383
    This method requires Julia 1.2 or later.
384

385
# Examples
386
```jldoctest
387
julia> x = [1 2; missing 4]
388
2×2 Matrix{Union{Missing, Int64}}:
389
 1         2
390
  missing  4
391

392
julia> filter(isodd, skipmissing(x))
393
1-element Vector{Int64}:
394
 1
395
```
396
"""
397
function filter(f, itr::SkipMissing{<:AbstractArray})
3✔
398
    y = similar(itr.x, eltype(itr), 0)
3✔
399
    for xi in itr.x
3✔
400
        if xi !== missing && f(xi)
18✔
401
            push!(y, xi)
6✔
402
        end
403
    end
21✔
404
    y
3✔
405
end
406

407
"""
408
    coalesce(x...)
409

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

413
See also [`skipmissing`](@ref), [`something`](@ref), [`@coalesce`](@ref).
414

415
# Examples
416

417
```jldoctest
418
julia> coalesce(missing, 1)
419
1
420

421
julia> coalesce(1, missing)
422
1
423

424
julia> coalesce(nothing, 1)  # returns `nothing`
425

426
julia> coalesce(missing, missing)
427
missing
428
```
429
"""
430
function coalesce end
431

432
coalesce() = missing
4✔
433
coalesce(x::Missing, y...) = coalesce(y...)
11✔
434
coalesce(x::Any, y...) = x
9✔
435

436

437
"""
438
    @coalesce(x...)
439

440
Short-circuiting version of [`coalesce`](@ref).
441

442
# Examples
443
```jldoctest
444
julia> f(x) = (println("f(\$x)"); missing);
445

446
julia> a = 1;
447

448
julia> a = @coalesce a f(2) f(3) error("`a` is still missing")
449
1
450

451
julia> b = missing;
452

453
julia> b = @coalesce b f(2) f(3) error("`b` is still missing")
454
f(2)
455
f(3)
456
ERROR: `b` is still missing
457
[...]
458
```
459

460
!!! compat "Julia 1.7"
461
    This macro is available as of Julia 1.7.
462
"""
463
macro coalesce(args...)
6✔
464
    expr = :(missing)
6✔
465
    for arg in reverse(args)
6✔
466
        expr = :((val = $arg) !== missing ? val : $expr)
7✔
467
    end
7✔
468
    return esc(:(let val; $expr; end))
6✔
469
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