diff --git a/NEWS.md b/NEWS.md index 7d1277a02dc3a..5b6f89bce201d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -738,6 +738,10 @@ Deprecated or removed * The `sum_kbn` and `cumsum_kbn` functions have been moved to the [KahanSummation](https://github.com/JuliaMath/KahanSummation.jl) package ([#24869]). + * Iteration (`next`, `eltype`, `in`, `map`, etc) on `Associative`s has been deprecated. + Explicitly nominate `pairs(dict)`, `values(dict)` or `keys(dict)` as appropriate + ([#25013]). + Command-line option changes --------------------------- diff --git a/base/associative.jl b/base/associative.jl index f3719ba65eaac..56c39590c55a8 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -16,20 +16,6 @@ const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ haskey(d::Associative, k) = in(k, keys(d)) -function in(p::Pair, a::Associative, valcmp=(==)) - v = get(a,p[1],secret_table_token) - if v !== secret_table_token - valcmp(v, p[2]) && return true - end - return false -end - -function in(p, a::Associative) - error("""Associative collections only contain Pairs; - Either look for e.g. A=>B instead, or use the `keys` or `values` - function if you are looking for a key or value respectively.""") -end - function summary(t::Associative) n = length(t) return string(typeof(t), " with ", n, (n==1 ? " entry" : " entries")) @@ -44,26 +30,38 @@ struct ValueIterator{T<:Associative} dict::T end -summary(iter::T) where {T<:Union{KeySet,ValueIterator}} = +struct PairIterator{T<:Associative} + dict::T +end + +function in(p::Pair, a::PairIterator, valcmp=(==)) + v = get(a.dict, p[1], secret_table_token) + if v !== secret_table_token + valcmp(v, p[2]) && return true + end + return false +end + +summary(iter::T) where {T<:Union{KeySet,ValueIterator,PairIterator}} = string(T.name, " for a ", summary(iter.dict)) -show(io::IO, iter::Union{KeySet,ValueIterator}) = show(io, collect(iter)) +show(io::IO, iter::Union{KeySet,ValueIterator,PairIterator}) = show(io, collect(iter)) -length(v::Union{KeySet,ValueIterator}) = length(v.dict) -isempty(v::Union{KeySet,ValueIterator}) = isempty(v.dict) -_tt2(::Type{Pair{A,B}}) where {A,B} = B -eltype(::Type{ValueIterator{D}}) where {D} = _tt2(eltype(D)) +length(v::Union{KeySet,ValueIterator,PairIterator}) = length(v.dict) +isempty(v::Union{KeySet,ValueIterator,PairIterator}) = isempty(v.dict) +eltype(::Type{ValueIterator{D}}) where {D} = valtype(D) +eltype(::Type{PairIterator{D}}) where {D} = pairtype(D) -start(v::Union{KeySet,ValueIterator}) = start(v.dict) -done(v::Union{KeySet,ValueIterator}, state) = done(v.dict, state) +start(v::Union{KeySet,ValueIterator,PairIterator}) = start(v.dict) +done(v::Union{KeySet,ValueIterator,PairIterator}, state) = done(v.dict, state) function next(v::KeySet, state) - n = next(v.dict, state) + n = next(PairIterator(v.dict), state) n[1][1], n[2] end function next(v::ValueIterator, state) - n = next(v.dict, state) + n = next(PairIterator(v.dict), state) n[1][2], n[2] end @@ -136,7 +134,13 @@ This includes arrays, where the keys are the array indices. """ pairs(collection) = Generator(=>, keys(collection), values(collection)) -pairs(a::Associative) = a +pairs(a::Associative) = PairIterator(a) + +function next(a::Associative, i) + println("next(::Associative, ::Any) is deprecated.") + display(stacktrace()); println() # TODO remove after problems fixed + next(PairIterator(a), i) +end """ empty(a::Associative, [index_type=keytype(a)], [value_type=valtype(a)]) @@ -155,7 +159,7 @@ empty(a::Associative, ::Type{V}) where {V} = empty(a, keytype(a), V) # Note: thi function copy(a::Associative) b = empty(a) - for (k,v) in a + for (k,v) in pairs(a) b[k] = v end return b @@ -184,7 +188,7 @@ Dict{Int64,Int64} with 3 entries: """ function merge!(d::Associative, others::Associative...) for other in others - for (k,v) in other + for (k,v) in pairs(other) d[k] = v end end @@ -223,7 +227,7 @@ Dict{Int64,Int64} with 3 entries: """ function merge!(combine::Function, d::Associative, others::Associative...) for other in others - for (k,v) in other + for (k,v) in pairs(other) d[k] = haskey(d, k) ? combine(d[k], v) : v end end @@ -250,9 +254,9 @@ julia> keytype(Dict(Int32(1) => "foo")) Int32 ``` """ -keytype(::Type{Associative{K,V}}) where {K,V} = K +keytype(::Type{Associative{K, V}}) where {K, V} = K keytype(a::Associative) = keytype(typeof(a)) -keytype(::Type{A}) where {A<:Associative} = keytype(supertype(A)) +keytype(::Type{A}) where {A <: Associative} = keytype(supertype(A)) """ valtype(type) @@ -265,10 +269,25 @@ julia> valtype(Dict(Int32(1) => "foo")) String ``` """ -valtype(::Type{Associative{K,V}}) where {K,V} = V -valtype(::Type{A}) where {A<:Associative} = valtype(supertype(A)) +valtype(::Type{Associative{K, V}}) where {K, V} = V +valtype(::Type{A}) where {A <: Associative} = valtype(supertype(A)) valtype(a::Associative) = valtype(typeof(a)) +""" + pairtype(type) + +Get the `Pair` type of an associative collection type. Behaves similarly to [`eltype`](@ref). + +# Examples +```jldoctest +julia> pairtype(Dict(Int32(1) => "foo")) +Pair{Int32,String} +``` +""" +pairtype(::Type{Associative{K, V}}) where {K, V} = Pair{K, V} +pairtype(::Type{A}) where {A <: Associative} = pairtype(supertype(A)) +pairtype(a::Associative) = pairtype(typeof(a)) + """ merge(d::Associative, others::Associative...) @@ -368,7 +387,7 @@ Dict{Int64,String} with 2 entries: function filter!(f, d::Associative) badkeys = Vector{keytype(d)}() try - for pair in d + for pair in pairs(d) # don't delete!(d, k) here, since associative types # may not support mutation during iteration f(pair) || push!(badkeys, pair.first) @@ -384,7 +403,7 @@ end function filter_in_one_pass!(f, d::Associative) try - for pair in d + for pair in pairs(d) if !f(pair) delete!(d, pair.first) end @@ -399,7 +418,7 @@ function filter!_dict_deprecation(e, f, d::Associative) if isa(e, MethodError) && e.f === f depwarn("In `filter!(f, dict)`, `f` is now passed a single pair instead of two arguments.", :filter!) badkeys = Vector{keytype(d)}() - for (k,v) in d + for (k,v) in pairs(d) # don't delete!(d, k) here, since associative types # may not support mutation during iteration f(k, v) || push!(badkeys, k) @@ -435,7 +454,7 @@ function filter(f, d::Associative) # don't just do filter!(f, copy(d)): avoid making a whole copy of d df = empty(d) try - for pair in d + for pair in pairs(d) if f(pair) df[pair.first] = pair.second end @@ -443,7 +462,7 @@ function filter(f, d::Associative) catch e if isa(e, MethodError) && e.f === f depwarn("In `filter(f, dict)`, `f` is now passed a single pair instead of two arguments.", :filter) - for (k, v) in d + for (k, v) in pairs(d) if f(k, v) df[k] = v end @@ -455,16 +474,14 @@ function filter(f, d::Associative) return df end -eltype(::Type{Associative{K,V}}) where {K,V} = Pair{K,V} - function isequal(l::Associative, r::Associative) l === r && return true if isa(l,ObjectIdDict) != isa(r,ObjectIdDict) return false end if length(l) != length(r) return false end - for pair in l - if !in(pair, r, isequal) + for pair in pairs(l) + if !in(pair, pairs(r), isequal) return false end end @@ -477,8 +494,8 @@ function ==(l::Associative, r::Associative) return false end if length(l) != length(r) return false end - for pair in l - if !in(pair, r, ==) + for pair in pairs(l) + if !in(pair, pairs(r), ==) return false end end @@ -488,7 +505,7 @@ end const hasha_seed = UInt === UInt64 ? 0x6d35bb51952d5539 : 0x952d5539 function hash(a::Associative, h::UInt) hv = hasha_seed - for (k,v) in a + for (k,v) in pairs(a) hv ⊻= hash(k, hash(v)) end hash(hv, h) @@ -599,11 +616,11 @@ _oidd_nextind(a, i) = reinterpret(Int,ccall(:jl_eqtable_nextind, Csize_t, (Any, start(t::ObjectIdDict) = _oidd_nextind(t.ht, 0) done(t::ObjectIdDict, i) = (i == -1) -next(t::ObjectIdDict, i) = (Pair{Any,Any}(t.ht[i+1],t.ht[i+2]), _oidd_nextind(t.ht, i+2)) +next(t::PairIterator{<:ObjectIdDict}, i) = (Pair{Any,Any}(t.dict.ht[i+1],t.dict.ht[i+2]), _oidd_nextind(t.dict.ht, i+2)) function length(d::ObjectIdDict) n = 0 - for pair in d + for pair in pairs(d) n+=1 end n diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 2f22a32679697..aca6f3fb632fa 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -107,7 +107,7 @@ function deepcopy_internal(x::Dict, stackdict::ObjectIdDict) dest = empty(x) stackdict[x] = dest - for (k, v) in x + for (k, v) in pairs(x) dest[deepcopy_internal(k, stackdict)] = deepcopy_internal(v, stackdict) end dest diff --git a/base/deprecated.jl b/base/deprecated.jl index 68960bb291104..e8278f9b38f00 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2186,6 +2186,11 @@ end @deprecate_moved sum_kbn "KahanSummation" @deprecate_moved cumsum_kbn "KahanSummation" +# PR #25013 +@deprecate eltype(A::Type{Associative{K,V}}) where {K,V} pairtype(A) +@deprecate next(a::Associative, i) next(pairs(a), i) +#@deprecate Base.in(p::Pair, a::Associative, valcmp = (==)) Base.in(p, PairIterator(a), valcmp) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/dict.jl b/base/dict.jl index bd3ac41287e55..41a3ccf09674c 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -43,7 +43,7 @@ function show(io::IO, t::Associative{K,V}) where V where K if !show_circular(io, t) first = true n = 0 - for pair in t + for pair in pairs(t) first || print(io, ',') first = false show(recur_io, pair) @@ -139,9 +139,12 @@ Dict(ps::Pair{K}...) where {K} = Dict{K,Any}(ps) Dict(ps::(Pair{K,V} where K)...) where {V} = Dict{Any,V}(ps) Dict(ps::Pair...) = Dict{Any,Any}(ps) +pair_or_eltype(x) = eltype(x) +pair_or_eltype(x::Associative) = pairtype(x) + function Dict(kv) try - associative_with_eltype((K, V) -> Dict{K, V}, kv, eltype(kv)) + associative_with_eltype((K, V) -> Dict{K, V}, kv, pair_or_eltype(kv)) catch e if !applicable(start, kv) || !all(x->isa(x,Union{Tuple,Pair}),kv) throw(ArgumentError("Dict(kv): kv needs to be an iterator of tuples or pairs")) @@ -193,7 +196,7 @@ empty(a::Associative, ::Type{K}, ::Type{V}) where {K, V} = Dict{K, V}() # conversion between Dict types function convert(::Type{Dict{K,V}},d::Associative) where V where K h = Dict{K,V}() - for (k,v) in d + for (k,v) in pairs(d) ck = convert(K,k) if !haskey(h,ck) h[ck] = convert(V,v) @@ -711,8 +714,8 @@ function start(t::Dict) return i end done(t::Dict, i) = i > length(t.vals) -@propagate_inbounds function next(t::Dict{K,V}, i) where {K,V} - return (Pair{K,V}(t.keys[i],t.vals[i]), skip_deleted(t,i+1)) +@propagate_inbounds function next(t::PairIterator{Dict{K,V}}, i) where {K,V} + return (Pair{K,V}(t.dict.keys[i],t.dict.vals[i]), skip_deleted(t.dict,i+1)) end isempty(t::Dict) = (t.count == 0) @@ -756,11 +759,11 @@ ImmutableDict ImmutableDict(KV::Pair{K,V}) where {K,V} = ImmutableDict{K,V}(KV[1], KV[2]) ImmutableDict(t::ImmutableDict{K,V}, KV::Pair) where {K,V} = ImmutableDict{K,V}(t, KV[1], KV[2]) -function in(key_value::Pair, dict::ImmutableDict, valcmp=(==)) +function in(key_value::Pair, dict::PairIterator{<:ImmutableDict}, valcmp=(==)) key, value = key_value while isdefined(dict, :parent) - if dict.key == key - valcmp(value, dict.value) && return true + if dict.dict.key == key + valcmp(value, dict.dict.value) && return true end dict = dict.parent end @@ -792,7 +795,7 @@ end # this actually defines reverse iteration (e.g. it should not be used for merge/copy/filter type operations) start(t::ImmutableDict) = t -next(::ImmutableDict{K,V}, t) where {K,V} = (Pair{K,V}(t.key, t.value), t.parent) +next(::PairIterator{ImmutableDict{K,V}}, t) where {K,V} = (Pair{K,V}(t.key, t.value), t.parent) done(::ImmutableDict, t) = !isdefined(t, :parent) length(t::ImmutableDict) = count(x->true, t) isempty(t::ImmutableDict) = done(t, start(t)) diff --git a/base/docs/utils.jl b/base/docs/utils.jl index b4a1f4eb947ec..66f245d98d190 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -139,7 +139,7 @@ repl_corrections(s) = repl_corrections(STDOUT, s) const symbols_latex = Dict{String,String}() function symbol_latex(s::String) if isempty(symbols_latex) - for (k,v) in Base.REPLCompletions.latex_symbols + for (k,v) in pairs(Base.REPLCompletions.latex_symbols) symbols_latex[v] = k end end diff --git a/base/env.jl b/base/env.jl index e7849373e308f..379532f10b845 100644 --- a/base/env.jl +++ b/base/env.jl @@ -81,7 +81,7 @@ pop!(::EnvDict, k::AbstractString) = (v = ENV[k]; _unsetenv(k); v) pop!(::EnvDict, k::AbstractString, def) = haskey(ENV,k) ? pop!(ENV,k) : def delete!(::EnvDict, k::AbstractString) = (_unsetenv(k); ENV) setindex!(::EnvDict, v, k::AbstractString) = _setenv(k,string(v)) -push!(::EnvDict, k::AbstractString, v) = setindex!(ENV, v, k) +push!(::EnvDict, k::AbstractString, v) = setindex!(ENV, v, k) # Should this be a `Pair`? if Sys.iswindows() start(hash::EnvDict) = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) @@ -92,7 +92,7 @@ if Sys.iswindows() end return false end - function next(hash::EnvDict, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) + function next(hash::PairIterator{EnvDict}, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) pos = block[1] blk = block[2] len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) @@ -109,7 +109,7 @@ else # !windows start(::EnvDict) = 0 done(::EnvDict, i) = (ccall(:jl_environ, Any, (Int32,), i) === nothing) - function next(::EnvDict, i) + function next(::PairIterator{EnvDict}, i) env = ccall(:jl_environ, Any, (Int32,), i) if env === nothing throw(BoundsError()) @@ -126,7 +126,7 @@ end # os-test #TODO: Make these more efficent function length(::EnvDict) i = 0 - for (k,v) in ENV + for (k,v) in pairs(ENV) i += 1 end return i diff --git a/base/exports.jl b/base/exports.jl index ed3f5d2b34b49..85b7cd29d300c 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -82,6 +82,7 @@ export ObjectIdDict, OrdinalRange, Pair, + PairIterator, PartialQuickSort, PermutedDimsArray, QuickSort, diff --git a/base/inference.jl b/base/inference.jl index 6b5f867eabf7f..190ecb36a2ab4 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -5686,7 +5686,7 @@ function remove_redundant_temp_vars!(src::CodeInfo, nargs::Int, sa::ObjectIdDict slottypes = src.slottypes ssavaluetypes = src.ssavaluetypes repls = ObjectIdDict() - for (v, init) in sa + for (v, init) in pairs(sa) repl = get_replacement(sa, v, init, nargs, slottypes, ssavaluetypes) compare = isa(repl, TypedSlot) ? normslot(repl) : repl if compare !== v diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index fdad979f6b664..1165a6ce7becd 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -314,13 +314,13 @@ function versioninfo(io::IO=STDOUT; verbose::Bool=false, packages::Bool=false) println(io, " LLVM: libLLVM-",libllvm_version," (", Sys.JIT, ", ", Sys.cpu_name, ")") println(io, "Environment:") - for (k,v) in ENV + for (k,v) in pairs(ENV) if ismatch(r"JULIA", String(k)) println(io, " $(k) = $(v)") end end if verbose - for (k,v) in ENV + for (k,v) in pairs(ENV) if ismatch(r"PATH|FLAG|^TERM$|HOME", String(k)) println(io, " $(k) = $(v)") end diff --git a/base/process.jl b/base/process.jl index 0d56aaee5b2f1..3d80dd00ba574 100644 --- a/base/process.jl +++ b/base/process.jl @@ -208,7 +208,7 @@ end byteenv(env::AbstractArray{<:AbstractString}) = String[cstr(x) for x in env] byteenv(env::Associative) = - String[cstr(string(k)*"="*string(v)) for (k,v) in env] + String[cstr(string(k)*"="*string(v)) for (k,v) in pairs(env)] byteenv(env::Void) = nothing byteenv(env::Union{AbstractVector{Pair{T}}, Tuple{Vararg{Pair{T}}}}) where {T<:AbstractString} = String[cstr(k*"="*string(v)) for (k,v) in env] diff --git a/base/repl/LineEdit.jl b/base/repl/LineEdit.jl index 5e09ce730b6c6..da5dff938bc07 100644 --- a/base/repl/LineEdit.jl +++ b/base/repl/LineEdit.jl @@ -1233,7 +1233,7 @@ end function normalize_keys(keymap::Dict) ret = Dict{Any,Any}() - for (k,v) in keymap + for (k,v) in pairs(keymap) normalized = normalize_key(k) if haskey(ret,normalized) error("""Multiple spellings of a key in a single keymap @@ -1396,7 +1396,7 @@ function postprocess!(dict::Dict) if haskey(dict, wildcard) add_specialisations(dict, dict, 1) end - for (k,v) in dict + for (k,v) in pairs(dict) k == wildcard && continue postprocess!(v) end @@ -2179,7 +2179,7 @@ function reset_state(s::PromptState) end function reset_state(s::MIState) - for (mode, state) in s.mode_state + for (mode, state) in pairs(s.mode_state) reset_state(state) end end diff --git a/base/repl/REPL.jl b/base/repl/REPL.jl index c291bd7de8ca4..2bfdc64887c51 100644 --- a/base/repl/REPL.jl +++ b/base/repl/REPL.jl @@ -432,7 +432,7 @@ end function mode_idx(hist::REPLHistoryProvider, mode) c = :julia - for (k,v) in hist.mode_mapping + for (k,v) in pairs(hist.mode_mapping) isequal(v, mode) && (c = k) end return c diff --git a/base/replutil.jl b/base/replutil.jl index 65a72b0864007..9258b7e4d9939 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -59,7 +59,7 @@ function show(io::IO, ::MIME"text/plain", t::Associative{K,V}) where {K,V} vs = Vector{AbstractString}(uninitialized, min(rows, length(t))) keylen = 0 vallen = 0 - for (i, (k, v)) in enumerate(t) + for (i, (k, v)) in enumerate(pairs(t)) i > rows && break ks[i] = sprint(0, show, k, env=recur_io) vs[i] = sprint(0, show, v, env=recur_io) @@ -73,7 +73,7 @@ function show(io::IO, ::MIME"text/plain", t::Associative{K,V}) where {K,V} rows = cols = typemax(Int) end - for (i, (k, v)) in enumerate(t) + for (i, (k, v)) in enumerate(pairs(t)) print(io, "\n ") i == rows < length(t) && (print(io, rpad("⋮", keylen), " => ⋮"); break) diff --git a/base/serialize.jl b/base/serialize.jl index 2efe10e480de6..0f6b8149be028 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -345,7 +345,7 @@ end function serialize(s::AbstractSerializer, d::Dict) serialize_cycle_header(s, d) && return write(s.io, Int32(length(d))) - for (k,v) in d + for (k,v) in pairs(d) serialize(s, k) serialize(s, v) end diff --git a/base/show.jl b/base/show.jl index 15ab70c465584..9e051c865ea25 100644 --- a/base/show.jl +++ b/base/show.jl @@ -94,7 +94,7 @@ pipe_writer(io::IOContext) = io.io lock(io::IOContext) = lock(io.io) unlock(io::IOContext) = unlock(io.io) -in(key_value::Pair, io::IOContext) = in(key_value, io.dict, ===) +in(key_value::Pair, io::IOContext) = in(key_value, pairs(io.dict), ===) in(key_value::Pair, io::IO) = false haskey(io::IOContext, key) = haskey(io.dict, key) haskey(io::IO, key) = false @@ -108,7 +108,7 @@ displaysize(io::IOContext) = haskey(io, :displaysize) ? io[:displaysize] : displ show_circular(io::IO, @nospecialize(x)) = false function show_circular(io::IOContext, @nospecialize(x)) d = 1 - for (k, v) in io.dict + for (k, v) in pairs(io.dict) if k === :SHOWN_SET if v === x print(io, "#= circular reference @-$d =#") @@ -215,7 +215,7 @@ end has_typevar(@nospecialize(t), v::TypeVar) = ccall(:jl_has_typevar, Cint, (Any, Any), t, v)!=0 function io_has_tvar_name(io::IOContext, name::Symbol, @nospecialize(x)) - for (key, val) in io.dict + for (key, val) in pairs(io.dict) if key === :unionall_env && val isa TypeVar && val.name === name && has_typevar(x, val) return true end diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 4cb4f3ce8f3b7..5cc6d51d5669f 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -244,7 +244,7 @@ function sparsevec(dict::Associative{Ti,Tv}) where {Tv,Ti<:Integer} cnt = 0 len = zero(Ti) - for (k, v) in dict + for (k, v) in pairs(dict) k >= 1 || throw(ArgumentError("index must be positive.")) if k > len len = k @@ -265,7 +265,7 @@ function sparsevec(dict::Associative{Ti,Tv}, len::Integer) where {Tv,Ti<:Integer cnt = 0 maxk = convert(Ti, len) - for (k, v) in dict + for (k, v) in pairs(dict) 1 <= k <= maxk || throw(ArgumentError("an index (key) is out of bound.")) cnt += 1 @inbounds nzind[cnt] = k diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index f07d2f29f5ea0..49422260719ad 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -73,7 +73,7 @@ empty(d::WeakKeyDict, ::Type{K}, ::Type{V}) where {K, V} = WeakKeyDict{K, V}() # conversion between Dict types function convert(::Type{WeakKeyDict{K,V}},d::Associative) where V where K h = WeakKeyDict{K,V}() - for (k,v) in d + for (k,v) in pairs(d) ck = convert(K,k) if !haskey(h,ck) h[ck] = convert(V,v) @@ -132,9 +132,9 @@ function start(t::WeakKeyDict{K,V}) where V where K return (start(t.ht), gc_token) end done(t::WeakKeyDict, i) = done(t.ht, i[1]) -function next(t::WeakKeyDict{K,V}, i) where V where K +function next(t::PairIterator{WeakKeyDict{K,V}}, i) where V where K gc_token = i[2] - wkv, i = next(t.ht, i[1]) + wkv, i = next(PairIterator(t.dict.ht), i[1]) kv = Pair{K,V}(wkv[1].value::K, wkv[2]) return (kv, (i, gc_token)) end diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 916834c42bf3b..b4a53c76eef06 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1420,14 +1420,14 @@ struct GenericDict{K,V} <: Associative{K,V} s::Associative{K,V} end -for (G, A) in ((GenericSet, AbstractSet), - (GenericDict, Associative)) +for (G, I, A) in ((GenericSet, GenericSet, AbstractSet), + (GenericDict, PairIterator{<:GenericSet}, Associative)) @eval begin Base.convert(::Type{$G}, s::$A) = $G(s) Base.done(s::$G, state) = done(s.s, state) - Base.next(s::$G, state) = next(s.s, state) + Base.next(s::$I, state) = next(s.s, state) end - for f in (:eltype, :isempty, :length, :start) + for f in (:isempty, :length, :start) @eval begin Base.$f(s::$G) = $f(s.s) end diff --git a/test/dict.jl b/test/dict.jl index 7212022e51ea4..1b674c662129d 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -77,13 +77,13 @@ end h["a","b","c"] = 4 @test h["a","b","c"] == h[("a","b","c")] == 4 - @testset "eltype, keytype and valtype" begin - @test eltype(h) == Pair{Any,Any} + @testset "pairtype, keytype and valtype" begin + @test pairtype(h) == Pair{Any,Any} @test keytype(h) == Any @test valtype(h) == Any td = Dict{AbstractString,Float64}() - @test eltype(td) == Pair{AbstractString,Float64} + @test pairtype(td) == Pair{AbstractString,Float64} @test keytype(td) == AbstractString @test valtype(td) == Float64 @test keytype(Dict{AbstractString,Float64}) === AbstractString @@ -421,7 +421,7 @@ end d = @inferred ObjectIdDict(Pair(1,1), Pair(2,2), Pair(3,3)) @test isa(d, ObjectIdDict) @test d == ObjectIdDict(1=>1, 2=>2, 3=>3) - @test eltype(d) == Pair{Any,Any} + @test pairtype(d) == Pair{Any,Any} end @testset "Issue #7944" begin @@ -435,7 +435,8 @@ end @testset "iteration" begin d = Dict('a'=>1, 'b'=>1, 'c'=> 3) @test [d[k] for k in keys(d)] == [d[k] for k in eachindex(d)] == - [v for (k, v) in d] == [d[x[1]] for (i, x) in enumerate(d)] + [v for (k, v) in pairs(d)] == [d[x[1]] for (i, x) in enumerate(d)] == + [v for v in values(d)] end @testset "generators, similar" begin @@ -496,19 +497,19 @@ import Base.ImmutableDict @test collect(d1) == [Pair(k1, v1)] @test collect(d4) == reverse([Pair(k1, v1), Pair(k2, v2), Pair(k1, v2), Pair(k2, v1)]) @test d1 == ImmutableDict(d, k1 => v1) - @test !((k1 => v2) in d2) - @test (k1 => v2) in d3 - @test (k1 => v1) in d4 - @test (k1 => v2) in d4 - @test in(k2 => "value2", d4, ===) - @test in(k2 => v2, d4, ===) - @test in(k2 => NaN, dnan, isequal) - @test in(k2 => NaN, dnan, ===) - @test !in(k2 => NaN, dnan, ==) - @test !in(k2 => 1, dnum, ===) - @test in(k2 => 1.0, dnum, ===) - @test !in(k2 => 1, dnum, <) - @test in(k2 => 0, dnum, <) + @test !((k1 => v2) in pairs(d2)) + @test (k1 => v2) in pairs(d3) + @test (k1 => v1) in pairs(d4) + @test (k1 => v2) in pairs(d4) + @test in(k2 => "value2", pairs(d4), ===) + @test in(k2 => v2, pairs(d4), ===) + @test in(k2 => NaN, pairs(dnan), isequal) + @test in(k2 => NaN, pairs(dnan), ===) + @test !in(k2 => NaN, pairs(dnan), ==) + @test !in(k2 => 1, pairs(dnum), ===) + @test in(k2 => 1.0, pairs(dnum), ===) + @test !in(k2 => 1, pairs(dnum), <) + @test in(k2 => 0, pairs(dnum), <) @test get(d1, "key1", :default) === v1 @test get(d4, "key1", :default) === v2 @test get(d4, "foo", :default) === :default diff --git a/test/env.jl b/test/env.jl index ea24759aa5941..4f3d86bc186b5 100644 --- a/test/env.jl +++ b/test/env.jl @@ -37,7 +37,7 @@ end k1, k2 = "__test__", "__test1__" withenv(k1=>k1, k2=>k2) do b_k1, b_k2 = false, false - for (k, v) in ENV + for (k, v) in pairs(ENV) if k==k1 b_k1=true elseif k==k2 @@ -66,7 +66,7 @@ end @test withenv(Dict{Any,Any}()...) do; true; end # Test for #18141 -for (k, v) in ENV +for (k, v) in pairs(ENV) if length(v) > 0 @test v[end] != '\0' end