bug icon indicating copy to clipboard operation
bug copied to clipboard

`StringBuilder` change in 2.13.9 (`append` returning `this.type`) exposes poor interaction between eta-expansion and overloading

Open LuciferYang opened this issue 2 years ago • 4 comments

Reproduction steps

Scala version: 2.13.9

Welcome to Scala 2.13.9 (OpenJDK 64-Bit Server VM, Java 1.8.0_322).
Type in expressions for evaluation. Or try :help.

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class TestObj(testValue: Option[String] = None)
def appendToBuilder(obj: TestObj, builder: StringBuilder): Unit = {
  obj.testValue.foreach(builder.append)
}


// Exiting paste mode, now interpreting.


  obj.testValue.foreach(builder.append)
                                ^
<pastie>:3: error: type mismatch;
 found   : (x: Char): builder.type <and> (x: Double): builder.type <and> (x: Float): builder.type <and> (x: Long): builder.type <and> (x: Int): builder.type <and> (x: Short): builder.type <and> (x: Byte): builder.type <and> (x: Boolean): builder.type <and> (s: StringBuilder): builder.type <and> (cs: CharSequence): builder.type <and> (s: String): builder.type <and> (x: Any): builder.type (with underlying type (x: Char): builder.type <and> (x: Double): builder.type <and> (x: Float): builder.type <and> (x: Long): builder.type <and> (x: Int): builder.type <and> (x: Short): builder.type <and> (x: Byte): builder.type <and> (x: Boolean): builder.type <and> (s: StringBuilder): builder.type <and> (cs: CharSequence): builder.type <and> (s: String): builder.type <and> (x: Any): builder.type)
 required: String => ?

This code can be compiled with Scala 2.13.8

Welcome to Scala 2.13.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_322).
Type in expressions for evaluation. Or try :help.

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class TestObj(testValue: Option[String] = None)
def appendToBuilder(obj: TestObj, builder: StringBuilder): Unit = {
  obj.testValue.foreach(builder.append)
}


// Exiting paste mode, now interpreting.

class TestObj
def appendToBuilder(obj: TestObj, builder: StringBuilder): Unit

Problem

The same code can be compiled with 2.13.8, but fails with 2.13.9

LuciferYang avatar Sep 20 '22 11:09 LuciferYang

cc @SethTisue

LuciferYang avatar Sep 20 '22 11:09 LuciferYang

This is likely related to https://github.com/scala/scala/commit/35c99eac200cc579f56376a5e8b25fdb1813e8cc, but there's an existing underlying problem:

trait A {
  def foo(s: String): this.type
  def foo(s: Int): this.type
}
trait T {
  val a1: A
  val o: Option[String]

  def t(a2: A): Unit = {
    o.foreach(a1.foo) // ok
    o.foreach(a2.foo) // type mismatch
  }
}

removing the overload gives a hint (i assume):

trait A {
  def foo(s: String): this.type
}
trait T {
  val a1: A
  val o: Option[String]

  def t(a2: A): Unit = {
    o.foreach(a1.foo) // ok
    o.foreach(a2.foo) // error
  }
}

results in

Test.scala:10: error: method with dependent type (s: String): a2.type cannot be converted to function value
    o.foreach(a2.foo)
                 ^
1 error

lrytz avatar Sep 20 '22 12:09 lrytz

Note that the workaround is to write a lambda instead of relying on eta expansion:

obj.testValue.foreach(builder.append(_))

SethTisue avatar Sep 20 '22 13:09 SethTisue

Tentatively milestoned this for 2.13.10 since maybe we could at least improve the error message?

SethTisue avatar Sep 20 '22 13:09 SethTisue