Change in varargs in Scala-2.13?

Hi all, in 2.12 this worked fine:

val argList = ListBuffer[AnyRef]()
jdbcTemplate.update(sb.toString(), argList:_*)

But in 2.13 it doesn’t compile:

type mismatch;
 found   : scala.collection.mutable.ListBuffer[AnyRef]
 required: Seq[?]

If I make a seq out of it, calling toSeq, it works:

val argList = ListBuffer[AnyRef]()
jdbcTemplate.update(sb.toString(), argList.toSeq:_*)

I find this strange as a ListBuffer is also a Seq, what’s going on?

Yes it has changed. A straightforward explanation happily, Seq is now an alias for collection.immutable.Seq whereas prior to 2.13 it could have been mutable.

See the release notes.

Given we already need special syntax for varargs it would be very convenient for developers if the compiler made this transparent.

I think it really can’t, and shouldn’t be – you’re trying to pass a mutable data structure to a situation that requires immutability. It was arguably a bug that it worked before…

2 Likes

IMO passing a mutable structure is fine and requiring immutable was a mistake. As long as you’re not concurrently modifying it, it’s fine. If you are concurrently modifying it, stop doing that. That concurrently modifying mutable collections is dangerous should go without saying, varargs or not.

Right, but the thing is, if I’ve declared a varargs parameter, I am expecting to receive a literal list – and therefore I don’t expect that list to be mutable. That’s what I think of as the normal state of affairs; :_* is an unfortunately-necessary workaround, but the underlying expectation is that it’s immutable.

All IMO, of course, and there’s room to disagree, but I do think the change was appropriate, and better matches my expectations as a library author…

1 Like

As a library author, you don’t have to take responsibility for your callers concurrently modifying the collection they’re passing you. If they choose to do so anyway, they can and should expect trouble.