Skip to content

Commit f79a803

Browse files
authored
Backport "Replace is{Poly|Erased}FunctionType with {PolyOrErased,Poly,Erased}FunctionOf" to LTS (#19120)
Backports #18207 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 14307b2 + 72d4f8a commit f79a803

File tree

11 files changed

+65
-36
lines changed

11 files changed

+65
-36
lines changed

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
947947
def isStructuralTermSelectOrApply(tree: Tree)(using Context): Boolean = {
948948
def isStructuralTermSelect(tree: Select) =
949949
def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match
950+
case defn.PolyOrErasedFunctionOf(_) =>
951+
false
950952
case RefinedType(parent, rname, rinfo) =>
951953
rname == tree.name || hasRefinement(parent)
952954
case tp: TypeProxy =>
@@ -959,10 +961,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
959961
false
960962
!tree.symbol.exists
961963
&& tree.isTerm
962-
&& {
963-
val qualType = tree.qualifier.tpe
964-
hasRefinement(qualType) && !defn.isPolyOrErasedFunctionType(qualType)
965-
}
964+
&& hasRefinement(tree.qualifier.tpe)
966965
def loop(tree: Tree): Boolean = tree match
967966
case TypeApply(fun, _) =>
968967
loop(fun)

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

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ class Definitions {
11081108
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)
11091109
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean)] = {
11101110
ft.dealias match
1111-
case RefinedType(parent, nme.apply, mt: MethodType) if isErasedFunctionType(parent) =>
1111+
case ErasedFunctionOf(mt) =>
11121112
Some(mt.paramInfos, mt.resType, mt.isContextualMethod)
11131113
case _ =>
11141114
val tsym = ft.dealias.typeSymbol
@@ -1120,6 +1120,42 @@ class Definitions {
11201120
}
11211121
}
11221122

