I have the following code that I want to use for storing a vector of functions:
using FunctionWrappers
import FunctionWrappers: FunctionWrapper
abstract type AbstractF end
struct F{P,T,U} <: AbstractF
    p::P
    f::FunctionWrapper{U,Tuple{T,T,T,U,P}}
end
struct G{P,T,U} <: AbstractF
    p::P
    f::FunctionWrapper{U,Tuple{T,T,T,U,P}}
end
(F::AbstractF)(a, b, c, d) = F.f(a, b, c, d, F.p)
When I use a vector of functions of say type F, this is all fine:
function evaluate_list_of_wrappers(wrappers)
    nums = zeros(length(wrappers))
    for (i, f) in pairs(wrappers)
        a, b, c, d = rand(4)
        nums[i] = f(a, b, c, d)
    end
    return nums
end
f1 = (a, b, c, d, p) -> a * b
f2 = (a, b, c, d, p) -> c * p[1]
g1 = (a, b, c, d, p) -> a + b + c
g2 = (a, b, c, d, p) -> a - b + c
p = (1.0, 5)
F1 = F{typeof(p),Float64,Float64}(p, f1)
F2 = F{typeof(p),Float64,Float64}(p, f2)
G1 = G{typeof(p),Float64,Float64}(p, g1)
G2 = G{typeof(p),Float64,Float64}(p, g2)
@code_warntype evaluate_list_of_wrappers((F1, F2)) # Fine 
julia> @code_warntype evaluate_list_of_wrappers((F1, F2)) # Fine 
MethodInstance for evaluate_list_of_wrappers(::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}})
  from evaluate_list_of_wrappers(wrappers) in Main at Untitled-1:19
Arguments
  #self#::Core.Const(evaluate_list_of_wrappers)
  wrappers::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}}
Locals
  @_3::Union{Nothing, Tuple{Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Int64}}
  nums::Vector{Float64}
  @_5::Int64
  @_6::Int64
  f::F{Tuple{Float64, Int64}, Float64, Float64}
  i::Int64
  d::Float64
  c::Float64
  b::Float64
  a::Float64
Body::Vector{Float64}
1 β %1  = Main.length(wrappers)::Core.Const(2)
β         (nums = Main.zeros(%1))
β   %3  = Main.pairs(wrappers)::Core.PartialStruct(Base.Pairs{Int64, F{Tuple{Float64, Int64}, Float64, Float64}, Base.OneTo{Int64}, Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}}}, Any[Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}}, Core.Const(Base.OneTo(2))])
β         (@_3 = Base.iterate(%3))
β   %5  = (@_3::Core.PartialStruct(Tuple{Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Int64}, Any[Core.PartialStruct(Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Any[Core.Const(1), F{Tuple{Float64, Int64}, Float64, Float64}]), Core.Const(1)]) === nothing)::Core.Const(false)
β   %6  = Base.not_int(%5)::Core.Const(true)
βββ       goto #4 if not %6
2 β %8  = @_3::Tuple{Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}, Int64}
β   %9  = Core.getfield(%8, 1)::Pair{Int64, F{Tuple{Float64, Int64}, Float64, Float64}}
β   %10 = Base.indexed_iterate(%9, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
β         (i = Core.getfield(%10, 1))
β         (@_6 = Core.getfield(%10, 2))
β   %13 = Base.indexed_iterate(%9, 2, @_6::Core.Const(2))::Core.PartialStruct(Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, Int64}, Any[F{Tuple{Float64, Int64}, Float64, Float64}, Core.Const(3)])  
β         (f = Core.getfield(%13, 1))
β   %15 = Core.getfield(%8, 2)::Int64
β   %16 = Main.rand(4)::Vector{Float64}
β   %17 = Base.indexed_iterate(%16, 1)::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(2)])
β         (a = Core.getfield(%17, 1))
β         (@_5 = Core.getfield(%17, 2))
β   %20 = Base.indexed_iterate(%16, 2, @_5::Core.Const(2))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(3)])
β         (b = Core.getfield(%20, 1))
β         (@_5 = Core.getfield(%20, 2))
β   %23 = Base.indexed_iterate(%16, 3, @_5::Core.Const(3))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(4)])
β         (c = Core.getfield(%23, 1))
β         (@_5 = Core.getfield(%23, 2))
β   %26 = Base.indexed_iterate(%16, 4, @_5::Core.Const(4))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(5)])
β         (d = Core.getfield(%26, 1))
β   %28 = (f)(a, b, c, d)::Float64
β         Base.setindex!(nums, %28, i)
β         (@_3 = Base.iterate(%3, %15))
β   %31 = (@_3 === nothing)::Bool
β   %32 = Base.not_int(%31)::Bool
βββ       goto #4 if not %32
3 β       goto #2
4 β       return nums
But if I now include different types, I get an issue:
julia> @code_warntype evaluate_list_of_wrappers((F1, F2, G1, G2)) # ?
MethodInstance for evaluate_list_of_wrappers(::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}})
  from evaluate_list_of_wrappers(wrappers) in Main at Untitled-1:19
