-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #24573: Add stricter checks for platform SAM compatibility #24624
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
noti0na1
wants to merge
1
commit into
scala:main
Choose a base branch
from
dotty-staging:fix-24573
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+325
−38
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sjrd
reviewed
Dec 2, 2025
Member
Author
|
|
Copilot finished reviewing on behalf of
noti0na1
December 4, 2025 21:21
bracevac
approved these changes
Dec 5, 2025
| * @param cls The SAM class to check | ||
| * @return true if LMF can handle the required adaptation | ||
| */ | ||
| def samNotNeededExpansion(cls: ClassSymbol)(using Context): Boolean = cls.typeRef.possibleSamMethods match |
Contributor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested change
| def samNotNeededExpansion(cls: ClassSymbol)(using Context): Boolean = cls.typeRef.possibleSamMethods match | |
| def samExpansionNotNeeded(cls: ClassSymbol)(using Context): Boolean = cls.typeRef.possibleSamMethods match |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
backport:nominated
If we agree to backport this PR, replace this tag with "backport:accepted", otherwise delete it.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes issue #24573 by adding stricter checks for platform SAM compatibility.
The regression issue starts from version 3.8.0 where
Function1and related traits gained theNoInitsflag (I guess due to the way we read from jvm bytecode or from tasty?).This changes how the compiler determines whether a SAM type qualifies as a platform SAM. When a trait is classified as a Java platform SAM, the compiler uses
invokedynamicwithLambdaMetaFactory(LMF) to create the lambda at runtime, rather than expanding it into an anonymous class at compile time. This is more efficient, but LMF has limitations on what type adaptations it can perform automatically.It turns out the logic regarding SAM traits extending other traits has problems from the beginning, and even in Scala 2. The code from the issue works before 3.8 is totally by accident (because we always expand the SAM trait extending
FunctionN).We can reproduce the runtime exception using a custom function class (in Scala 2, and Scala 3.0~8):
From the view of Scala,
SFis a valid SAM, because it has one abstract functiondef apply(t: T): Unit. However, after erasure, theapplyofF1becomesObject apply(Object), and the apply ofSFbecomesvoid apply(Object), which are two different abstract functions; hence,SFis not qualifies as a function interface on JVM. This is not only forUnittype, any primitive number type can cause the similar problem.Therefore, we have to expand the rhs of
val sf: SF[String] = i => println(i)into an anonymous class and implement all the bridge functions.This PR strengthen the SAM check on Java platform by adding a function called
samNotNeededExpansionto check if the SAM method's erased signature is compatible with all overridden methods. It mirrors the logic inErasure.Boxing.adaptClosureto determine what LMF can and cannot auto-adapt.