Skip to content

inference: enable constant propagation for invoked calls #41024

@aviatesk

Description

@aviatesk

The simple but realistic target code would be like this:

# interface, which expects common field `x::Int`
abstract type AbstractInterface end

# to help inference of mixins
function Base.getproperty(x::AbstractInterface, sym::Symbol)
    if sym === :x
        return getfield(x, sym)::Int
    else
        return getfield(x, sym) # fallback
    end
end

# another interface, which expects additional field `y::Rational{Int}`
abstract type AbstractInterfaceExtended <: AbstractInterface end

# to help inference of mixins
function Base.getproperty(x::AbstractInterfaceExtended, sym::Symbol)
    if sym === :y
        return getfield(x, sym)::Rational{Int}
    end
    return Base.@invoke getproperty(x::AbstractInterface, sym::Symbol)
end

Constant prop' works well for a case when sym === :y:

julia> code_typed((AbstractInterfaceExtended,); optimize=false) do x
           x.y
       end |> first
CodeInfo(
1%1 = Base.getproperty(x, :y)::Rational{Int64}
└──      return %1
) => Rational{Int64}

but doens't work for cases when sym === :x:

julia> code_typed((AbstractInterfaceExtended,); optimize=false) do x
           x.x
       end |> first
CodeInfo(
1%1 = Base.getproperty(x, :x)::Any # we want ::Int here
└──      return %1
) => Any

julia> code_typed((AbstractInterface,); optimize=false) do x
           x.x
       end
1-element Vector{Any}:
 CodeInfo(
1%1 = Base.getproperty(x, :x)::Any # we want ::Int here
└──      return %1
) => Any

Simply we need to enable constant prop' for abstract_invoke.
Especially, we want to implement a way to recompute argtypes taking into account a invoked call signature computed by :jl_type_intersection_with_env:

(ti, env::SimpleVector) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector
rt, edge = typeinf_edge(interp, method, ti, env, sv)
edge !== nothing && add_backedge!(edge::MethodInstance, sv)
return CallMeta(rt, InvokeCallInfo(MethodMatch(ti, env, method, argtype <: method.sig)))

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions