diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 06a0213e7141c5..0421877a166235 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -298,7 +298,11 @@ function invmod(n::T) where {T<:BitInteger} end # ^ for any x supporting * -to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x) +function to_power_type(x::Number) + T = promote_type(typeof(x), typeof(one(x)), typeof(x*x)) + convert(T, x) +end +to_power_type(x) = oftype(x*x, x) @noinline throw_domerr_powbysq(::Any, p) = throw(DomainError(p, LazyString( "Cannot raise an integer x to a negative power ", p, ".", "\nConvert input to float."))) diff --git a/test/math.jl b/test/math.jl index c0a2d8bf8c9f8f..5a9f3248e59f4e 100644 --- a/test/math.jl +++ b/test/math.jl @@ -1498,6 +1498,28 @@ end n = Int64(1024 / log2(E)) @test E^n == Inf @test E^float(n) == Inf + + # #55633 + struct Issue55633_1 <: Number end + struct Issue55633_3 <: Number end + struct Issue55633_9 <: Number end + Base.one(::Issue55633_3) = Issue55633_1() + Base.:(*)(::Issue55633_3, ::Issue55633_3) = Issue55633_9() + Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_3}) = Int + Base.promote_rule(::Type{Issue55633_3}, ::Type{Issue55633_9}) = Int + Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_9}) = Int + Base.promote_rule(::Type{Issue55633_1}, ::Type{Int}) = Int + Base.promote_rule(::Type{Issue55633_3}, ::Type{Int}) = Int + Base.promote_rule(::Type{Issue55633_9}, ::Type{Int}) = Int + Base.convert(::Type{Int}, ::Issue55633_1) = 1 + Base.convert(::Type{Int}, ::Issue55633_3) = 3 + Base.convert(::Type{Int}, ::Issue55633_9) = 9 + for x ∈ (im, pi, Issue55633_3()) + p = promote(one(x), x, x*x) + for y ∈ 0:2 + @test all((t -> ===(t...)), zip(x^y, p[y + 1])) + end + end end # Test that sqrt behaves correctly and doesn't exhibit fp80 double rounding.