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
Reusing ArrayBuilder after clear() overwrites its previous result #9564
Comments
Imported From: https://issues.scala-lang.org/browse/SI-9564?orig=1 |
@SethTisue said: |
@SethTisue said: |
@SethTisue said: |
@som-snytt said: |
Linas Medžiūnas (linasm) said: |
@Ichoran said: It's an easy fix. The harder part is to decide where to put it. |
Linas Medžiūnas (linasm) said: |
@SethTisue said: |
@Ichoran said: scala> val a = Array.newBuilder[Int]
a: scala.collection.mutable.ArrayBuilder[Int] = ArrayBuilder.ofInt
scala> val b = { a += 1; a.result }
b: Array[Int] = Array(1)
scala> val c = { a.clear(); a += 2; a.result }
c: Array[Int] = Array(2)
scala> val d = b
d: Array[Int] = Array(1) It's just the corner case where the builder returns an array of the right size (and thus doesn't copy) AND has been cleared and reused that we run into any trouble at all. Unless making this work properly slows things down, I don't see much justification for the occasional disastrous behavior, even if we do improve the documentation to make it really clear that you'd better not reuse builders for immutable collections. Also, that other mutable builders also give you problems if you try to do this (because they simply return themselves) is only an argument, I think, that we should document those builders very carefully. In some cases, the API isn't even honored: scala> val a = collection.mutable.ListBuffer.newBuilder[Int]
a: scala.collection.mutable.Builder[Int,scala.collection.mutable.ListBuffer[Int]] = scala.collection.mutable.GrowingBuilder@7de752dd
scala> { a += 1; a.clear; a += 2; a.result }
res47: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2) My recommendation is to make the library as sane as possible and make the documentation as clear as possible regarding possible trouble spots. Having hidden corner cases that bite you when you don't strictly adhere to a conservative reading of the docs despite apparent evidence that the desired behavior is maintained is not a nice thing to deliver to users. |
@sjrd said (edited on Jan 6, 2016 8:23:37 PM UTC): IMO, the main problem is that the documentation of Fixing it for mutable collections will obviously turn the |
@sjrd said: |
@Ichoran said (edited on Jan 7, 2016 1:39:04 AM UTC): Secondly, I'm not arguing that Thirdly, the behavior of mostly-working-except-when-it-doesn't is, docs aside, a poor choice. Now it may be the case that there's no sufficiently nonperturbative way to get out of this situation aside from changing the docs. But I don't think we should be terribly pleased by this state of affairs, and should look for better ways to handle the situation |
Linas Medžiūnas (linasm) said (edited on Jan 8, 2016 8:40:03 AM UTC):
So, if we could draw a line between |
@sjrd said (edited on Jan 8, 2016 9:28:25 AM UTC): In a brand new design, I would fight for a different design where Builders and Collections would not be fused. In such a design,
@rex Kerr, I guess that makes sense. Under that goal, you could argue that we should fix |
@Ichoran said: The only wildcard is how big of a performance benefit it would be for Scala.js. If it's absolutely trashes JS performance for all array creations to have the 100% guarantee, well, maybe that's too great a price to pay. I think ensured 0% is better than 94% with no warning on the 6% failures (well, not exactly 6%, really p(n = 16) + p(n = 32) + p(n = 64) + ...). |
@sjrd said: |
@Ichoran said: @sjrd This is what I had in mind. |
In some cases ArrayBuilder.elems may still point to the previously created array after a call to ArrayBuilder.clear(). As a result, reusing such ArrayBuilder overwrites the contents of previously created array:
IMHO a simple fix would be to reset the field ArrayBuilder.elems on ArrayBuilder.clear() to a new array.
The text was updated successfully, but these errors were encountered: