@@ -610,6 +610,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
610
610
genTraitConstructorDefDef(dd)
611
611
else
612
612
genStaticForwarderForDefDef(dd)
613
+ genInterfaceMethodBridgeForDefDef(dd)
613
614
genDefDef(dd)
614
615
else
615
616
genDefDef(dd)
@@ -690,6 +691,48 @@ trait BCodeSkelBuilder extends BCodeHelpers {
690
691
).transform(dd.rhs)
691
692
})
692
693
694
+ /** Creates a bridges for interfece inherited and narrowed methods,
695
+ * to workaround JVM limitations when using LambdaMetaFactory (see issue #15402)
696
+ * Example:
697
+ * ```
698
+ * trait Foo:
699
+ * def self: Foo
700
+ *
701
+ * trait Bar extends Foo:
702
+ * def self: Bar = this
703
+ * def SAM(x: Any): Any
704
+ *
705
+ * def usage(x: List[Foo]) = x.map(_.self)
706
+ * ```
707
+ * We need to define a bridge in trait Bar `def self: Foo = Bar.this.self`
708
+ * in order to prevent JVM runtime exceptions. Otherwise at the time of
709
+ * accessing `_.self` in the SAM instance created based on the `trait Bar`
710
+ * it will complain about missing implementation of `def self: Foo`.
711
+ * Javac compiler does exactly the same.
712
+ */
713
+ private def genInterfaceMethodBridgeForDefDef (dd : DefDef ): Unit =
714
+ val sym = dd.symbol
715
+ sym.owner.directlyInheritedTraits
716
+ .flatMap { parent =>
717
+ val inheritedSym = parent.info.decl(sym.name)
718
+ Option .when(
719
+ inheritedSym.exists &&
720
+ sym.signature != inheritedSym.signature &&
721
+ sym.info <:< inheritedSym.info
722
+ )(inheritedSym.symbol.asTerm)
723
+ }.distinctBy(_.signature)
724
+ .foreach(genInterfaceMethodBridge(sym.asTerm, _))
725
+
726
+ private def genInterfaceMethodBridge (sym : TermSymbol , inheritedSym : TermSymbol ): Unit =
727
+ assert(sym.name == inheritedSym.name, " Not an override" )
728
+ val owner = sym.owner.asClass
729
+ val bridgeSym = inheritedSym.copy(owner = owner, flags = sym.flags).asTerm
730
+ val bridge = tpd.DefDef (bridgeSym, {paramss =>
731
+ val params = paramss.head
732
+ tpd.Apply (tpd.This (owner).select(sym), params)
733
+ })
734
+ genDefDef(bridge)
735
+
693
736
private def genStaticForwarderForDefDef (dd : DefDef ): Unit =
694
737
val forwarderDef = makeStaticForwarder(dd)
695
738
genDefDef(forwarderDef)
0 commit comments