Skip to content

Commit def880d

Browse files
committed
Use PolyFunction instead of ErasedFunction
We generalize the meaning of `PolyFunction` to mean any kind of refined lambda encoding. These refinements support any type with the following shape as a lambda type: ```scala PolyFunction { def apply[[T1, ..., Tn]]([given] [erased] x1: X1, ..., [erased] xn: Xn): R } ```
1 parent 5625107 commit def880d

File tree

15 files changed

+38
-63
lines changed

15 files changed

+38
-63
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
954954
def isStructuralTermSelectOrApply(tree: Tree)(using Context): Boolean = {
955955
def isStructuralTermSelect(tree: Select) =
956956
def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match
957-
case defn.PolyOrErasedFunctionOf(_) =>
957+
case defn.PolyFunctionOf(_) =>
958958
false
959959
case RefinedType(parent, rname, rinfo) =>
960960
rname == tree.name || hasRefinement(parent)

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ extends tpd.TreeTraverser:
197197
val mt = ContextualMethodType(paramName :: Nil)(
198198
_ => paramType :: Nil,
199199
mt => if isLast then res else expandThrowsAlias(res, mt :: encl))
200-
val fntpe = RefinedType(defn.ErasedFunctionClass.typeRef, nme.apply, mt)
200+
val fntpe = RefinedType(defn.PolyFunctionClass.typeRef, nme.apply, mt)
201201
if !encl.isEmpty && isLast then
202202
val cs = CaptureSet(encl.map(_.paramRefs.head)*)
203203
CapturingType(fntpe, cs, boxed = false)

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

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,12 +1112,12 @@ class Definitions {
11121112
def apply(args: List[Type], resultType: Type, isContextual: Boolean = false)(using Context): Type =
11131113
val mt = MethodType.companion(isContextual, false)(args, resultType)
11141114
if mt.hasErasedParams then
1115-
RefinedType(ErasedFunctionClass.typeRef, nme.apply, mt)
1115+
RefinedType(PolyFunctionClass.typeRef, nme.apply, mt)
11161116
else
11171117
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)
11181118
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean)] = {
11191119
ft.dealias match
1120-
case ErasedFunctionOf(mt) =>
1120+
case PolyFunctionOf(mt: MethodType) =>
11211121
Some(mt.paramInfos, mt.resType, mt.isContextualMethod)
11221122
case dft =>
11231123
val tsym = dft.typeSymbol
@@ -1129,38 +1129,14 @@ class Definitions {
11291129
}
11301130
}
11311131

