Closed brainandforce closed 3 weeks ago
The proper fix is not to use type inference at all from ^
.
xref #24151
Why are we even trying to do this in the first place? I get the idea — it's trying to ensure type stability — but does it even work more often than it fails? What are the datatypes for which typeof(x) != typeof(x*x)
but typeof(x*x) == typeof(x*x*x)
?
OK, two cases are im
and Char
. Are there more? Maybe this is more common than I first thought. In the Char
case, there's not even a one(::Char)
method defined.
@mbauman this was initially introduced to fix #11383, for Irrational
That said, I'm pretty sure the right thing to do here is to use promote
. Testing that fix rn.
The function
Base.to_power_type(x)
is found here and defined below:This function is used in
Base.power_by_squaring
to determine what type the result should be. I think the definition above is flawed, and we should be using this:But why, you ask?
In the general case, to maintain type stability, the output of
Base.power_by_squaring(x, n)
needs to be a type that can storex^0
,x
, andx^2
. However,one(x)
, which is used to calculatex^0
, may be a different type fromx
orx*x
:I am currently writing a package, CliffordNumbers.jl, which has some data types
T
(such asKVector{K}
whenK
is odd) for which neithertypeof(one(T))
norBase._return_type(*, Tuple{T, T})
areT
. This causes exponentiation to fail without some workarounds because the input is not always convertable to the result ofBase._return_type(*, Tuple{T, T})
.The problem I faced might be a really niche edge case, but I think the way integer powers of types are handled in cases where they are not equivalent to the type itself is worth discussing and refining. The solution I present would completely solve my issues (though I have already solved them within the package), but I'm not sure if it's too much of a breaking change.