Skip to content

Commit 829865b

Browse files
committed
Refactor platform SAM check to ensure compatible bridge for LambdaMetaFactory
1 parent 35a8c53 commit 829865b

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

compiler/src/dotty/tools/dotc/config/JavaPlatform.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,18 @@ class JavaPlatform extends Platform {
4545

4646
def rootLoader(root: TermSymbol)(using Context): SymbolLoader = new SymbolLoaders.PackageLoader(root, classPath)
4747

48-
private def samMethodHasCompatibleErasedSignature(cls: ClassSymbol)(using Context): Boolean = atPhase(erasurePhase):
49-
cls.typeRef.possibleSamMethods.toList match
50-
case samDenot :: Nil =>
51-
val samMethod = samDenot.symbol
52-
val samErasedResult = TypeErasure.erasure(samMethod.info.resultType)
53-
samMethod.allOverriddenSymbols.forall { overridden =>
54-
val overriddenErasedResult = TypeErasure.erasure(overridden.info.resultType)
55-
samErasedResult =:= overriddenErasedResult
56-
}
57-
case _ => false // No SAM method or multiple - handled elsewhere
48+
private def samMethodHasCompatibleBridge(cls: ClassSymbol)(using Context): Boolean =
49+
cls.typeRef.possibleSamMethods match
50+
case Seq(samMeth) =>
51+
val samResultType = samMeth.info.resultType
52+
if samResultType.isRef(defn.UnitClass) then
53+
// If the result type of the SAM method is Unit, but the result type of the overridden
54+
// methods is not Unit, the bridge will return Object, which is not compatible with Void
55+
// required by LambdaMetaFactory.
56+
// See issue #24573 for details.
57+
samMeth.symbol.allOverriddenSymbols.forall(_.info.resultType.isRef(defn.UnitClass))
58+
else true
59+
case _ => false
5860

5961
/** Is the SAMType `cls` also a SAM under the rules of the JVM? */
6062
def isSam(cls: ClassSymbol)(using Context): Boolean =
@@ -64,10 +66,8 @@ class JavaPlatform extends Platform {
6466
!ExplicitOuter.needsOuterIfReferenced(cls) &&
6567
// Superaccessors already show up as abstract methods here, so no test necessary
6668
cls.typeRef.fields.isEmpty &&
67-
// Check that SAM method's erased signature is compatible with all overridden methods
68-
// For example, `void apply(Object)` is not compatible with `Object apply(Object)`
69-
// even though both can have the same type signature `def apply(o: Object): Unit` before erasure.
70-
samMethodHasCompatibleErasedSignature(cls)
69+
// Check if SAM method will have a compatible bridge for LambdaMetaFactory
70+
samMethodHasCompatibleBridge(cls)
7171

7272
/** We could get away with excluding BoxedBooleanClass for the
7373
* purpose of equality testing since it need not compare equal

0 commit comments

Comments
 (0)