1132-
object PolyOrErasedFunctionOf {
1133-
/** Matches a refined `PolyFunction` or `ErasedFunction` type and extracts the apply info.
1134-
*
1135-
* Pattern: `(PolyFunction | ErasedFunction) { def apply: $mt }`
1136-
*/
1137-
def unapply(ft: Type)(using Context): Option[MethodicType] = ft.dealias match
1138-
case RefinedType(parent, nme.apply, mt: MethodicType)
1139-
if parent.derivesFrom(defn.PolyFunctionClass) || parent.derivesFrom(defn.ErasedFunctionClass) =>
1140-
Some(mt)
1141-
case _ => None
1142-
}
1143-
11441132
object PolyFunctionOf {
11451133
/** Matches a refined `PolyFunction` type and extracts the apply info.
11461134
*
1147-
* Pattern: `PolyFunction { def apply: $pt }`
1135+
* Pattern: `PolyFunction { def apply: $mt }`
11481136
*/
1149-
def unapply(ft: Type)(using Context): Option[PolyType] = ft.dealias match
1150-
case RefinedType(parent, nme.apply, pt: PolyType)
1137+
def unapply(ft: Type)(using Context): Option[MethodicType] = ft.dealias match
1138+
case RefinedType(parent, nme.apply, mt: MethodicType)
11511139
if parent.derivesFrom(defn.PolyFunctionClass) =>
1152-
Some(pt)
1153-
case _ => None
1154-
}
1155-
1156-
object ErasedFunctionOf {
1157-
/** Matches a refined `ErasedFunction` type and extracts the apply info.
1158-
*
1159-
* Pattern: `ErasedFunction { def apply: $mt }`
1160-
*/
1161-
def unapply(ft: Type)(using Context): Option[MethodType] = ft.dealias match
1162-
case RefinedType(parent, nme.apply, mt: MethodType)
1163-
if parent.derivesFrom(defn.ErasedFunctionClass) =>
11641140
Some(mt)
11651141
case _ => None
11661142
}
@@ -1514,9 +1490,6 @@ class Definitions {
15141490
lazy val PolyFunctionClass = requiredClass("scala.PolyFunction")
15151491
def PolyFunctionType = PolyFunctionClass.typeRef
15161492

1517-
lazy val ErasedFunctionClass = requiredClass("scala.runtime.ErasedFunction")
1518-
def ErasedFunctionType = ErasedFunctionClass.typeRef
1519-
15201493
/** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */
15211494
def scalaClassName(cls: Symbol)(using Context): TypeName = cls.denot match
15221495
case clsd: ClassDenotation if clsd.owner eq ScalaPackageClass =>
@@ -1756,13 +1729,11 @@ class Definitions {
17561729
/** Returns whether `tp` is an instance or a refined instance of:
17571730
* - scala.FunctionN
17581731
* - scala.ContextFunctionN
1759-
* - ErasedFunction
17601732
* - PolyFunction
17611733
*/
17621734
def isFunctionType(tp: Type)(using Context): Boolean =
17631735
isFunctionNType(tp)
17641736
|| tp.derivesFrom(defn.PolyFunctionClass) // TODO check for refinement?
1765-
|| tp.derivesFrom(defn.ErasedFunctionClass) // TODO check for refinement?
17661737

17671738
private def withSpecMethods(cls: ClassSymbol, bases: List[Name], paramTypes: Set[TypeRef]) =
17681739
if !ctx.settings.Yscala2Stdlib.value then
@@ -1866,7 +1837,7 @@ class Definitions {
18661837
tp.stripTypeVar.dealias match
18671838
case tp1: TypeParamRef if ctx.typerState.constraint.contains(tp1) =>
18681839
asContextFunctionType(TypeComparer.bounds(tp1).hiBound)
1869-
case tp1 @ ErasedFunctionOf(mt) if mt.isContextualMethod =>
1840+
case tp1 @ PolyFunctionOf(mt: MethodType) if mt.isContextualMethod =>
18701841
tp1
18711842
case tp1 =>
18721843
if tp1.typeSymbol.name.isContextFunction && isFunctionNType(tp1) then tp1
@@ -1886,17 +1857,17 @@ class Definitions {
18861857
atPhase(erasurePhase)(unapply(tp))
18871858
else
18881859
asContextFunctionType(tp) match
1889-
case ErasedFunctionOf(mt) =>
1860+
case PolyFunctionOf(mt: MethodType) =>
18901861
Some((mt.paramInfos, mt.resType, mt.erasedParams))
18911862
case tp1 if tp1.exists =>
18921863
val args = tp1.functionArgInfos
1893-
val erasedParams = erasedFunctionParameters(tp1)
1864+
val erasedParams = erasedFunctionParameters(tp1) // TODO this seems to alwas be a list of false
18941865
Some((args.init, args.last, erasedParams))
18951866
case _ => None
18961867

18971868
/* Returns a list of erased booleans marking whether parameters are erased, for a function type. */
1898-
def erasedFunctionParameters(tp: Type)(using Context): List[Boolean] = tp.dealias match {
1899-
case ErasedFunctionOf(mt) => mt.erasedParams
1869+
def erasedFunctionParameters(tp: Type)(using Context): List[Boolean] = tp.dealias match { // TODO remove
1870+
case PolyFunctionOf(mt: MethodType) => mt.erasedParams
19001871
case tp if isFunctionNType(tp) => List.fill(functionArity(tp)) { false }
19011872
case _ => Nil
19021873
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ class TypeApplications(val self: Type) extends AnyVal {
509509
* Handles `ErasedFunction`s and poly functions gracefully.
510510
*/
511511
final def functionArgInfos(using Context): List[Type] = self.dealias match
512-
case defn.ErasedFunctionOf(mt) => (mt.paramInfos :+ mt.resultType)
512+
case defn.PolyFunctionOf(mt: MethodType) => (mt.paramInfos :+ mt.resultType)
513513
case _ => self.dropDependentRefinement.dealias.argInfos
514514

515515
/** Argument types where existential types in arguments are disallowed */

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
654654
else SuperType(eThis, eSuper)
655655
case ExprType(rt) =>
656656
defn.FunctionType(0)
657-
case defn.PolyOrErasedFunctionOf(mt) =>
657+
case defn.PolyFunctionOf(mt) =>
658658
eraseRefinedFunctionApply(mt)
659659
case tp: TypeVar if !tp.isInstantiated =>
660660
assert(inSigName, i"Cannot erase uninstantiated type variable $tp")
@@ -936,7 +936,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
936936
sigName(defn.FunctionOf(Nil, rt))
937937
case tp: TypeVar if !tp.isInstantiated =>
938938
tpnme.Uninstantiated
939-
case tp @ defn.PolyOrErasedFunctionOf(_) =>
939+
case tp @ defn.PolyFunctionOf(_) =>
940940
// we need this case rather than falling through to the default
941941
// because RefinedTypes <: TypeProxy and it would be caught by
942942
// the case immediately below

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1886,7 +1886,7 @@ object Types {
18861886
formals1 mapConserve (_.translateFromRepeated(toArray = isJava)),
18871887
result1, isContextual)
18881888
if mt.hasErasedParams then
1889-
RefinedType(defn.ErasedFunctionType, nme.apply, mt)
1889+
RefinedType(defn.PolyFunctionType, nme.apply, mt)
18901890
else if alwaysDependent || mt.isResultDependent then
18911891
RefinedType(nonDependentFunType, nme.apply, mt)
18921892
else nonDependentFunType

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ object Erasure {
679679
// Instead, we manually lookup the type of `apply` in the qualifier.
680680
inContext(preErasureCtx) {
681681
val qualTp = tree.qualifier.typeOpt.widen
682-
if qualTp.derivesFrom(defn.PolyFunctionClass) || qualTp.derivesFrom(defn.ErasedFunctionClass) then
682+
if qualTp.derivesFrom(defn.PolyFunctionClass) then
683683
eraseRefinedFunctionApply(qualTp.select(nme.apply).widen).classSymbol
684684
else
685685
NoSymbol

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ object TreeChecker {
449449
// PolyFunction and ErasedFunction apply methods stay structural until Erasure
450450
val isRefinedFunctionApply = (tree.name eq nme.apply) && {
451451
val qualTpe = tree.qualifier.typeOpt
452-
qualTpe.derivesFrom(defn.PolyFunctionClass) || qualTpe.derivesFrom(defn.ErasedFunctionClass)
452+
qualTpe.derivesFrom(defn.PolyFunctionClass)
453453
}
454454

455455
// Outer selects are pickled specially so don't require a symbol

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
105105
expected =:= defn.FunctionOf(actualArgs, actualRet,
106106
defn.isContextFunctionType(baseFun))
107107
val arity: Int =
108-
if fun.derivesFrom(defn.ErasedFunctionClass) then -1 // TODO support?
109-
else if defn.isFunctionNType(fun) then
108+
if defn.isFunctionNType(fun) then
110109
// TupledFunction[(...) => R, ?]
111110
fun.functionArgInfos match
112111
case funArgs :+ funRet

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13291329
case RefinedType(parent, nme.apply, mt @ MethodTpe(_, formals, restpe))
13301330
if defn.isNonRefinedFunction(parent) && formals.length == defaultArity =>
13311331
(formals, untpd.InLambdaTypeTree(isResult = true, (_, syms) => restpe.substParams(mt, syms.map(_.termRef))))
1332-
case defn.ErasedFunctionOf(mt @ MethodTpe(_, formals, restpe)) if formals.length == defaultArity =>
1332+
case defn.PolyFunctionOf(mt @ MethodTpe(_, formals, restpe)) if formals.length == defaultArity =>
13331333
(formals, untpd.InLambdaTypeTree(isResult = true, (_, syms) => restpe.substParams(mt, syms.map(_.termRef))))
13341334
case SAMType(mt @ MethodTpe(_, formals, _), samParent) =>
13351335
val restpe = mt.resultType match
@@ -1433,7 +1433,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14331433
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span)
14341434
val typeArgs = appDef.termParamss.head.map(_.tpt) :+ resTpt
14351435
val core =
1436-
if mt.hasErasedParams then TypeTree(defn.ErasedFunctionClass.typeRef)
1436+
if mt.hasErasedParams then TypeTree(defn.PolyFunctionClass.typeRef)
14371437
else
14381438
val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure)
14391439
val tycon = TypeTree(funSym.typeRef)
@@ -3220,7 +3220,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
32203220
}
32213221

32223222
val erasedParams = pt match {
3223-
case defn.ErasedFunctionOf(mt: MethodType) => mt.erasedParams
3223+
case defn.PolyFunctionOf(mt: MethodType) => mt.erasedParams
32243224
case _ => paramTypes.map(_ => false)
32253225
}
32263226

0 commit comments

Comments
 (0)