@@ -688,6 +688,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
688
688
genTraitConstructorDefDef(dd)
689
689
else
690
690
genStaticForwarderForDefDef(dd)
691
+ genInterfaceMethodBridgeForDefDef(dd)
691
692
genDefDef(dd)
692
693
else
693
694
genDefDef(dd)
@@ -768,6 +769,48 @@ trait BCodeSkelBuilder extends BCodeHelpers {
768
769
).transform(dd.rhs)
769
770
})
770
771
772
+ /** Creates a bridges for interfece inherited and narrowed methods,
773
+ * to workaround JVM limitations when using LambdaMetaFactory (see issue #15402)
774
+ * Example:
775
+ * ```
776
+ * trait Foo:
777
+ * def self: Foo
778
+ *
779
+ * trait Bar extends Foo:
780
+ * def self: Bar = this
781
+ * def SAM(x: Any): Any
782
+ *
783
+ * def usage(x: List[Foo]) = x.map(_.self)
784
+ * ```
785
+ * We need to define a bridge in trait Bar `def self: Foo = Bar.this.self`
786
+ * in order to prevent JVM runtime exceptions. Otherwise at the time of
787
+ * accessing `_.self` in the SAM instance created based on the `trait Bar`
788
+ * it will complain about missing implementation of `def self: Foo`.
789
+ * Javac compiler does exactly the same.
790
+ */
791
+ private def genInterfaceMethodBridgeForDefDef (dd : DefDef ): Unit =
792
+ val sym = dd.symbol
793
+ sym.owner.directlyInheritedTraits
794
+ .flatMap { parent =>
795
+ val inheritedSym = parent.info.decl(sym.name)
796
+ Option .when(
797
+ inheritedSym.exists &&
798
+ sym.signature != inheritedSym.signature &&
799
+ sym.info <:< inheritedSym.info
800
+ )(inheritedSym.symbol.asTerm)
801
+ }.distinctBy(_.signature)
802
+ .foreach(genInterfaceMethodBridge(sym.asTerm, _))
803
+
804
+ private def genInterfaceMethodBridge (sym : TermSymbol , inheritedSym : TermSymbol ): Unit =
805
+ assert(sym.name == inheritedSym.name, " Not an override" )
806
+ val owner = sym.owner.asClass
807
+ val bridgeSym = inheritedSym.copy(owner = owner, flags = sym.flags).asTerm
808
+ val bridge = tpd.DefDef (bridgeSym, {paramss =>
809
+ val params = paramss.head
810
+ tpd.Apply (tpd.This (owner).select(sym), params)
811
+ })
812
+ genDefDef(bridge)
813
+
771
814
private def genStaticForwarderForDefDef (dd : DefDef ): Unit =
772
815
val forwarderDef = makeStaticForwarder(dd)
773
816
genDefDef(forwarderDef)
0 commit comments