Skip to content

Commit b5c17f6

Browse files
committed
Specialize context functions
Apply function specialization also to context functions
1 parent 45da401 commit b5c17f6

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,8 @@ class Definitions {
15461546
new PerRun(Function2SpecializedReturnTypes.map(_.symbol))
15471547

15481548
def isSpecializableFunction(cls: ClassSymbol, paramTypes: List[Type], retType: Type)(using Context): Boolean =
1549-
paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length))
1549+
paramTypes.length <= 2
1550+
&& (cls.derivesFrom(FunctionClass(paramTypes.length)) || isContextFunctionClass(cls))
15501551
&& isSpecializableFunctionSAM(paramTypes, retType)
15511552

15521553
/** If the Single Abstract Method of a Function class has this type, is it specializable? */

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,14 @@ class SpecializeFunctions extends MiniPhase {
8080
val specializedApply = nme.apply.specializedFunction(retType, argTypes)
8181
val newSel = fun match
8282
case Select(qual, _) =>
83-
qual.select(specializedApply)
83+
val qual1 = qual.tpe.widen match
84+
case defn.FunctionOf(args, res, true, false) =>
85+
// need to cast to regular function, since specialied apply methods
86+
// are not members of context functions
87+
qual.cast(defn.FunctionOf(args, res, isContextual = false, false))
88+
case _ =>
89+
qual
90+
qual1.select(specializedApply)
8491
case _ =>
8592
(fun.tpe: @unchecked) match
8693
case TermRef(prefix: ThisType, name) =>

compiler/test/dotty/tools/dotc/transform/SpecializeFunctionsTests.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,18 @@ class SpecializeFunctionsTests extends DottyBytecodeTest {
209209
}
210210
}
211211

212+
@Test def contextLambdaNoBoxing1 = {
213+
implicit val source: String =
214+
"""|class Test {
215+
| val fn = (x: Int) ?=> x + 1
216+
| fn(using 2)
217+
|}""".stripMargin
218+
219+
checkBCode(source) { dir =>
220+
assertNoBoxing("<init>", findClass("Test", dir).methods)
221+
}
222+
}
223+
212224
@Test def lambdaNoBoxing2 = {
213225
implicit val source: String =
214226
"""|class Test {

0 commit comments

Comments
 (0)