Skip to content

Conversation

@rfourquet
Copy link
Member

T <: Union{A, B} is sometimes meant to mean either A or B, which are concrete types. This can result in crashes or wrong results if T takes actually the value Union{A, B}.

There may be other places in base with similar bugs...

@rfourquet rfourquet added the bugfix This change fixes an existing bug label Jun 17, 2017
Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice finds :)

@JeffBezanson
Copy link
Member

Thanks for finding these. I would like to try to minimize use of @eval though; it makes the code harder to read and duplicates the method bodies. Types like Union{Array{T1}, Array{T2}, ...} can be used instead of Array{T} where T<:Union{T1,T2}.

@rfourquet
Copy link
Member Author

@eval [...] duplicates the method bodies.

OK, I didn't know there would be a difference for the compiler.

Types like Union{Array{T1}, Array{T2}, ...} can be used instead of Array{T} where T<:Union{T1,T2}.

I started in a couple of places, but when the list of types is big, it start to be quite verbose... Please have a look at this patch in array.jl, and if it's fine by you, I will continue the transormation in the remaining places.

base/random.jl Outdated
for i = 16*n128÷sizeof(T)+1:n
@inbounds A[i] = rand(r, T)
for T = (Base.BitInteger64_types..., Int128)
@eval function rand!(r::MersenneTwister, A::Array{$T})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent off a bit

base/array.jl Outdated
function ==(a::A, b::A) where A <: Union{Array{Int8,N},Array{UInt8,N},Array{Int16,N},
Array{UInt16,N},Array{Int32,N},Array{UInt32,N},
Array{Int64,N},Array{UInt64,N},Array{Int128,N},
Array{UInt128,N}} where N
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use something like const BitIntegerArray = Union{map(T->Array{T}, uniontypes(BitInteger))...}.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks, done.

base/array.jl Outdated
const BitIntegerArray{N} = Union{map(T->Array{T,N}, BitInteger_types)...} where N
# use memcmp for == on bit integer types
function ==(a::Array{T,N}, b::Array{T,N}) where T<:BitInteger where N
function ==(a::A, b::A) where A <: BitIntegerArray
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use A for an array type in that many signatures, T or something a few characters longer would be a more common usage

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it useful for distinction as a composite type, but ok.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So T was looking like aneltype, so I chose Arr; if still not good, please suggest.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arr works for me, it's not a variable name that we heavily use for array values

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Quite an understatement as I could not find any use of Arr elsewhere in Base ;-) )

base/random.jl Outdated
rand!(rd::RandomDevice, A::BoolBitIntegerArray) = (win32_SystemFunction036!(A); A)

else # !windows

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be better to remove the blank line at the start of the if is_windows() block than add more at the beginning and end here - this is redundant with the indentation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually prefer to have space before and after struct/method definitions for better readability (i.e. this if/else/end is not usual code), but your call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what isn't usual code about it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just meant it's rare to have struct or method definition within an if block, it's usually at the top level; sometimes the style is amended for special cases, like skipping the indentation corresponding module blocks, I thought why not here, but no pb!

base/random.jl Outdated
end

function rand!(r::MersenneTwister, A::Array{T}) where T<:Union{Base.BitInteger64,Int128}
# A::Array{UInt128} will matche the specialized method above
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match

@rfourquet rfourquet changed the title replace Union with at-eval in some places replace types of Union with Union of types in some places Jun 19, 2017
@rfourquet
Copy link
Member Author

Good to go?

@rfourquet
Copy link
Member Author

Will merge in a couple of days if no objection.

@rfourquet rfourquet merged commit c1f107f into master Jul 6, 2017
@rfourquet rfourquet deleted the rf/Union-eval branch July 6, 2017 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix This change fixes an existing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants