No typeinference for object call syntax

I have problems getting type-inference to work when replacing a function with a function object.
The purpose is to add an extra AbstractType to improve dispatch.

However nothing I tried so far works. Any help is highly welcome!

function func(T::Type)
  T
end


abstract type AbstractType end
struct Gunc <: AbstractType end
gunc = Gunc()

function (::Gunc)(::Type{T}) where T
  T
end

struct Hunc <: AbstractType end
hunc = Hunc()

function (::Hunc)(::Type{T}) where T
  func(T)
end

struct Junc <: AbstractType end
junc = Junc()

function (::Junc)(T::Type)
  func(T)
end

struct Kunc <: AbstractType end
kunc = Kunc()

@inline function (::Kunc)(::Type{T}) where T
  func(T)
end


func2(args...) = func(args...)
gunc2(args...) = gunc(args...)
hunc2(args...) = hunc(args...)
junc2(args...) = junc(args...)
kunc2(args...) = kunc(args...)

@code_warntype func2(Int)  # all fine
@code_warntype gunc2(Int)  # ::Any warning
@code_warntype hunc2(Int)  # ::Any warning
@code_warntype junc2(Int)  # ::Any warning
@code_warntype kunc2(Int)  # ::Any warning

The code_warntype output:

Body::Type{Int64}
36 1 ─     return Int64                                                                         

Body::Any
37 1 ─ %1 = (getfield)(args, 1)::Core.Compiler.Const(Int64, false)                              
   β”‚   %2 = (Main.gunc)(%1)::Any                                                                
   └──      return %2                 
                                                          
Body::Any
38 1 ─ %1 = (getfield)(args, 1)::Core.Compiler.Const(Int64, false)                              
   β”‚   %2 = (Main.hunc)(%1)::Any                                                                
   └──      return %2                
                                                           
Body::Any
39 1 ─ %1 = (getfield)(args, 1)::Core.Compiler.Const(Int64, false)                              
   β”‚   %2 = (Main.junc)(%1)::Any                                                                
   └──      return %2                   
                                                        
Body::Any
40 1 ─ %1 = (getfield)(args, 1)::Core.Compiler.Const(Int64, false)                          
   β”‚   %2 = (Main.kunc)(%1)::Any                                                                
   └──      return %2    

Don’t use non-const global variables (like gunc etc). See Performance Tips Β· The Julia Language.

2 Likes

thank you so much that was exactly my problem!