# julia 1.4
# ]add AxisKeys
using AxisKeys
using Test
# "more" type-stable version of reverse
reverse_tuple(x) = ntuple(i -> x[length(x) + 1 - i], length(x))
f1(nt) = NamedDimsArray(zeros(1,1,1), keys(nt) |> reverse)
f2(nt) = NamedDimsArray(zeros(1,1,1), keys(nt) |> reverse_tuple)
@inferred f1((a=1,b=1,c=1)) # fails: keys not inferred
@inferred f2((a=1,b=1,c=1)) # passes

Basically, function f1 does not infer correctly, but f2 does - and the only thing that differs is the tuple reversal function.
Note that Base.reverseis type-stable if used by itself, and the example above reproduces only when reverse is put inside something else.

You’re putting the (:c, :b, :a) tuple into a type parameter, so you’re not really fighting type-stability… you’re fighting constant propagation. Not only does Julia need to get the type of reverse correct, it needs to deduce (and mark) the fact that it’s going to return that particular value ahead of time. That in turn is affecting the downstream type-stability once you put the (hopefully) constant value into a type parameter.

Indeed, you are right - I didn’t notice that. It means AxisKeys interface is not type-stable, and nothing is suboptimal about Base.reverse implementation, right?
Then my reverse_tuple is somehow easier for the julia constant propagation, but it has nothing to do with type stability?