Skip to content

Commit 177896a

Browse files
committed
Specialize byname functions
I tried to extend specialization to all context functions, not just ones of 0 arity. But that runs into problems for dependent context functions, since the necessary casts get complicated. Since context functions over primitive types are an anti-pattern anyway I don't think we need to optimize this case, after all.
1 parent 6c43bed commit 177896a

File tree

2 files changed

+23
-19
lines changed

2 files changed

+23
-19
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -1558,7 +1558,8 @@ class Definitions {
15581558
new PerRun(Function2SpecializedReturnTypes.map(_.symbol))
15591559

15601560
def isSpecializableFunction(cls: ClassSymbol, paramTypes: List[Type], retType: Type)(using Context): Boolean =
1561-
paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length))
1561+
paramTypes.length <= 2
1562+
&& (cls.derivesFrom(FunctionClass(paramTypes.length)) || isByNameFunctionClass(cls))
15621563
&& isSpecializableFunctionSAM(paramTypes, retType)
15631564

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

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

+21-18
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,27 @@ class SpecializeFunctions extends MiniPhase {
7676
argTypes,
7777
retType
7878
)
79-
80-
if (!isSpecializable || argTypes.exists(_.isInstanceOf[ExprType])) return tree
81-
82-
val specializedApply = nme.apply.specializedFunction(retType, argTypes)
83-
val newSel = fun match {
84-
case Select(qual, _) =>
85-
qual.select(specializedApply)
86-
case _ =>
87-
(fun.tpe: @unchecked) match {
88-
case TermRef(prefix: ThisType, name) =>
89-
tpd.This(prefix.cls).select(specializedApply)
90-
case TermRef(prefix: NamedType, name) =>
91-
tpd.ref(prefix).select(specializedApply)
92-
}
93-
}
94-
95-
newSel.appliedToTermArgs(args)
96-
79+
if isSpecializable then
80+
val specializedApply = nme.apply.specializedFunction(retType, argTypes)
81+
val newSel = fun match
82+
case Select(qual, _) =>
83+
val qual1 = qual.tpe.widen match
84+
case defn.ByNameFunction(res) =>
85+
// Need to cast to regular function, since specialied apply methods
86+
// are not members of ContextFunction0. The cast will be eliminated in
87+
// erasure.
88+
qual.cast(defn.FunctionOf(Nil, res))
89+
case _ =>
90+
qual
91+
qual1.select(specializedApply)
92+
case _ =>
93+
(fun.tpe: @unchecked) match
94+
case TermRef(prefix: ThisType, name) =>
95+
tpd.This(prefix.cls).select(specializedApply)
96+
case TermRef(prefix: NamedType, name) =>
97+
tpd.ref(prefix).select(specializedApply)
98+
newSel.appliedToTermArgs(args)
99+
else tree
97100
case _ => tree
98101
}
99102

0 commit comments

Comments
 (0)