-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: fix #31295, allow e.g. view(a,:) .+= view(b,:)
#31300
Conversation
I think this lowering makes the most amount of sense here, but you're right that a dot-expression on the LHS does indeed throw a wrinkle into things. Assuming f.(A) .+= g.(A) I have two possible mental models for the above expression. I could imagine it being the equivalent of the for i in eachindex(A)
f(A[i]) += g(A[i])
end or I can think of it as broadcast!((x,y)->f(x)+g(y), f.(A), A, A) Neither of these models suggest a very useful semantic for the lowering here — the first is a syntax error and the second broadcasts into a temporary array that negates the whole raison d'être of So, I think I approve of your interpretation here — we'll throw up our hands and not worry about the potential of fusing the LHS on either side of the expression. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a lisp reviewer, but I approve of what this PR says on the tin. :)
Arguably we should do the same transformation for |
The practical case when it is important is for instance (I give the simplest possible scenario):
while this works:
The reason is that quite often you dynamically determine the symbol to point to a field (this happens often when you work with tabular data structures with special methods for As I am not a Lisp expert either I just want to make sure that we have it covered (I guess we have, but just to make sure). |
Maybe it would be best to explicitly write in the documentation in what cases what kind of lowering happens so at least we are explicit? |
5dcaeb2
to
6aa18ff
Compare
I added this change. It should be more efficient, since we can avoid an extra |
Yes, this should be safe and completely nonbreaking:
I approve! |
Well I had a blind spot in both my broadcasting alias analysis and the above reasoning; this PR does indeed change behaviors if there are repeated indices. I do think this could be considered a bug given how the behaviors are different with and without Julia 1.1: julia> x = [1]
x[[1,1]] .+= 1
2-element view(::Array{Int64,1}, [1, 1]) with eltype Int64:
2
2
julia> x = [1]
@views x[[1,1]] .+= 1
2-element view(::Array{Int64,1}, [1, 1]) with eltype Int64:
3
3 This PR makes the answer in both cases |
I do believe it should be x[[1,1]] .+= 1 is equivalent to x[1] += 1
x[1] += 1 |
I'm inclined to agree, but that mental model doesn't extend to our other unaliasing behaviors: julia> x = [3,4]
x .+= view(x, [2,1]) # This view gets unaliased and copied
x
2-element Array{Int64,1}:
7
7
julia> x = [3,4]
x[1] += x[2]# So it's not the same as the unrolled version
x[2] += x[1]
x
2-element Array{Int64,1}:
7
11 That's the simplification, but the same thing happens in |
Ah so the alternate view is something like: x[1] = xorig[1] + 1
x[1] = xorig[1] + 1 Hmm. |
Looks like I should put the old behavior back pending a full decision on this. |
Thanks Jeff. We can move the larger design questions to #31392. |
Is this change going to be backported? (CC @nalimilan) |
I'm not 100% sure what to do here, but basically for any LHS expression except a
getindex
this will be lowered toSo there's no fusion between the LHS and RHS, but that seems tricky.