Skip to content

AbstractMethodError in SAM lambdas when SAM contains method overrided with narrowed type #15402

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

Open
Odomontois opened this issue Jun 8, 2022 · 3 comments · May be fixed by #15551
Open

AbstractMethodError in SAM lambdas when SAM contains method overrided with narrowed type #15402

Odomontois opened this issue Jun 8, 2022 · 3 comments · May be fixed by #15551

Comments

@Odomontois
Copy link

Odomontois commented Jun 8, 2022

Compiler version

3.1.2
and
3.2.0-RC1-bin-20220607-76a0b29-NIGHTLY

Minimized code

trait Named:
  def name: String

  def me: Named
end Named

trait Foo extends Named:
  def name = "foo"

  def me: Foo = this

  def foo(x: String): String
end Foo

class Names(xs: List[Named]):
  def mkString = xs.iterator.map(_.me.name).mkString(",")

object Names:
  def single[T <: Named](t: T): Names = Names(List(t))

@main def Repro() =
  val names = Names.single[Foo](x => x)
  println(names.mkString)

Output

Exception in thread "main" java.lang.AbstractMethodError: Receiver class Moons$package$$$Lambda$15/0x0000000800c074f8 does not define or inherit an implementation of the resolved method 'abstract .Named me()' of interface Named.
	at Names.mkString$$anonfun$1(Moons.scala:18)
	at scala.collection.Iterator$$anon$9.next(Iterator.scala:577)
	at scala.collection.IterableOnceOps.addString(IterableOnce.scala:1184)
	at scala.collection.IterableOnceOps.addString$(IterableOnce.scala:1179)
	at scala.collection.AbstractIterator.addString(Iterator.scala:1293)
	at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1129)
	at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1127)
	at scala.collection.AbstractIterator.mkString(Iterator.scala:1293)
	at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1142)
	at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1142)
	at scala.collection.AbstractIterator.mkString(Iterator.scala:1293)
	at Names.mkString(Moons.scala:18)
	at $package$.Repro(Moons.scala:25)
	at Repro.main(Moons.scala:23)

Scastie link

https://scastie.scala-lang.org/Odomontois/kzIirdZ1RRaDr1Wm8QN9TA/1

@Odomontois Odomontois added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Jun 8, 2022
@smarter
Copy link
Member

smarter commented Jun 8, 2022

Scala 2 handles this by not generating an invokedynamic lambda in this situation and falling back to an anonymous class instance instead, I guess we should do the same (in https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala).

@smarter smarter added area:transform and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Jun 8, 2022
@odersky
Copy link
Contributor

odersky commented Jun 12, 2022

@WojciechMazur Do you think you could take this on?

@tpunder
Copy link

tpunder commented Nov 7, 2023

I just ran into this issue.

Here is another minimized example:

trait Adapter[T] extends Function1[T, Unit]

object Example {
  def main(args: Array[String]): Unit = {
    // In Scala 3 this causes a java.lang.AbstractMethodError
    makeAdapter[Integer](123)
  }

  // Works in Scala 2.12 and 2.13 but generates wrong bytecode for Scala 3
  // due to using `(arg: Number) => ()` instead of `(arg: T) => ()`
  def makeAdapter[T <: Number]: Adapter[T] = (arg: Number) => ()

https://scastie.scala-lang.org/cRqYj3CiSpWxGrGJNeV2Ww

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