Hi,
I want to write addition function for tuples with unknown length and unknown type e.g. something like Tuple{a, b, c, d...}
where the length and type is determined at runtime, and a, b, c, and d are custom types with addition defined.
Naively, I would try something like this
function add_tuple(a, b)
a .+ b
end
This works great for a :: Tuple{Int, Float64}
:
@btime add_tuple((1,2.0), (2,3.0))
0.013 ns (0 allocations: 0 bytes)
@code_warntype add_tuple((1,3.0), (2,2.0))
Variables
#self#::Core.Compiler.Const(add_tuple, false)
a::Tuple{Int64,Float64}
b::Tuple{Int64,Float64}
Body::Tuple{Int64,Float64}
1 β %1 = Base.broadcasted(Main.:+, a, b)::Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(+),Tuple{Tuple{Int64,Float64},Tuple{Int64,Float64}}}
β %2 = Base.materialize(%1)::Tuple{Int64,Float64}
βββ return %2
A bit surprisingly, type inference seems to fail for slightly more complicated examples
struct MyInt
s :: Int
end
Base.:+(a::MyInt, b::MyInt) = MyInt(a.s + b.s)
a = MyInt(1)
@code_warntype add_tuple((1,a), (2,a))
Variables
#self#::Core.Compiler.Const(add_tuple, false)
a::Tuple{Int64,MyInt}
b::Tuple{Int64,MyInt}
Body::Tuple{Union{Int64, MyInt},Union{Int64, MyInt}}
1 β %1 = Base.broadcasted(Main.:+, a, b)::Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(+),Tuple{Tuple{Int64,MyInt},Tuple{Int64,MyInt}}}
β %2 = Base.materialize(%1)::Tuple{Union{Int64, MyInt},Union{Int64, MyInt}}
βββ return %2
Not that type inference fails for Base.materialize
, even though the compiler should have enough information to figure out the output type. I suspect this has some performance cost in more complicated cases.
My question is why this happens, and if there is anything I can do to force type inference. Thanks!