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

end is unsafe with user-defined getindex #16104

Closed
mlubin opened this issue Apr 28, 2016 · 13 comments
Closed

end is unsafe with user-defined getindex #16104

mlubin opened this issue Apr 28, 2016 · 13 comments

Comments

@mlubin
Copy link
Member

mlubin commented Apr 28, 2016

Ref jump-dev/JuMP.jl#730, it seems like there's no way to change the behavior of end translating to size when used within a multidimensional array, which means that it's unsafe to use end to index into JuMP arrays which don't use 1-based indexing. Any hope of a solution to this?

CC @joehuchette @IainNZ
(Thanks @yuyichao for the pointer)

@stevengj
Copy link
Member

Shouldn't it call endof instead?

@mlubin
Copy link
Member Author

mlubin commented Apr 28, 2016

@stevengj that's the case only for one-dimensional arrays IIRC

@stevengj
Copy link
Member

It would be natural to extend it to call endof(A, i) in the i-th dimension.

@mlubin
Copy link
Member Author

mlubin commented Apr 28, 2016

I can play around with a PR for that if it has a chance of going through

@stevengj
Copy link
Member

stevengj commented Apr 28, 2016

Here is the relevant code in julia-syntax.scm.

Replacing size(A,i) with endof(A,i) looks pretty easy, and makes sense to me.

A complication is that it calls trailingsize for the last index in cases with 2 or more indices, so that you can do e.g. A[i,end] even if A is 3-dimensional and get A[i,end,end]. (@StefanKarpinski, why do we allow this?) But I guess you could overload Base.trailingsize in JuMP too.

@mlubin
Copy link
Member Author

mlubin commented Apr 28, 2016

trailingsize isn't an issue for us because we already error on getindex when the number of dimensions doesn't match.

@StefanKarpinski
Copy link
Member

A complication is that it calls trailingsize for the last index in cases with 2 or more indices, so that you can do e.g. A[i,end] even if A is 3-dimensional and get A[i,end,end]. (@StefanKarpinski, why do we allow this?) But I guess you could overload Base.trailingsize in JuMP too.

Isnt' this "generalized linear indexing", on the chopping block in 0.5, see #14770.

@stevengj
Copy link
Member

stevengj commented Apr 28, 2016

@mlubin, you would still have to overload it because otherwise it will return size(A,i) for the last dimension. Better yet, we can call trailingendof instead of trailingsize, defined as:

trailingendof(A,n) = n == ndims(A) ? endof(A,n) : trailingsize(A,n)

Good to hear that this "feature" is on the chopping block, though; we can then remove trailingendof and just call endof(A,n).

(So far, the only registered packages that use the unexported Base.trailingsize function seem to be DSP.jl, ZipFile.jl, and Zlib.jl.)

@mlubin
Copy link
Member Author

mlubin commented Apr 28, 2016

Will it be easier to fix this after #14770?

@stevengj
Copy link
Member

@mlubin, no, I think the two can be done independently if you define trailingendof as I suggested above. After general linear indexing is removed, then trailingendof can be removed and replaced with endof.

@mbauman
Copy link
Member

mbauman commented Apr 28, 2016

How about we just lower to one function name in all cases? This moves the logic into a place where custom types can intercept it… and it decouples the last index from the size. You just need a three-argument function lastindex(A, dim, is_last_index). Maybe that could even get folded into endof.

Cartesian indices still pose a problem: rand(3,2,1)[CartesianIndex((3,2)), end]… but that's a much harder problem that may be just fine left unresolved.

@stevengj
Copy link
Member

stevengj commented Apr 28, 2016

@mbauman, because the goal is to get rid of trailingendof, this should remain an undocumented internal function that custom types shouldn't touch. Anyone overriding endof should only have to implement the 2-argument version.

@mbauman
Copy link
Member

mbauman commented May 10, 2018

I believe this should be fixed (or be feasible to fix within an offset array package) via #25763.

@mbauman mbauman closed this as completed May 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants