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

return type of size(::AbstractArray) and size(::AbstractArray,::Int) #9777

Open
Jutho opened this issue Jan 14, 2015 · 8 comments
Open

return type of size(::AbstractArray) and size(::AbstractArray,::Int) #9777

Jutho opened this issue Jan 14, 2015 · 8 comments
Labels
arrays [a, r, r, a, y, s] compiler:inference Type inference

Comments

@Jutho
Copy link
Contributor

Jutho commented Jan 14, 2015

I was surprised to find out that the return type of size(::AbstractArray,::Int) is Any, which I traced back to the return type of size(::AbstractArray) being (Any,...), which originates from what I can see from the return type of length(::Range) being Any. This seems somewhat unfortunate, wouldn't the fact that size always returns an NTuple{N,Int} be part of the implicit interface specification of AbstractArray{T,N}, just like length should always return an Int?

I stumbled upon this when revisiting my old interest of permutedims, where I now noted the ::SubArray typeassert here , which actually doesn't work as the return type of first_index of a SubArray is not inferred correctly, exactly because of the issue in the title.

@timholy
Copy link
Member

timholy commented Jan 14, 2015

When given an abstract type like Range or AbstractArray, it's not entirely surprising that it's not always Int. For example, in base we have length defined for a range of dates, and for dates it seems plausible that the return type of length should be "unitful."

However, many other range types also give broad inference results for length, like StepRange{T<:Integer,S}. About the only one that is "naturally" inferred is UnitRange{T<:Integer}. length for an AbstractArray infers to an Int only because of a typeassert in abstractarray.jl.

@Jutho
Copy link
Contributor Author

Jutho commented Jan 15, 2015

I don't see why length should be unitful if length corresponds to a number of steps or a number of elements, which should always be an integer without unit. Not saying it has to be Int, but it should be Integer? Surely there are other meanings of the word length which could make sense for certain objects and which have a unit, like indeed time periods or geometrical objects, but then I guess they should not be additional methods of Base.length, which, according to the docs, always has to do with a number of elements.

Also, it's a bit arbitrary to add a typeassert to length but not to size in abstractarray.jl. I guess this is not really intentional?

@timholy
Copy link
Member

timholy commented Jan 15, 2015

I was forgetting the step must be defined---I was thinking of it as a span, but of course that's not right.

@Jutho
Copy link
Contributor Author

Jutho commented Jan 15, 2015

Well, I was also somewhat to quick / tired yesterday. It doesn't indeed really make sense to consider abstract types. For the concrete ranges, the length seems to be (on my 64bit system) Int64 or UInt64, where the latter makes sense as it could not fit in the former if you would really want to construct a range over all UInt64 numbers. I guess I was just trying to understand the rationale behind the typeassert of SubArray in the permutedims code, which I assume doesn't really do much?

But this triggered the related question: why a typeassert for length of AbstractArray but not for size?

@timholy
Copy link
Member

timholy commented Jan 15, 2015

I suspect we should add the typeassert for size. I have no idea what the assert is doing in permutedims, it sees very strange to me.

@simonster
Copy link
Member

I added that typeassert to the permutedims code in cdb6f7c. It actually fixes a performance problem when B is not a SubArray. Even if !isa(B, SubArray), type inference still decides to go down that branch (#5560 etc., although the branch is later optimized out during code generation). If it's not a SubArray, then there is no applicable first_index method, so type inference decides it returns Any. Then offset is also Any, which is not good.

@brenhinkeller
Copy link
Contributor

brenhinkeller commented Nov 16, 2022

FWIW, the current state of affairs (Julia 1.8.2):

julia> Core.Compiler.return_type(size, Tuple{Array,Int})
Int64

julia> Core.Compiler.return_type(size, Tuple{DenseArray,Int})
Any

julia> Core.Compiler.return_type(size, Tuple{AbstractArray,Int})
Any

julia> Core.Compiler.return_type(size, Tuple{UnitRange,Int})
Any

julia> Core.Compiler.return_type(size, Tuple{Base.OneTo,Int})
Any

Base.OneTo returning Any is the one that surprised me

@martinholters
Copy link
Member

Note that e.g.

ulia> Core.Compiler.return_type(size, Tuple{Base.OneTo{Int},Int})
Int64

For the non-concrete OneTo (without type parameter), the issue comes from

julia> Core.Compiler.return_type(length, Tuple{Base.OneTo})
Any

And the best we can do there is probably Integer.

@brenhinkeller brenhinkeller added arrays [a, r, r, a, y, s] compiler:inference Type inference labels Nov 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arrays [a, r, r, a, y, s] compiler:inference Type inference
Projects
None yet
Development

No branches or pull requests

5 participants