Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with type inference in comprehensions #17717

Closed
garrison opened this issue Jul 30, 2016 · 10 comments
Closed

Issue with type inference in comprehensions #17717

garrison opened this issue Jul 30, 2016 · 10 comments
Labels
types and dispatch Types, subtyping and method dispatch

Comments

@garrison
Copy link
Sponsor Member

garrison commented Jul 30, 2016

In the discussion for #7258 it was proposed to make empty comprehensions return Array{Union{},1}, but the text of the relevant NEWS.md entry suggests that this was ultimately rejected, if I understand correctly. ("If the result is empty, then type inference is still used to determine the element type," it says.) However, the final expression below seems to result in a Array{Union{},1}, even though it should be possible to infer the type.

julia> a = [4,5,6]
3-element Array{Int64,1}:
 4
 5
 6

julia> typeof([i for i in 1:3])
Array{Int64,1}

julia> typeof([a[i] for i in 1:3])
Array{Int64,1}

julia> typeof([i for i in 1:0])
Array{Int64,1}

julia> typeof([a[i] for i in 1:0])
Array{Union{},1}

In particular, this causes the following to blow up:

julia> sum([a[i] for i in 1:0])
ERROR: StackOverflowError:
 in convert(::Type{Union{}}, ::Int64) at ./sysimg.jl:55 (repeats 80000 times)
@KristofferC
Copy link
Sponsor Member

What if a is a const?

@garrison
Copy link
Sponsor Member Author

@KristofferC setting a to be const fixes it. I have experienced a similar thing within functions; let me see if I can reproduce with a better example.

@garrison
Copy link
Sponsor Member Author

This program:

function f(n)
    a = zeros(Int, 3)
    @show [a[j] for j in 1:n]
    b = zeros(Int, 3)
    @show [b[j] for j in 1:n]
    c = zeros(Int, 3)
    @show [c[j] for j in 1:n]
end

f(0)

outputs the following:

[a[j] for j = 1:n] = Int64[]
[b[j] for j = 1:n] = Union{}[]
[c[j] for j = 1:n] = Union{}[]

If you re-order it so that a, b, and c are defined before any of the comprehensions, it works as expected. If instead you comment out the first two lines of the function, the third and fourth lines work as expected, but the fifth and sixth still result in Union{}[].

@kshyatt kshyatt added the types and dispatch Types, subtyping and method dispatch label Jul 30, 2016
@JeffBezanson
Copy link
Sponsor Member

The behavior is exactly as described in NEWS. This was discussed very extensively. The available options are (1) the current behavior, (2) always return Array{Union{}}, (3) give an error in the empty case. Option (1) was deemed least bad.

@garrison
Copy link
Sponsor Member Author

garrison commented Aug 1, 2016

I don't understand how repeating the same pair of lines (aside from changing the variable name from a to b to c) should lead to different results on the second and third runs in the function above.

Also---and perhaps a separate bug---I think sum(Union{}[]) should do something other than a StackOverflowError, possibly a MethodError? The underlying issue is that zero(Union{}) itself causes a stack overflow.

@tkelman
Copy link
Contributor

tkelman commented Aug 1, 2016

[a[j] for j = 1:n] = Int64[]
[b[j] for j = 1:n] = Union{}[]

looks like wat material to me.

perhaps a separate bug---I think sum(Union{}[]) should do something other than a StackOverflowError, possibly a MethodError? The underlying issue is that zero(Union{}) itself causes a stack overflow.

I agree we should try to avoid the stack overflow there, perhaps a "deliberately unimplemented" MethodError.

@KristofferC
Copy link
Sponsor Member

I am also quite perplexed by the behavior here. It looks like 3 identical uncoupled statements so type inference should give the same answer for all of them?

@JeffBezanson
Copy link
Sponsor Member

This is why some of us argued for always returning Array{Union{}} even though it seems bad at first. We talk about how type inference results are not predictable, and are not meant to be, and people never quite seem to believe us. Well, here you go.

@KristofferC
Copy link
Sponsor Member

But why is b and c boxed here?

@JeffBezanson
Copy link
Sponsor Member

I agree it ideally shouldn't be, but it's probably the same problem as #15276.

garrison added a commit to garrison/ExactDiag.jl that referenced this issue Aug 3, 2016
garrison added a commit to garrison/ExactDiag.jl that referenced this issue Nov 19, 2017
but on the second line the same specifier is still, sadly, necessary

That these specifiers became necessary here was what led me to report
JuliaLang/julia#17717 (comment)
back when julia 0.5 was starting to stabilize
(see bec87df).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

No branches or pull requests

5 participants