1123+
object PolyOrErasedFunctionOf {
1124+
/** Matches a refined `PolyFunction` or `ErasedFunction` type and extracts the apply info.
1125+
*
1126+
* Pattern: `(PolyFunction | ErasedFunction) { def apply: $mt }`
1127+
*/
1128+
def unapply(ft: Type)(using Context): Option[MethodicType] = ft.dealias match
1129+
case RefinedType(parent, nme.apply, mt: MethodicType)
1130+
if parent.derivesFrom(defn.PolyFunctionClass) || parent.derivesFrom(defn.ErasedFunctionClass) =>
1131+
Some(mt)
1132+
case _ => None
1133+
}
1134+
1135+
object PolyFunctionOf {
1136+
/** Matches a refined `PolyFunction` type and extracts the apply info.
1137+
*
1138+
* Pattern: `PolyFunction { def apply: $pt }`
1139+
*/
1140+
def unapply(ft: Type)(using Context): Option[PolyType] = ft.dealias match
1141+
case RefinedType(parent, nme.apply, pt: PolyType)
1142+
if parent.derivesFrom(defn.PolyFunctionClass) =>
1143+
Some(pt)
1144+
case _ => None
1145+
}
1146+
1147+
object ErasedFunctionOf {
1148+
/** Matches a refined `ErasedFunction` type and extracts the apply info.
1149+
*
1150+
* Pattern: `ErasedFunction { def apply: $mt }`
1151+
*/
1152+
def unapply(ft: Type)(using Context): Option[MethodType] = ft.dealias match
1153+
case RefinedType(parent, nme.apply, mt: MethodType)
1154+
if parent.derivesFrom(defn.ErasedFunctionClass) =>
1155+
Some(mt)
1156+
case _ => None
1157+
}
1158+
11231159
object PartialFunctionOf {
11241160
def apply(arg: Type, result: Type)(using Context): Type =
11251161
PartialFunctionClass.typeRef.appliedTo(arg :: result :: Nil)
@@ -1705,26 +1741,16 @@ class Definitions {
17051741
def isFunctionNType(tp: Type)(using Context): Boolean =
17061742
isNonRefinedFunction(tp.dropDependentRefinement)
17071743

1708-
/** Does `tp` derive from `PolyFunction` or `ErasedFunction`? */
1709-
def isPolyOrErasedFunctionType(tp: Type)(using Context): Boolean =
1710-
isPolyFunctionType(tp) || isErasedFunctionType(tp)
1711-
1712-
/** Does `tp` derive from `PolyFunction`? */
1713-
def isPolyFunctionType(tp: Type)(using Context): Boolean =
1714-
tp.derivesFrom(defn.PolyFunctionClass)
1715-
1716-
/** Does `tp` derive from `ErasedFunction`? */
1717-
def isErasedFunctionType(tp: Type)(using Context): Boolean =
1718-
tp.derivesFrom(defn.ErasedFunctionClass)
1719-
17201744
/** Returns whether `tp` is an instance or a refined instance of:
17211745
* - scala.FunctionN
17221746
* - scala.ContextFunctionN
17231747
* - ErasedFunction
17241748
* - PolyFunction
17251749
*/
17261750
def isFunctionType(tp: Type)(using Context): Boolean =
1727-
isFunctionNType(tp) || isPolyOrErasedFunctionType(tp)
1751+
isFunctionNType(tp)
1752+
|| tp.derivesFrom(defn.PolyFunctionClass) // TODO check for refinement?
1753+
|| tp.derivesFrom(defn.ErasedFunctionClass) // TODO check for refinement?
17281754

17291755
private def withSpecMethods(cls: ClassSymbol, bases: List[Name], paramTypes: Set[TypeRef]) =
17301756
for base <- bases; tp <- paramTypes do
@@ -1825,7 +1851,7 @@ class Definitions {
18251851
tp.stripTypeVar.dealias match
18261852
case tp1: TypeParamRef if ctx.typerState.constraint.contains(tp1) =>
18271853
asContextFunctionType(TypeComparer.bounds(tp1).hiBound)
1828-
case tp1 @ RefinedType(parent, nme.apply, mt: MethodType) if isErasedFunctionType(parent) && mt.isContextualMethod =>
1854+
case tp1 @ ErasedFunctionOf(mt) if mt.isContextualMethod =>
18291855
tp1
18301856
case tp1 =>
18311857
if tp1.typeSymbol.name.isContextFunction && isFunctionNType(tp1) then tp1
@@ -1845,7 +1871,7 @@ class Definitions {
18451871
atPhase(erasurePhase)(unapply(tp))
18461872
else
18471873
asContextFunctionType(tp) match
1848-
case RefinedType(parent, nme.apply, mt: MethodType) if isErasedFunctionType(parent) =>
1874+
case ErasedFunctionOf(mt) =>
18491875
Some((mt.paramInfos, mt.resType, mt.erasedParams))
18501876
case tp1 if tp1.exists =>
18511877
val args = tp1.functionArgInfos
@@ -1855,7 +1881,7 @@ class Definitions {
18551881

18561882
/* Returns a list of erased booleans marking whether parameters are erased, for a function type. */
18571883
def erasedFunctionParameters(tp: Type)(using Context): List[Boolean] = tp.dealias match {
1858-
case RefinedType(parent, nme.apply, mt: MethodType) => mt.erasedParams
1884+
case ErasedFunctionOf(mt) => mt.erasedParams
18591885
case tp if isFunctionNType(tp) => List.fill(functionArity(tp)) { false }
18601886
case _ => Nil
18611887
}

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 RefinedType(parent, nme.apply, mt: MethodType) if defn.isPolyOrErasedFunctionType(parent) => (mt.paramInfos :+ mt.resultType)
512+
case defn.ErasedFunctionOf(mt) => (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/TypeComparer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
659659
isSubType(info1, info2)
660660

661661
if defn.isFunctionType(tp2) then
662-
if defn.isPolyFunctionType(tp2) then
662+
if tp2.derivesFrom(defn.PolyFunctionClass) then
663663
// TODO should we handle ErasedFunction is this same way?
664664
tp1.member(nme.apply).info match
665665
case info1: PolyType =>

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -654,8 +654,8 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
654654
else SuperType(eThis, eSuper)
655655
case ExprType(rt) =>
656656
defn.FunctionType(0)
657-
case RefinedType(parent, nme.apply, refinedInfo) if defn.isPolyOrErasedFunctionType(parent) =>
658-
eraseRefinedFunctionApply(refinedInfo)
657+
case defn.PolyOrErasedFunctionOf(mt) =>
658+
eraseRefinedFunctionApply(mt)
659659
case tp: TypeVar if !tp.isInstantiated =>
660660
assert(inSigName, i"Cannot erase uninstantiated type variable $tp")
661661
WildcardType
@@ -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 @ RefinedType(parent, nme.apply, _) if defn.isPolyOrErasedFunctionType(parent) =>
939+
case tp @ defn.PolyOrErasedFunctionOf(_) =>
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 & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,9 +1737,7 @@ object Types {
17371737
if !tf1.exists then tf2
17381738
else if !tf2.exists then tf1
17391739
else NoType
1740-
case t if defn.isNonRefinedFunction(t) =>
1741-
t
1742-
case t if defn.isErasedFunctionType(t) =>
1740+
case t if defn.isFunctionType(t) =>
17431741
t
17441742
case t @ SAMType(_, _) =>
17451743
t

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

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

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,11 @@ object TreeChecker {
446446
val tpe = tree.typeOpt
447447

448448
// PolyFunction and ErasedFunction apply methods stay structural until Erasure
449-
val isRefinedFunctionApply = (tree.name eq nme.apply) && defn.isPolyOrErasedFunctionType(tree.qualifier.typeOpt)
449+
val isRefinedFunctionApply = (tree.name eq nme.apply) && {
450+
val qualTpe = tree.qualifier.typeOpt
451+
qualTpe.derivesFrom(defn.PolyFunctionClass) || qualTpe.derivesFrom(defn.ErasedFunctionClass)
452+
}
453+
450454
// Outer selects are pickled specially so don't require a symbol
451455
val isOuterSelect = tree.name.is(OuterSelectName)
452456
val isPrimitiveArrayOp = ctx.erasedTypes && nme.isPrimitiveName(tree.name)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +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 defn.isErasedFunctionType(fun) then -1 // TODO support?
108+
if fun.derivesFrom(defn.ErasedFunctionClass) then -1 // TODO support?
109109
else if defn.isFunctionNType(fun) then
110110
// TupledFunction[(...) => R, ?]
111111
fun.functionArgInfos match

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13221322

13231323
(pt1.argInfos.init, typeTree(interpolateWildcards(pt1.argInfos.last.hiBound)))
13241324
case RefinedType(parent, nme.apply, mt @ MethodTpe(_, formals, restpe))
1325-
if (defn.isNonRefinedFunction(parent) || defn.isErasedFunctionType(parent)) && formals.length == defaultArity =>
1325+
if defn.isNonRefinedFunction(parent) && formals.length == defaultArity =>
1326+
(formals, untpd.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef))))
1327+
case defn.ErasedFunctionOf(mt @ MethodTpe(_, formals, restpe)) if formals.length == defaultArity =>
13261328
(formals, untpd.DependentTypeTree(syms => restpe.substParams(mt, syms.map(_.termRef))))
13271329
case SAMType(mt @ MethodTpe(_, formals, restpe), _) =>
13281330
(formals,
@@ -3162,8 +3164,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31623164
else formals.map(untpd.TypeTree)
31633165
}
31643166

3165-
val erasedParams = pt.dealias match {
3166-
case RefinedType(parent, nme.apply, mt: MethodType) => mt.erasedParams
3167+
val erasedParams = pt match {
3168+
case defn.ErasedFunctionOf(mt: MethodType) => mt.erasedParams
31673169
case _ => paramTypes.map(_ => false)
31683170
}
31693171

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1779,7 +1779,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
17791779
def isContextFunctionType: Boolean =
17801780
dotc.core.Symbols.defn.isContextFunctionType(self)
17811781
def isErasedFunctionType: Boolean =
1782-
dotc.core.Symbols.defn.isErasedFunctionType(self)
1782+
self.derivesFrom(dotc.core.Symbols.defn.ErasedFunctionClass)
17831783
def isDependentFunctionType: Boolean =
17841784
val tpNoRefinement = self.dropDependentRefinement
17851785
tpNoRefinement != self

0 commit comments

Comments
 (0)