diff --git a/base/essentials.jl b/base/essentials.jl index 97f32483a6b14..7b70c0dff074d 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -543,21 +543,41 @@ unsafe_convert(::Type{T}, x::T) where {T<:Ptr} = x # to resolve ambiguity with unsafe_convert(::Type{P}, x::Ptr) where {P<:Ptr} = convert(P, x) """ - reinterpret(type, x) + reinterpret(::Type{Out}, x::In) -Change the type-interpretation of the binary data in the primitive value `x` -to that of the primitive type `type`. -The size of `type` has to be the same as that of the type of `x`. +Change the type-interpretation of the binary data in the isbits value `x` +to that of the isbits type `Out`. +The size (ignoring padding) of `Out` has to be the same as that of the type of `x`. For example, `reinterpret(Float32, UInt32(7))` interprets the 4 bytes corresponding to `UInt32(7)` as a [`Float32`](@ref). -# Examples ```jldoctest julia> reinterpret(Float32, UInt32(7)) 1.0f-44 + +julia> reinterpret(NTuple{2, UInt8}, 0x1234) +(0x34, 0x12) + +julia> reinterpret(UInt16, (0x34, 0x12)) +0x1234 + +julia> reinterpret(Tuple{UInt16, UInt8}, (0x01, 0x0203)) +(0x0301, 0x02) ``` + +!!! warning + + Use caution if some combinations of bits in `Out` are not considered valid and would + otherwise be prevented by the type's constructors and methods. Unexpected behavior + may result without additional validation. """ -reinterpret(::Type{T}, x) where {T} = bitcast(T, x) +function reinterpret(Out::Type, x::In) where {In} + if isprimitivetype(Out) && isprimitivetype(In) + return bitcast(Out, x) + end + # only available when Base is fully loaded. + return _reinterpret(Out, x) +end """ sizeof(T::DataType) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index d33c127b78c76..74b888a39fd76 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -795,42 +795,10 @@ function _copyfrompacked!(ptr_out::Ptr{Out}, ptr_in::Ptr{In}) where {Out, In} end end -""" - reinterpret(::Type{Out}, x::In) - -Reinterpret the valid non-padding bytes of an isbits value `x` as isbits type `Out`. - -Both types must have the same amount of non-padding bytes. This operation is guaranteed -to be reversible. - -```jldoctest -julia> reinterpret(NTuple{2, UInt8}, 0x1234) -(0x34, 0x12) - -julia> reinterpret(UInt16, (0x34, 0x12)) -0x1234 - -julia> reinterpret(Tuple{UInt16, UInt8}, (0x01, 0x0203)) -(0x0301, 0x02) -``` - -!!! warning - - Use caution if some combinations of bits in `Out` are not considered valid and would - otherwise be prevented by the type's constructors and methods. Unexpected behavior - may result without additional validation. -""" -@inline function reinterpret(::Type{Out}, x::In) where {Out, In} +@inline function _reinterpret(::Type{Out}, x::In) where {Out, In} + # handle non-primitive types isbitstype(Out) || throw(ArgumentError("Target type for `reinterpret` must be isbits")) isbitstype(In) || throw(ArgumentError("Source type for `reinterpret` must be isbits")) - if isprimitivetype(Out) && isprimitivetype(In) - outsize = sizeof(Out) - insize = sizeof(In) - outsize == insize || - throw(ArgumentError("Sizes of types $Out and $In do not match; got $outsize \ - and $insize, respectively.")) - return bitcast(Out, x) - end inpackedsize = packedsize(In) outpackedsize = packedsize(Out) inpackedsize == outpackedsize || diff --git a/test/core.jl b/test/core.jl index f0439afeed23c..a87c45b698e49 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1897,7 +1897,7 @@ function f4528(A, B) end end @test f4528(false, Int32(12)) === nothing -@test_throws ArgumentError f4528(true, Int32(12)) +@test_throws ErrorException f4528(true, Int32(12)) # issue #4518 f4518(x, y::Union{Int32,Int64}) = 0 diff --git a/test/numbers.jl b/test/numbers.jl index d7fd6531b157d..e89dffd8e33cf 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2216,11 +2216,11 @@ end @test round(Int16, -32768.1) === Int16(-32768) end # issue #7508 -@test_throws ArgumentError reinterpret(Int, 0x01) +@test_throws ErrorException reinterpret(Int, 0x01) @testset "issue #12832" begin @test_throws ArgumentError reinterpret(Float64, Complex{Int64}(1)) - @test_throws ArgumentError reinterpret(Int32, false) + @test_throws ErrorException reinterpret(Int32, false) end # issue #41 ndigf(n) = Float64(log(Float32(n)))