Skip to content

Specificity alteration under precompilation #22002

@timholy

Description

@timholy

Noticed in JuliaGraphics/Gtk.jl#311. Here's a reasonably short repro:

__precompile__(false)

module Convert

import Base: convert

export GBoxed

abstract type GBoxed  end

convert(::Type{GBoxed}, unbox::Ptr{GBoxed}) = GBoxedUnkown(unbox)
convert{T <: GBoxed}(::Type{GBoxed}, unbox::Ptr{T}) = GBoxedUnkown(unbox)
convert{T <: GBoxed}(::Type{T}, unbox::Ptr{GBoxed}) = convert(T, convert(Ptr{T}, unbox))
convert{T <: GBoxed}(::Type{T}, unbox::Ptr{T}) = T(unbox)

abstract type GdkEvent <: GBoxed end

convert(::Type{GdkEvent}, evt::Ptr{GdkEvent}) = -1

end

Because the method tables for convert are very long, this filter_gboxed.jl script is handy:

using Convert

isgboxed_method(m::Method) = _isgboxed(Base.unwrap_unionall(m.sig).parameters[2])
_isgboxed(::Type{Type{T}}) where T<:GBoxed = true
function _isgboxed(t::Type)
    p = Base.unwrap_unionall(t).parameters
    length(p) != 1 && return false
    _isgboxed(p[1])
end
_isgboxed(TV::TypeVar) = TV.ub <: GBoxed
_isgboxed(arg) = false

mt = methods(convert)
collect(Iterators.filter(isgboxed_method, mt))

As written, the output is

5-element Array{Any,1}:
 convert(::Type{Convert.GdkEvent}, evt::Ptr{Convert.GdkEvent}) in Convert at /tmp/Convert.jl:18         
 convert(::Type{T}, unbox::Ptr{T}) where T<:Convert.GBoxed in Convert at /tmp/Convert.jl:14             
 convert(::Type{Convert.GBoxed}, unbox::Ptr{Convert.GBoxed}) in Convert at /tmp/Convert.jl:11           
 convert(::Type{Convert.GBoxed}, unbox::Ptr{T}) where T<:Convert.GBoxed in Convert at /tmp/Convert.jl:12
 convert(::Type{T}, unbox::Ptr{Convert.GBoxed}) where T<:Convert.GBoxed in Convert at /tmp/Convert.jl:13

However, if you change it to __precompile__(true) then I get

 convert(::Type{Convert.GBoxed}, unbox::Ptr{Convert.GBoxed}) in Convert at /tmp/Convert.jl:11           
 convert(::Type{T}, unbox::Ptr{T}) where T<:Convert.GBoxed in Convert at /tmp/Convert.jl:14             
 convert(::Type{Convert.GdkEvent}, evt::Ptr{Convert.GdkEvent}) in Convert at /tmp/Convert.jl:18         
 convert(::Type{Convert.GBoxed}, unbox::Ptr{T}) where T<:Convert.GBoxed in Convert at /tmp/Convert.jl:12
 convert(::Type{T}, unbox::Ptr{Convert.GBoxed}) where T<:Convert.GBoxed in Convert at /tmp/Convert.jl:13

The second method should come after the third.

Metadata

Metadata

Assignees

No one assigned

    Labels

    types and dispatchTypes, subtyping and method dispatch

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions