Description
openedon Aug 3, 2020
I've been poking at this for a while now and still can't quite isolate this the way I want, so let me show you what I have. I'm trying to figure out how to set up a test for a fix for invalidations from loading ColorTypes.
The invalidations are triggered by adding new eltype(::Type)
specializations. The ColorTypes issue is fixed just by adding
eltype(::Type{<:NamedTuple}) = Any
but I wonder if there's a more systematic fix? For the record we already have a definition
eltype(::Type{NamedTuple{names,T}} where names) where {T} = eltype(T)
so this is just about handling the case where the type is not fully specified.
Here is a prototype and analysis:
julia> f(::Type{T}) where T = eltype(T)
f (generic function with 1 method)
julia> function g()
while true # block interpreter
return f(T where T<:NamedTuple{(:indent,)})
end
end
g (generic function with 1 method)
julia> g()
Any
julia> using SnoopCompileCore
julia> abstract type Container{T} end
julia> invlist = @snoopr Base.eltype(::Type{C}) where {T,C<:Container{T}} = T;
julia> using SnoopCompile
julia> trees = invalidation_trees(invlist)
1-element Vector{SnoopCompile.MethodInvalidations}:
inserting eltype(::Type{C}) where {T, C<:Container{T}} in Main at REPL[6]:1 invalidated:
backedges: 1: superseding eltype(::Type) in Base at array.jl:123 with MethodInstance for eltype(::Type{A} where A<:(NamedTuple{(:io,),_A} where _A<:Tuple{IO})) (3 children)
2: superseding eltype(::Type) in Base at array.jl:123 with MethodInstance for eltype(::Type{A} where A<:(NamedTuple{(:init,),_A} where _A<:Tuple{IOContext})) (4 children)
3: superseding eltype(::Type) in Base at array.jl:123 with MethodInstance for eltype(::Type{A} where A<:(NamedTuple{(:indent, :first_block, :sorted, :by),_A} where _A<:Tuple{Int64,Bool,Bool,Function})) (4 children)
4: superseding eltype(::Type) in Base at array.jl:123 with MethodInstance for eltype(::Type{A} where A<:(NamedTuple{(:indent, :sorted, :by),_A} where _A<:Tuple{Int64,Bool,Function})) (5 children)
5: superseding eltype(::Type) in Base at array.jl:123 with MethodInstance for eltype(::Type{A} where A<:(NamedTuple{(:indent, :region_active),_A} where _A<:Tuple{Any,Bool})) (171 children)
julia> m = only(methods(f))
f(::Type{T}) where T in Main at REPL[1]:1
julia> m.specializations
svec(#undef, #undef, #undef, #undef, #undef, #undef, MethodInstance for f(::Type{NamedTuple{(:indent,),T} where T<:Tuple}), MethodInstance for f(::Type{T}) where T)
julia> mi = m.specializations[end]
MethodInstance for f(::Type{T}) where T
julia> mi.backedges
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getproperty(x::Core.MethodInstance, f::Symbol)
@ Base ./Base.jl:33
[2] top-level scope
@ REPL[13]:1
To edit a specific method, type the corresponding number into the REPL and press Ctrl+Q
julia> mi = m.specializations[end-1]
MethodInstance for f(::Type{NamedTuple{(:indent,),T} where T<:Tuple})
julia> mi.backedges
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getproperty(x::Core.MethodInstance, f::Symbol)
@ Base ./Base.jl:33
[2] top-level scope
@ REPL[15]:1
To edit a specific method, type the corresponding number into the REPL and press Ctrl+Q
Where are the backedges? I guess they must be runtime dispatched...I was just surprised since there's only one method. But of course that's good in many ways since it severs the chain of invalidations. However, that's not what happens with the cases above. They are triggered by the REPL, as you can verify with node = only(trees).backedges[end]; ascend(node)
.
I've also tried this:
# This first part is my attempt to set up a test that will replicate some of the code in REPL that gets invalidated
# Doesn't work yet
julia> nteltypekw(; indent=0,region_active::Bool=false,kwargs...) = indent
nteltypekw (generic function with 1 method)
julia> nteltype(c) = (x = c[]; nteltypekw(; indent=x.indent, extra=:none))
nteltype (generic function with 1 method)
julia> struct HasIndent indent::Int end
julia> hi = HasIndent(3)
HasIndent(3)
julia> nteltype(Ref{Any}(hi))
3
as a way of aiming for the same thing without explicitly manipulating NamedTuple
.