Issue 1:
Working with negative exponents has some very odd behaviors, to say the least. Running the internals of the ^ function gives different results than ^ itself, evaluation success changes based on whether a variable is replaced with its value, and @code_* forms are convinced that the result should always be of type Int64. Tested on v1.0.0 and v1.1.0-DEV.

julia> 2 ^ -5
0.03125

julia> Base.power_by_squaring(2, -5)
ERROR: DomainError with -5:
Cannot raise an integer x to a negative power -5.
Make x a float by adding a zero decimal (e.g., 2.0^-5 instead of 2^-5), or write 1/x^5, float(x)^-5, or (x//1)^-5
Stacktrace:
[1] throw_domerr_powbysq(::Int64, ::Int64) at ./intfuncs.jl:176
[2] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:196
[3] top-level scope at none:0

julia> @edit 2 ^ -5
# ^(x::T, p::T) where {T<:Integer} = power_by_squaring(x,p)

julia> x = -2;

julia> x ^ x
ERROR: DomainError with -2:
Cannot raise an integer x to a negative power -2.
Make x a float by adding a zero decimal (e.g., 2.0^-2 instead of 2^-2), or write 1/x^2, float(x)^-2, or (x//1)^-2
Stacktrace:
[1] throw_domerr_powbysq(::Int64, ::Int64) at ./intfuncs.jl:176
[2] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:196
[3] ^(::Int64, ::Int64) at ./intfuncs.jl:220
[4] top-level scope at none:0

julia> x ^ (-2)
0.25

julia> (-2) ^ x
ERROR: DomainError with -2:
Cannot raise an integer x to a negative power -2.
Make x a float by adding a zero decimal (e.g., 2.0^-2 instead of 2^-2), or write 1/x^2, float(x)^-2, or (x//1)^-2
Stacktrace:
[1] throw_domerr_powbysq(::Int64, ::Int64) at ./intfuncs.jl:176
[2] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:196
[3] ^(::Int64, ::Int64) at ./intfuncs.jl:220
[4] top-level scope at none:0

julia> (-2) ^ (-2)
0.25

julia> @code_warntype x ^ x
Body::Int64
220 1 ─ %1 = invoke Base.power_by_squaring(_2::Int64, _3::Int64)::Int64 │
└── return %1 │

Issue 2:
As discussed in https://discourse.julialang.org/t/confusing-difference-literal-vs-variable/13515/5 it would be good if this is documented somewhere. The explanation of @StefanKarpinski in this thread will be helpful:

This was a controversial change and there are still many people who are not entirely comfortable with it. The starting point is that people do not really often expect or want x^2 and x^-1 to be pow(x, 2) and pow(x, -1), respectively. Rather, people want x^2 to be syntax for xx. The latter can generally be implemented much more efficiently than calling a general power function. With sufficiently clever optimizations (constant propagation + power reduction), one can potentailly optimize pow(x, 2) into xx but it would be even better if we didn’t have to do such a clever optimization in the first place. It’s been a fairly common and successful strategy in the design of Julia to arrange things so that you can get great performance in a straightforward way without need for clever optimizations instead of trying to make the optimizers smarter. So what this design does is it causes x^n where n is a literal integer value to call Base.literal_pow(x, Val(n)), which allows us to specialize the syntax on individual literal values like 2 or -1. This allow us to make x^2 actually mean x*x instead of needing to try to optimize it to that. It also allows us to make negative literal exponents work without introducing a type instability in the general ^ function. And indeed, we used to get regular complaints from new users that 2^-1 doesn’t return 0.5 as they would expect, instead giving them a domain error because of the negative exponent. There are good reasons for it but users don’t care about involved language design reasons, they just want it to work. A way to think about this is that ^2 is its own operator, as is ^3 and ^-1, and so on. Hopefully that helps.

#24240