Any way to make this one-liner type stable?

I’ve got this function which widens each of the arguments of a Tuple type

widen_tupleargs(::Type{T}) where {T<:Tuple} = Tuple{map(widen,T.parameters)...}

e.g.

julia> widen_tupleargs(Tuple{Int16,Float16})
Tuple{Int32,Float32}

However, its not type-stable,

julia> @code_warntype widen_tupleargs(Tuple{Int16,Float16})
Variables:
  #self# <optimized out>
  #unused# <optimized out>

Body:
  begin 
      return (Core._apply)(Core.apply_type, (Core.tuple)(Main.Tuple)::Tuple{DataType}, $(Expr(:invoke, MethodInstance for map(::Base.#widen, ::SimpleVector), :(Main.map), :(Main.widen), :((Core.getfield)($(Expr(:static_parameter, 1)), :parameters)::SimpleVector))))::Any
  end::Any

Is there any way to write this so that it is type stable? I’d be curious on either 0.6 or 0.7 (above output was 0.6). Thanks for any help!

1 Like

You could try something like this, with head and tail (the versions for tuple type):

widen_tupleargs(::Type{Tuple{}}) = Tuple{}
widen_tupleargs(::Type{T}) where {T<:Tuple} =  Base.tuple_type_cons(widen(Base.tuple_type_head(T)), widen_tupleargs(Base.tuple_type_tail(T)))

This is for Julia 0.6, I didn’t check if it changed in 0.7

2 Likes

Awesome, Base.tuple_type_head/tail is exactly what I was looking for, thanks! I just checked on 0.7 and it works exactly the same.