Restrict `signed(x) = reinterpret(...)` to BitIntegers. (#33459)
This commit restricts the `reinterpret` implementation of `signed(x)`
to only apply to `Base.BitInteger`s. This brings its behavior in-line
with `unsigned(x)`.
Previously, although `unsigned(x)` did restrict the `reinterpret`
implementation to only apply to `Base.BitInteger`s, `signed(x)` by
default called `reinterpret(Signed, x)` for any type `T <: Unsigned`.
This of course wouldn't work for `BigInt`, which is presumably why
`unsigned(x)` was restricted (since `BigInt <: Signed` but not `BigInt
<: BitInteger`), but although _Base_ contains no non-BitInteger types in
`Unsigned` (besides `Bool`), of course users _could_ create such types,
so this should be restricted symmetrically.
Below is an example of the previous, unexpected broken behavior:
```julia
struct WeirdUnsigned <: Unsigned
msg::String
val::UInt16
end
WeirdUnsigned(x::Int) = WeirdUnsigned("missing", UInt16(x))
Base.Signed(x::WeirdUnsigned) = signed(x.val)
```
```julia
julia> signed(WeirdUnsigned(4))
ERROR: bitcast: expected primitive type value for second argument
Stacktrace:
[1] reinterpret at ./essentials.jl:417 [inlined]
[2] signed(::WeirdUnsigned) at ./int.jl:162
[3] top-level scope at REPL[20]:1
```
Whereas after this commit, this works as expected, calling the `Signed`
constructor:
```julia
julia> signed(WeirdUnsigned(4))
4
julia> typeof(signed(WeirdUnsigned(4)))
Int16
```
-------------------
This should be a non-breaking change. If there exist any `primitive
type` implementations that were relying on the reinterpret
implementation, they may see a slight performance regression, as this
will by default now call `Signed(x::T)`, instead of
`reinterpret(typeof(Signed(x)), x)` -- so they may want to manually
define the reinterpret implemention themselves.