Arguments
  #self#::Core.Const(evaluate_list_of_wrappers)
  wrappers::Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}}        
Locals
  @_3::Union{Nothing, Tuple{Pair{Int64, AbstractF}, Int64}}
  nums::Vector{Float64}
  @_5::Int64
  @_6::Int64
  f::AbstractF
  i::Int64
  d::Float64
  c::Float64
  b::Float64
  a::Float64
Body::Vector{Float64}
1 β %1  = Main.length(wrappers)::Core.Const(4)
β         (nums = Main.zeros(%1))
β   %3  = Main.pairs(wrappers)::Core.PartialStruct(Base.Pairs{Int64, AbstractF, Base.OneTo{Int64}, Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}}}, Any[Tuple{F{Tuple{Float64, Int64}, Float64, Float64}, F{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}, G{Tuple{Float64, Int64}, Float64, Float64}}, Core.Const(Base.OneTo(4))])
β         (@_3 = Base.iterate(%3))
β   %5  = (@_3::Core.PartialStruct(Tuple{Pair{Int64, AbstractF}, Int64}, Any[Core.PartialStruct(Pair{Int64, AbstractF}, Any[Core.Const(1), F{Tuple{Float64, Int64}, Float64, Float64}]), Core.Const(1)]) 
=== nothing)::Core.Const(false)
β   %6  = Base.not_int(%5)::Core.Const(true)
βββ       goto #4 if not %6
2 β %8  = @_3::Tuple{Pair{Int64, AbstractF}, Int64}
β   %9  = Core.getfield(%8, 1)::Pair{Int64, AbstractF}
β   %10 = Base.indexed_iterate(%9, 1)::Core.PartialStruct(Tuple{Int64, Int64}, Any[Int64, Core.Const(2)])
β         (i = Core.getfield(%10, 1))
β         (@_6 = Core.getfield(%10, 2))
β   %13 = Base.indexed_iterate(%9, 2, @_6::Core.Const(2))::Core.PartialStruct(Tuple{AbstractF, Int64}, Any[AbstractF, Core.Const(3)])
β         (f = Core.getfield(%13, 1))
β   %15 = Core.getfield(%8, 2)::Int64
β   %16 = Main.rand(4)::Vector{Float64}
β   %17 = Base.indexed_iterate(%16, 1)::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(2)])
β         (a = Core.getfield(%17, 1))
β         (@_5 = Core.getfield(%17, 2))
β   %20 = Base.indexed_iterate(%16, 2, @_5::Core.Const(2))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(3)])
β         (b = Core.getfield(%20, 1))
β         (@_5 = Core.getfield(%20, 2))
β   %23 = Base.indexed_iterate(%16, 3, @_5::Core.Const(3))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(4)])
β         (c = Core.getfield(%23, 1))
β         (@_5 = Core.getfield(%23, 2))
β   %26 = Base.indexed_iterate(%16, 4, @_5::Core.Const(4))::Core.PartialStruct(Tuple{Float64, Int64}, Any[Float64, Core.Const(5)])
β         (d = Core.getfield(%26, 1))
β   %28 = (f)(a, b, c, d)::Any
β         Base.setindex!(nums, %28, i)
β         (@_3 = Base.iterate(%3, %15))
β   %31 = (@_3 === nothing)::Bool
β   %32 = Base.not_int(%31)::Bool
βββ       goto #4 if not %32
3 β       goto #2
4 β       return nums
Namely, I now have f::AbstractF and %28 = (f)(a, b, c, d)::Any. Is there any way to get around this with the current setup?
 )
)