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

NullPointerException using Vector in 2.13.8 and 3.1.1 #12564

Closed
jackkoenig opened this issue Mar 24, 2022 · 5 comments · Fixed by scala/scala#9983
Closed

NullPointerException using Vector in 2.13.8 and 3.1.1 #12564

jackkoenig opened this issue Mar 24, 2022 · 5 comments · Fixed by scala/scala#9983

Comments

@jackkoenig
Copy link

jackkoenig commented Mar 24, 2022

Reproduction steps

Scala version: 2.13.8, 3.1.1

val vector1 = Vector.fill(1000)(0)

// Some prepending, manifesting the bug seems to require 2 separate prepends
val vector2 = List.fill(25)(1) ++: 2 +: vector1

// Now append for fun and profit
val vector3 = vector2 ++ List.fill(40)(3)

// Any iteration will do although might hit NullPointerException in different place
vector3.collect { case n => n }

Scala 2.13.8 Scastie: https://scastie.scala-lang.org/Z2g0dZaoRvG6iZchGULXBQ
Scala 3.1.1 Scastie: https://scastie.scala-lang.org/fA91IRCPRi2PSDkPWUOFOg

Problem

Run the above and you will see the stack trace:

java.lang.NullPointerException: Cannot read the array length because "this.a1" is null
	at scala.collection.immutable.NewVectorIterator.advance(Vector.scala:2031)
	at scala.collection.immutable.NewVectorIterator.next(Vector.scala:1992)
	at scala.collection.StrictOptimizedIterableOps.collect(StrictOptimizedIterableOps.scala:150)
	at scala.collection.StrictOptimizedIterableOps.collect$(StrictOptimizedIterableOps.scala:136)
	at scala.collection.immutable.Vector.collect(Vector.scala:113)
	at Playground$.delayedEndpoint$Playground$1(main.scala:12)
	at Playground$delayedInit$body.apply(main.scala:2)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at scala.Function0.apply$mcV$sp$(Function0.scala:39)
	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
	at scala.App.$anonfun$main$1(App.scala:76)
	at scala.App.$anonfun$main$1$adapted(App.scala:76)
	at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:563)
	at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:561)
	at scala.collection.AbstractIterable.foreach(Iterable.scala:926)
	at scala.App.main(App.scala:76)
	at scala.App.main$(App.scala:74)
	at Playground$.main(main.scala:2)
	at Main$.main(main.scala:19)
@SethTisue SethTisue added this to the 2.13.9 milestone Mar 24, 2022
@SethTisue
Copy link
Member

SethTisue commented Mar 24, 2022

nice catch and minimization!

@scala/collections anyone feel like digging into this?

@jackkoenig
Copy link
Author

Note of interest, if you change the appended collection size from 40 to 30, you get the NullPointerException on the append:

val vector1 = Vector.fill(1000)(0)

// Some prepending, manifesting the bug seems to require 2 separate prepends
val vector2 = List.fill(25)(1) ++: 2 +: vector1

// Now append for fun and profit
val vector3 = vector2 ++ List.fill(30)(3)

Gives:

java.lang.NullPointerException: Cannot read the array length because "copyIfDifferentSize_a" is null
	at scala.collection.immutable.VectorBuilder.result(Vector.scala:1761)
	at scala.collection.immutable.Vector.appendedAll0(Vector.scala:235)
	at scala.collection.immutable.Vector3.appendedAll0(Vector.scala:637)
	at scala.collection.immutable.Vector.appendedAll(Vector.scala:203)
	at scala.collection.immutable.Vector.appendedAll(Vector.scala:113)
	at scala.collection.SeqOps.concat(Seq.scala:187)
	at scala.collection.SeqOps.concat$(Seq.scala:187)
	at scala.collection.AbstractSeq.concat(Seq.scala:1161)
	at scala.collection.IterableOps.$plus$plus(Iterable.scala:726)
	at scala.collection.IterableOps.$plus$plus$(Iterable.scala:726)
	at scala.collection.AbstractIterable.$plus$plus(Iterable.scala:926)
	at Playground$.delayedEndpoint$Playground$1(main.scala:9)
	at Playground$delayedInit$body.apply(main.scala:2)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at scala.Function0.apply$mcV$sp$(Function0.scala:39)
	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
	at scala.App.$anonfun$main$1(App.scala:76)
	at scala.App.$anonfun$main$1$adapted(App.scala:76)
	at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:563)
	at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:561)
	at scala.collection.AbstractIterable.foreach(Iterable.scala:926)
	at scala.App.main(App.scala:76)
	at scala.App.main$(App.scala:74)
	at Playground$.main(main.scala:2)
	at Main$.main(main.scala:19)
	at Main.main(main.scala)

Scala 2.13.8 Scastie: https://scastie.scala-lang.org/xmHvVtcCQuCkwdIN4SRCJA

@griggt
Copy link

griggt commented Mar 24, 2022

Hmm...

scala> vector2.##
java.lang.ArrayIndexOutOfBoundsException: 8
  at scala.collection.immutable.Vector3.apply(Vector.scala:549)
  at scala.util.hashing.MurmurHash3.indexedSeqHash(MurmurHash3.scala:259)
  at scala.util.hashing.MurmurHash3$.seqHash(MurmurHash3.scala:354)
  at scala.collection.Seq.hashCode(Seq.scala:41)
  at scala.collection.Seq.hashCode$(Seq.scala:41)
  at scala.collection.AbstractSeq.hashCode(Seq.scala:1161)
  at scala.runtime.Statics.anyHash(Statics.java:127)
  ... 32 elided

@griggt
Copy link

griggt commented Mar 24, 2022

Scala 2.13.2 is OK, 2.13.3 is bad. Maybe regressed in scala/scala#9036 ?

@lrytz
Copy link
Member

lrytz commented Mar 25, 2022

incorrect assumption that k is positive

scala/scala#9036 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants