Is this expected behavior (0.5 to 0.6 breakage)?


#1

In 0.5:

julia> a = Vector{UInt32}([0x01, 0x02, 0x03])
3-element Array{UInt32,1}:
 0x00000001
 0x00000002
 0x00000003

julia> a + 1
3-element Array{UInt32,1}:
 0x00000002
 0x00000003
 0x00000004

In 0.6:

julia> a = Vector{UInt32}([0x01, 0x02, 0x03])
3-element Array{UInt32,1}:
 0x00000001
 0x00000002
 0x00000003

julia> a + 1
3-element Array{Int64,1}:
 2
 3
 4

(Is there a reason this change was made? FWIW, I prefer the old behavior. Changing the type out from under me broke a bunch of things, like Base.dSFMT.dsfmt_gv_init_by_array, which expects a Vector{UInt32}.


#2

1 is presumably an Int64, so wouldn’t you prefer the new behaviour, where it promotes to the larger type?


#3

I wouldn’t, actually, because the code that was working:

Base.dSFMT.dsfmt_gv_init_by_array(MersenneTwister(seed).seed+1)

breaks in 0.6 because now the argument has switched type, and there’s no method for dsfmt_gv_init_by_array that takes a vector of Int64.

It seems to me that if you don’t have to change the type, you shouldn’t. (Principle of least surprise?)


#4

But you are adding two different types, so it has to change the type of one of them. Promoting to the largest type is the most reliable.

Use one(UInt32) instead if you want to keep everything a UInt32


#5

Julia 0.5 had the behaviour of promotion in vectors being different to outside of vectors.

Below is julia 0.5

julia> 0x03 + 1
4

julia> [0x03] + 1
1-element Array{UInt8,1}:
 0x04

julia> 0x03 + -4
-1

julia> [0x03] + -4
ERROR: InexactError()
 in .+(::Array{UInt8,1}, ::Int64) at ./arraymath.jl:82
 in +(::Array{UInt8,1}, ::Int64) at ./arraymath.jl:94

I would expect that adding a Signed and an Unsigned type would always give a Signed type.
Whether it is inside a Vector or not.

Any code expecting otherwise was already wrong.
Its just that julia 0.5 was wrong in the same way.


I suggest using 0x1 a UInt8 literal
Since 0x... is the literal for a unsigned integer of the smallest type that can hold it.
So it 0x1 will (basically) always promote to the other type when used to increment it.

As compared to 1 which is a signed Int literal, which will either be 32bit or 64 bit depending on system.


#6

Promoting to the largest type is the most reliable.

Then I’d suggest that 'a' + 1 should equal 98, not 'b':

julia> sizeof('a')
4

julia> sizeof(1)
8

#7

Char is not a numeric type.
Does not follow the:
Promote to largest, and most signed type rule.
Or the Promote to a type that is at least as large and as signed as the most signed input


#8

I don’t think this is an intended change: I cannot find anything in NEWS.md mentioning it. If I remember correctly, array eltypes are (were) not promoted due to the size change in the array. The array of the original example doubles in size due to the promotion, which can be an issue with large arrays.

You should file an issue, if there is non already. At least a NEWS.md entry would be needed if this breaking change was indeed intended.


#9

This was changed in https://github.com/JuliaLang/julia/pull/19692 with a corresponding NEWS entry (albeit perhaps a bit cryptic).


#10

x-ref: https://github.com/JuliaLang/julia/issues/20946