Skip to content

Commit 2ab6f5d

Browse files
committed
Fix bytecode generation for Single Abstract Method lambdas - reworks
1 parent bb77a29 commit 2ab6f5d

File tree

3 files changed

+9
-10
lines changed

3 files changed

+9
-10
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,8 +1459,10 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14591459

14601460
val methodName = samMethod.javaSimpleName
14611461
val samMethodType = asmMethodType(samMethod).toASMType
1462+
// scala/bug#10334: make sure that a lambda object for `T => U` has a method `apply(T)U`, not only the `(Object)Object`
1463+
// version. Using the lambda a structural type `{def apply(t: T): U}` causes a reflective lookup for this method.
14621464
val needsGenericBridge = samMethodType != instantiatedMethodType
1463-
val bridgeMethods = atPhase(erasurePhase.prev){
1465+
val bridgeMethods = atPhase(erasurePhase){
14641466
samMethod.allOverriddenSymbols.toList
14651467
}
14661468
val overriddenMethodTypes = bridgeMethods.map(b => asmMethodType(b).toASMType)

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,10 +927,10 @@ object Types {
927927
*/
928928
final def possibleSamMethods(using Context): Seq[SingleDenotation] = {
929929
record("possibleSamMethods")
930-
atPhaseNoLater(erasurePhase.prev) {
930+
atPhaseNoLater(erasurePhase) {
931931
abstractTermMembers.toList.filterConserve(m =>
932932
!m.symbol.matchingMember(defn.ObjectType).exists && !m.symbol.isSuperAccessor)
933-
}
933+
}.map(_.current)
934934
}
935935

936936
/** The set of abstract type members of this type. */

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,9 @@ object Erasure {
433433
val implReturnsUnit = implResultType.classSymbol eq defn.UnitClass
434434
// The SAM that this closure should implement.
435435
// At this point it should be already guaranteed that there's only one method to implement
436-
val Seq(unerasedSam) = lambdaType.possibleSamMethods
437-
// We're now in erasure so the alternatives will have erased types
438-
val Seq(erasedSam: MethodType) = unerasedSam.symbol.alternatives.map(_.info)
439-
440-
val samParamTypes = erasedSam.paramInfos
441-
val samResultType = erasedSam.resultType
436+
val Seq(sam: MethodType) = lambdaType.possibleSamMethods.map(_.info)
437+
val samParamTypes = sam.paramInfos
438+
val samResultType = sam.resultType
442439

443440
/** Can the implementation parameter type `tp` be auto-adapted to a different
444441
* parameter type in the SAM?
@@ -502,7 +499,7 @@ object Erasure {
502499
val bridgeType =
503500
if paramAdaptationNeeded then
504501
if resultAdaptationNeeded then
505-
erasedSam
502+
sam
506503
else
507504
implType.derivedLambdaType(paramInfos = samParamTypes)
508505
else

0 commit comments

Comments
 (0)