Skip to content

Commit 6f6157a

Browse files
topolarityKristofferC
authored andcommitted
Make haskey(::@kwargs{item::Bool}, :item) constant-fold (#59320)
Resolves #59269. Resolves #59292.
1 parent be5bc79 commit 6f6157a

File tree

7 files changed

+31
-18
lines changed

7 files changed

+31
-18
lines changed

Compiler/test/inference.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6291,3 +6291,10 @@ end <: Bool
62916291
@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs
62926292
Core.get_binding_type(m, n, xs...)
62936293
end <: Type
6294+
6295+
# issue #59269
6296+
function haskey_inference_test()
6297+
kwargs = Core.compilerbarrier(:const, Base.pairs((; item = false)))
6298+
return haskey(kwargs, :item) ? nothing : Any[]
6299+
end
6300+
@inferred haskey_inference_test()

base/essentials.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,9 +489,9 @@ end
489489
Pairs{K, V, I, A}(data, itr) where {K, V, I, A} = $(Expr(:new, :(Pairs{K, V, I, A}), :(data isa A ? data : convert(A, data)), :(itr isa I ? itr : convert(I, itr))))
490490
Pairs{K, V}(data::A, itr::I) where {K, V, I, A} = $(Expr(:new, :(Pairs{K, V, I, A}), :data, :itr))
491491
Pairs{K}(data::A, itr::I) where {K, I, A} = $(Expr(:new, :(Pairs{K, eltype(A), I, A}), :data, :itr))
492-
Pairs(data::A, itr::I) where {I, A} = $(Expr(:new, :(Pairs{eltype(I), eltype(A), I, A}), :data, :itr))
492+
Pairs(data::A, itr::I) where {I, A} = $(Expr(:new, :(Pairs{I !== Nothing ? eltype(I) : keytype(A), eltype(A), I, A}), :data, :itr))
493493
end
494-
pairs(::Type{NamedTuple}) = Pairs{Symbol, V, NTuple{N, Symbol}, NamedTuple{names, T}} where {V, N, names, T<:NTuple{N, Any}}
494+
pairs(::Type{NamedTuple}) = Pairs{Symbol, V, Nothing, NT} where {V, NT <: NamedTuple}
495495

496496
"""
497497
Base.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)}

base/iterators.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,48 +267,48 @@ pairs(::IndexLinear, A::AbstractArray) = Pairs(A, LinearIndices(A))
267267
# preserve indexing capabilities for known indexable types
268268
# faster than zip(keys(a), values(a)) for arrays
269269
pairs(tuple::Tuple) = Pairs{Int}(tuple, keys(tuple))
270-
pairs(nt::NamedTuple) = Pairs{Symbol}(nt, keys(nt))
270+
pairs(nt::NamedTuple) = Pairs{Symbol}(nt, nothing)
271271
pairs(v::Core.SimpleVector) = Pairs(v, LinearIndices(v))
272272
pairs(A::AbstractVector) = pairs(IndexLinear(), A)
273273
# pairs(v::Pairs) = v # listed for reference, but already defined from being an AbstractDict
274274

275275
pairs(::IndexCartesian, A::AbstractArray) = Pairs(A, Base.CartesianIndices(axes(A)))
276276
pairs(A::AbstractArray) = pairs(IndexCartesian(), A)
277277

278-
length(v::Pairs) = length(getfield(v, :itr))
279-
axes(v::Pairs) = axes(getfield(v, :itr))
280-
size(v::Pairs) = size(getfield(v, :itr))
278+
length(v::Pairs) = length(keys(v))
279+
axes(v::Pairs) = axes(keys(v))
280+
size(v::Pairs) = size(keys(v))
281281

282282
Base.@eval @propagate_inbounds function _pairs_elt(p::Pairs{K, V}, idx) where {K, V}
283283
return $(Expr(:new, :(Pair{K, V}), :idx, :(getfield(p, :data)[idx])))
284284
end
285285

286286
@propagate_inbounds function iterate(p::Pairs{K, V}, state...) where {K, V}
287-
x = iterate(getfield(p, :itr), state...)
287+
x = iterate(keys(p), state...)
288288
x === nothing && return x
289289
idx, next = x
290290
return (_pairs_elt(p, idx), next)
291291
end
292292

293-
@propagate_inbounds function iterate(r::Reverse{<:Pairs}, state=(reverse(getfield(r.itr, :itr)),))
293+
@propagate_inbounds function iterate(r::Reverse{<:Pairs}, state=(reverse(keys(r.itr)),))
294294
x = iterate(state...)
295295
x === nothing && return x
296296
idx, next = x
297297
return (_pairs_elt(r.itr, idx), (state[1], next))
298298
end
299299

300-
@inline isdone(v::Pairs, state...) = isdone(getfield(v, :itr), state...)
300+
@inline isdone(v::Pairs, state...) = isdone(keys(v), state...)
301301

302302
IteratorSize(::Type{<:Pairs{<:Any, <:Any, I}}) where {I} = IteratorSize(I)
303303
IteratorSize(::Type{<:Pairs{<:Any, <:Any, <:AbstractUnitRange, <:Tuple}}) = HasLength()
304304

305305
function last(v::Pairs{K, V}) where {K, V}
306-
idx = last(getfield(v, :itr))
306+
idx = last(keys(v))
307307
return Pair{K, V}(idx, v[idx])
308308
end
309309

310-
haskey(v::Pairs, key) = (key in getfield(v, :itr))
311-
keys(v::Pairs) = getfield(v, :itr)
310+
haskey(v::Pairs, key) = key in keys(v)
311+
keys(v::Pairs) = getfield(v, :itr) === nothing ? keys(getfield(v, :data)) : getfield(v, :itr)
312312
values(v::Pairs) = getfield(v, :data) # TODO: this should be a view of data subset by itr
313313
getindex(v::Pairs, key) = getfield(v, :data)[key]
314314
setindex!(v::Pairs, value, key) = (getfield(v, :data)[key] = value; v)

base/namedtuple.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ merge(a::NamedTuple, b::NamedTuple{()}) = a
343343
merge(a::NamedTuple{()}, b::NamedTuple{()}) = a
344344
merge(a::NamedTuple{()}, b::NamedTuple) = b
345345

346-
merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, getfield(b, :data))
346+
merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,Nothing,<:NamedTuple}) = merge(a, getfield(b, :data))
347347

348348
merge(a::NamedTuple, b::Iterators.Zip{<:Tuple{Any,Any}}) = merge(a, NamedTuple{Tuple(b.is[1])}(b.is[2]))
349349

@@ -535,7 +535,7 @@ when it is printed in the stack trace view.
535535
536536
```julia
537537
julia> @Kwargs{init::Int} # the internal representation of keyword arguments
538-
Base.Pairs{Symbol, Int64, Tuple{Symbol}, @NamedTuple{init::Int64}}
538+
Base.Pairs{Symbol, Int64, Nothing, @NamedTuple{init::Int64}}
539539
540540
julia> sum("julia"; init=1)
541541
ERROR: MethodError: no method matching +(::Char, ::Char)
@@ -578,7 +578,7 @@ Stacktrace:
578578
macro Kwargs(ex)
579579
return :(let
580580
NT = @NamedTuple $ex
581-
Base.Pairs{keytype(NT),eltype(NT),typeof(NT.parameters[1]),NT}
581+
Base.Pairs{keytype(NT),eltype(NT),Nothing,NT}
582582
end)
583583
end
584584

base/show.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,8 @@ function show_type_name(io::IO, tn::Core.TypeName)
11061106
end
11071107

11081108
function maybe_kws_nt(x::DataType)
1109+
# manually-written version of
1110+
# x <: (Pairs{Symbol, eltype(NT), Nothing, NT} where NT <: NamedTuple)
11091111
x.name === typename(Pairs) || return nothing
11101112
length(x.parameters) == 4 || return nothing
11111113
x.parameters[1] === Symbol || return nothing
@@ -1115,7 +1117,7 @@ function maybe_kws_nt(x::DataType)
11151117
types isa DataType || return nothing
11161118
x.parameters[2] === eltype(p4) || return nothing
11171119
isa(syms, Tuple) || return nothing
1118-
x.parameters[3] === typeof(syms) || return nothing
1120+
x.parameters[3] === Nothing || return nothing
11191121
return p4
11201122
end
11211123
return nothing
@@ -3313,7 +3315,7 @@ function Base.showarg(io::IO, r::Iterators.Pairs{<:Integer, <:Any, <:Any, T}, to
33133315
print(io, "pairs(IndexLinear(), ::", T, ")")
33143316
end
33153317

3316-
function Base.showarg(io::IO, r::Iterators.Pairs{Symbol, <:Any, <:Any, T}, toplevel) where {T <: NamedTuple}
3318+
function Base.showarg(io::IO, r::Iterators.Pairs{Symbol, <:Any, Nothing, T}, toplevel) where {T <: NamedTuple}
33173319
print(io, "pairs(::NamedTuple)")
33183320
end
33193321

test/namedtuple.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ end
163163
@test merge(NamedTuple(), [:a=>1, :b=>2, :c=>3, :a=>4, :c=>5]) == (a=4, b=2, c=5)
164164
@test merge((c=0, z=1), [:a=>1, :b=>2, :c=>3, :a=>4, :c=>5]) == (c=5, z=1, a=4, b=2)
165165

166+
# https://github.com/JuliaLang/julia/issues/59292
167+
@test merge((; a = 1), Base.Pairs((; b = 2, c = 3), (:b,))) == (a = 1, b = 2)
168+
@test merge((; a = 1), Base.pairs((; b = 2, c = 3))) == (a = 1, b = 2, c = 3)
169+
166170
@test keys((a=1, b=2, c=3)) == (:a, :b, :c)
167171
@test keys(NamedTuple()) == ()
168172
@test keys((a=1,)) == (:a,)

test/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ test_repr("(:).a")
14481448
@test repr(@NamedTuple{var"#"::Int64}) == "@NamedTuple{var\"#\"::Int64}"
14491449

14501450
# Test general printing of `Base.Pairs` (it should not use the `@Kwargs` macro syntax)
1451-
@test repr(@Kwargs{init::Int}) == "Base.Pairs{Symbol, $Int, Tuple{Symbol}, @NamedTuple{init::$Int}}"
1451+
@test repr(@Kwargs{init::Int}) == "Base.Pairs{Symbol, $Int, Nothing, @NamedTuple{init::$Int}}"
14521452

14531453
@testset "issue #42931" begin
14541454
@test repr(NTuple{4, :A}) == "Tuple{:A, :A, :A, :A}"

0 commit comments

Comments
 (0)