Skip to content

LinearSeqOps.lengthCompare calls isEmpty, which calls lengthCompare, hence StackOverflowException #12805

Closed as not planned
@noresttherein

Description

@noresttherein

Reproduction steps

Scala version: 2.13.11

	class ConstSeq[X](override val head :X, override val knownSize :Int) extends AbstractSeq[X] with LinearSeq[X] {
		override def tail :LinearSeq[X] = {
			if (knownSize == 0)
				throw new UnsupportedOperationException("Seq.empty.tail")
			new ConstSeq(head, knownSize - 1)
		}
	}
	new ConstSeq(42, 2).isEmpty

Problem

Exception in thread "main" java.lang.StackOverflowError
	at scala.collection.LinearSeqOps.lengthCompare(LinearSeq.scala:95)
	at scala.collection.LinearSeqOps.lengthCompare$(LinearSeq.scala:86)
	at Playground$ConstSeq.lengthCompare(Playground.scala:12)
	at scala.collection.SeqOps.isEmpty(Seq.scala:843)
	at scala.collection.SeqOps.isEmpty$(Seq.scala:843)
	at scala.collection.AbstractSeq.isEmpty(Seq.scala:1189)
	at scala.collection.LinearSeqOps.loop$1(LinearSeq.scala:89)
	at scala.collection.LinearSeqOps.lengthCompare(LinearSeq.scala:96)
	at scala.collection.LinearSeqOps.lengthCompare$(LinearSeq.scala:86)
	at Playground$ConstSeq.lengthCompare(Playground.scala:12)
	at scala.collection.SeqOps.isEmpty(Seq.scala:843)
	at scala.collection.SeqOps.isEmpty$(Seq.scala:843)
	at scala.collection.AbstractSeq.isEmpty(Seq.scala:1189)
	at scala.collection.LinearSeqOps.loop$1(LinearSeq.scala:89)
	at scala.collection.LinearSeqOps.lengthCompare(LinearSeq.scala:96)
	at scala.collection.LinearSeqOps.lengthCompare$(LinearSeq.scala:86)
	at Playground$ConstSeq.lengthCompare(Playground.scala:12)
	at scala.collection.SeqOps.isEmpty(Seq.scala:843)
	at scala.collection.SeqOps.isEmpty$(Seq.scala:843)
	at scala.collection.AbstractSeq.isEmpty(Seq.scala:1189)
	at scala.collection.LinearSeqOps.loop$1(LinearSeq.scala:89)
	at scala.collection.LinearSeqOps.lengthCompare(LinearSeq.scala:96)
	at scala.collection.LinearSeqOps.lengthCompare$(LinearSeq.scala:86)
	at Playground$ConstSeq.lengthCompare(Playground.scala:12)

Now, a 'fix' for this could be just as well mentioning in the docs that isEmpty must be overridden, or similar, but the current situation is not ideal. Also, perhaps both should try knownSize first? The current implementation is a bit too specific to our immutable.List, while an immutable list implementation of a known size (nomen omen) is not unheard of.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions