julia
3b1c1fdd - Restrict `signed(x) = reinterpret(...)` to BitIntegers. (#33459)

Commit
6 years ago
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.
Author
Committer
Parents
Loading