Skip to content

Commit 652e6c2

Browse files
authored
Backport "Refactor function type logic" to LTS (#19109)
Backports #18193 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 76e39ce + 187b4e4 commit 652e6c2

19 files changed

+85
-88
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
961961
&& tree.isTerm
962962
&& {
963963
val qualType = tree.qualifier.tpe
964-
hasRefinement(qualType) && !defn.isRefinedFunctionType(qualType)
964+
hasRefinement(qualType) && !defn.isPolyOrErasedFunctionType(qualType)
965965
}
966966
def loop(tree: Tree): Boolean = tree match
967967
case TypeApply(fun, _) =>

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class CheckCaptures extends Recheck, SymTransformer:
187187
capt.println(i"solving $t")
188188
refs.solve()
189189
traverse(parent)
190-
case t @ RefinedType(_, nme.apply, rinfo) if defn.isFunctionOrPolyType(t) =>
190+
case t @ RefinedType(_, nme.apply, rinfo) if defn.isFunctionType(t) =>
191191
traverse(rinfo)
192192
case tp: TypeVar =>
193193
case tp: TypeRef =>
@@ -638,7 +638,7 @@ class CheckCaptures extends Recheck, SymTransformer:
638638
case expected @ CapturingType(eparent, refs) =>
639639
CapturingType(recur(eparent), refs, boxed = expected.isBoxed)
640640
case expected @ defn.FunctionOf(args, resultType, isContextual)
641-
if defn.isNonRefinedFunction(expected) && defn.isFunctionType(actual) && !defn.isNonRefinedFunction(actual) =>
641+
if defn.isNonRefinedFunction(expected) && defn.isFunctionNType(actual) && !defn.isNonRefinedFunction(actual) =>
642642
val expected1 = toDepFun(args, resultType, isContextual)
643643
expected1
644644
case _ =>
@@ -707,7 +707,7 @@ class CheckCaptures extends Recheck, SymTransformer:
707707
val (eargs, eres) = expected.dealias.stripCapturing match
708708
case defn.FunctionOf(eargs, eres, _) => (eargs, eres)
709709
case expected: MethodType => (expected.paramInfos, expected.resType)
710-
case expected @ RefinedType(_, _, rinfo: MethodType) if defn.isFunctionType(expected) => (rinfo.paramInfos, rinfo.resType)
710+
case expected @ RefinedType(_, _, rinfo: MethodType) if defn.isFunctionNType(expected) => (rinfo.paramInfos, rinfo.resType)
711711
case _ => (aargs.map(_ => WildcardType), WildcardType)
712712
val aargs1 = aargs.zipWithConserve(eargs) { (aarg, earg) => adapt(aarg, earg, !covariant) }
713713
val ares1 = adapt(ares, eres, covariant)
@@ -769,7 +769,7 @@ class CheckCaptures extends Recheck, SymTransformer:
769769
case actual @ AppliedType(tycon, args) if defn.isNonRefinedFunction(actual) =>
770770
adaptFun(actual, args.init, args.last, expected, covariant, insertBox,
771771
(aargs1, ares1) => actual.derivedAppliedType(tycon, aargs1 :+ ares1))
772-
case actual @ RefinedType(_, _, rinfo: MethodType) if defn.isFunctionOrPolyType(actual) =>
772+
case actual @ RefinedType(_, _, rinfo: MethodType) if defn.isFunctionType(actual) =>
773773
// TODO Find a way to combine handling of generic and dependent function types (here and elsewhere)
774774
adaptFun(actual, rinfo.paramInfos, rinfo.resType, expected, covariant, insertBox,
775775
(aargs1, ares1) =>
@@ -779,7 +779,7 @@ class CheckCaptures extends Recheck, SymTransformer:
779779
adaptFun(actual, actual.paramInfos, actual.resType, expected, covariant, insertBox,
780780
(aargs1, ares1) =>
781781
actual.derivedLambdaType(paramInfos = aargs1, resType = ares1))
782-
case actual @ RefinedType(p, nme, rinfo: PolyType) if defn.isFunctionOrPolyType(actual) =>
782+
case actual @ RefinedType(p, nme, rinfo: PolyType) if defn.isFunctionType(actual) =>
783783
adaptTypeFun(actual, rinfo.resType, expected, covariant, insertBox,
784784
ares1 =>
785785
val rinfo1 = rinfo.derivedLambdaType(rinfo.paramNames, rinfo.paramInfos, ares1)
@@ -996,7 +996,7 @@ class CheckCaptures extends Recheck, SymTransformer:
996996
case CapturingType(parent, refs) =>
997997
healCaptureSet(refs)
998998
traverse(parent)
999-
case tp @ RefinedType(parent, rname, rinfo: MethodType) if defn.isFunctionOrPolyType(tp) =>
999+
case tp @ RefinedType(parent, rname, rinfo: MethodType) if defn.isFunctionType(tp) =>
10001000
traverse(rinfo)
10011001
case tp: TermLambda =>
10021002
val saved = allowed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ extends tpd.TreeTraverser:
5454
val boxedRes = recur(res)
5555
if boxedRes eq res then tp
5656
else tp1.derivedAppliedType(tycon, args.init :+ boxedRes)
57-
case tp1 @ RefinedType(_, _, rinfo: MethodType) if defn.isFunctionOrPolyType(tp1) =>
57+
case tp1 @ RefinedType(_, _, rinfo: MethodType) if defn.isFunctionType(tp1) =>
5858
val boxedRinfo = recur(rinfo)
5959
if boxedRinfo eq rinfo then tp
6060
else boxedRinfo.toFunctionType(isJava = false, alwaysDependent = true)
@@ -231,7 +231,7 @@ extends tpd.TreeTraverser:
231231
tp.derivedAppliedType(tycon1, args1 :+ res1)
232232
else
233233
tp.derivedAppliedType(tycon1, args.mapConserve(arg => this(arg)))
234-
case tp @ RefinedType(core, rname, rinfo: MethodType) if defn.isFunctionOrPolyType(tp) =>
234+
case tp @ RefinedType(core, rname, rinfo: MethodType) if defn.isFunctionType(tp) =>
235235
val rinfo1 = apply(rinfo)
236236
if rinfo1 ne rinfo then rinfo1.toFunctionType(isJava = false, alwaysDependent = true)
237237
else tp
@@ -329,7 +329,7 @@ extends tpd.TreeTraverser:
329329
args.last, CaptureSet.empty, currentCs ++ outerCs)
330330
tp.derivedAppliedType(tycon1, args1 :+ resType1)
331331
tp1.capturing(outerCs)
332-
case tp @ RefinedType(parent, nme.apply, rinfo: MethodType) if defn.isFunctionOrPolyType(tp) =>
332+
case tp @ RefinedType(parent, nme.apply, rinfo: MethodType) if defn.isFunctionType(tp) =>
333333
propagateDepFunctionResult(mapOver(tp), currentCs ++ outerCs)
334334
.capturing(outerCs)
335335
case _ =>

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,6 +1466,7 @@ class Definitions {
14661466
def PolyFunctionType = PolyFunctionClass.typeRef
14671467

14681468
lazy val ErasedFunctionClass = requiredClass("scala.runtime.ErasedFunction")
1469+
def ErasedFunctionType = ErasedFunctionClass.typeRef
14691470

14701471
/** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */
14711472
def scalaClassName(cls: Symbol)(using Context): TypeName = cls.denot match
@@ -1700,21 +1701,29 @@ class Definitions {
17001701
* - scala.FunctionN
17011702
* - scala.ContextFunctionN
17021703
*/
1703-
def isFunctionType(tp: Type)(using Context): Boolean =
1704+
def isFunctionNType(tp: Type)(using Context): Boolean =
17041705
isNonRefinedFunction(tp.dropDependentRefinement)
17051706

1706-
/** Is `tp` a specialized, refined function type? Either an `ErasedFunction` or a `PolyFunction`. */
1707-
def isRefinedFunctionType(tp: Type)(using Context): Boolean =
1708-
tp.derivesFrom(defn.PolyFunctionClass) || isErasedFunctionType(tp)
1707+
/** Does `tp` derive from `PolyFunction` or `ErasedFunction`? */
1708+
def isPolyOrErasedFunctionType(tp: Type)(using Context): Boolean =
1709+
isPolyFunctionType(tp) || isErasedFunctionType(tp)
1710+
1711+
/** Does `tp` derive from `PolyFunction`? */
1712+
def isPolyFunctionType(tp: Type)(using Context): Boolean =
1713+
tp.derivesFrom(defn.PolyFunctionClass)
1714+
1715+
/** Does `tp` derive from `ErasedFunction`? */
1716+
def isErasedFunctionType(tp: Type)(using Context): Boolean =
1717+
tp.derivesFrom(defn.ErasedFunctionClass)
17091718

17101719
/** Returns whether `tp` is an instance or a refined instance of:
17111720
* - scala.FunctionN
17121721
* - scala.ContextFunctionN
17131722
* - ErasedFunction
17141723
* - PolyFunction
17151724
*/
1716-
def isFunctionOrPolyType(tp: Type)(using Context): Boolean =
1717-
isFunctionType(tp) || isRefinedFunctionType(tp)
1725+
def isFunctionType(tp: Type)(using Context): Boolean =
1726+
isFunctionNType(tp) || isPolyOrErasedFunctionType(tp)
17181727

17191728
private def withSpecMethods(cls: ClassSymbol, bases: List[Name], paramTypes: Set[TypeRef]) =
17201729
for base <- bases; tp <- paramTypes do
@@ -1818,7 +1827,7 @@ class Definitions {
18181827
case tp1 @ RefinedType(parent, nme.apply, mt: MethodType) if isErasedFunctionType(parent) && mt.isContextualMethod =>
18191828
tp1
18201829
case tp1 =>
1821-
if tp1.typeSymbol.name.isContextFunction && isFunctionType(tp1) then tp1
1830+
if tp1.typeSymbol.name.isContextFunction && isFunctionNType(tp1) then tp1
18221831
else NoType
18231832

18241833
/** Is `tp` an context function type? */
@@ -1846,13 +1855,10 @@ class Definitions {
18461855
/* Returns a list of erased booleans marking whether parameters are erased, for a function type. */
18471856
def erasedFunctionParameters(tp: Type)(using Context): List[Boolean] = tp.dealias match {
18481857
case RefinedType(parent, nme.apply, mt: MethodType) => mt.erasedParams
1849-
case tp if isFunctionType(tp) => List.fill(functionArity(tp)) { false }
1858+
case tp if isFunctionNType(tp) => List.fill(functionArity(tp)) { false }
18501859
case _ => Nil
18511860
}
18521861

1853-
def isErasedFunctionType(tp: Type)(using Context): Boolean =
1854-
tp.derivesFrom(defn.ErasedFunctionClass)
1855-
18561862
/** A whitelist of Scala-2 classes that are known to be pure */
18571863
def isAssuredNoInits(sym: Symbol): Boolean =
18581864
(sym `eq` SomeClass) || isTupleClass(sym)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,8 +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.isErasedFunctionType(parent) => (mt.paramInfos :+ mt.resultType)
513-
case RefinedType(parent, nme.apply, mt: MethodType) if parent.typeSymbol eq defn.PolyFunctionClass => (mt.paramInfos :+ mt.resultType)
512+
case RefinedType(parent, nme.apply, mt: MethodType) if defn.isPolyOrErasedFunctionType(parent) => (mt.paramInfos :+ mt.resultType)
514513
case _ => self.dropDependentRefinement.dealias.argInfos
515514

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

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -659,15 +659,17 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
659659
isSubType(info1, info2)
660660

661661
if defn.isFunctionType(tp2) then
662-
tp1w.widenDealias match
663-
case tp1: RefinedType =>
664-
return isSubInfo(tp1.refinedInfo, tp2.refinedInfo)
665-
case _ =>
666-
else if tp2.parent.typeSymbol == defn.PolyFunctionClass then
667-
tp1.member(nme.apply).info match
668-
case info1: PolyType =>
669-
return isSubInfo(info1, tp2.refinedInfo)
670-
case _ =>
662+
if defn.isPolyFunctionType(tp2) then
663+
// TODO should we handle ErasedFunction is this same way?
664+
tp1.member(nme.apply).info match
665+
case info1: PolyType =>
666+
return isSubInfo(info1, tp2.refinedInfo)
667+
case _ =>
668+
else
669+
tp1w.widenDealias match
670+
case tp1: RefinedType =>
671+
return isSubInfo(tp1.refinedInfo, tp2.refinedInfo)
672+
case _ =>
671673

672674
val skipped2 = skipMatching(tp1w, tp2)
673675
if (skipped2 eq tp2) || !Config.fastPathForRefinedSubtype then

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

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -560,21 +560,16 @@ object TypeErasure {
560560
case _ => false
561561
}
562562

563-
/** The erasure of `PolyFunction { def apply: $applyInfo }` */
564-
def erasePolyFunctionApply(applyInfo: Type)(using Context): Type =
565-
assert(applyInfo.isInstanceOf[PolyType])
566-
val res = applyInfo.resultType
567-
val paramss = res.paramNamess
568-
assert(paramss.length == 1)
569-
erasure(defn.FunctionType(paramss.head.length,
570-
isContextual = res.isImplicitMethod))
571-
572-
def eraseErasedFunctionApply(erasedFn: MethodType)(using Context): Type =
573-
val fnType = defn.FunctionType(
574-
n = erasedFn.erasedParams.count(_ == false),
575-
isContextual = erasedFn.isContextualMethod,
576-
)
577-
erasure(fnType)
563+
/** The erasure of `(PolyFunction | ErasedFunction) { def apply: $applyInfo }` */
564+
def eraseRefinedFunctionApply(applyInfo: Type)(using Context): Type =
565+
def functionType(info: Type): Type = info match {
566+
case info: PolyType =>
567+
functionType(info.resultType)
568+
case info: MethodType =>
569+
assert(!info.resultType.isInstanceOf[MethodicType])
570+
defn.FunctionType(n = info.erasedParams.count(_ == false))
571+
}
572+
erasure(functionType(applyInfo))
578573
}
579574

580575
import TypeErasure._
@@ -592,7 +587,7 @@ import TypeErasure._
592587
*/
593588
class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConstructor: Boolean, isSymbol: Boolean, inSigName: Boolean) {
594589

595-
/** The erasure |T| of a type T.
590+
/** The erasure |T| of a type T.
596591
*
597592
* If computing the erasure of T requires erasing a WildcardType or an
598593
* uninstantiated type variable, then an exception signaling an internal
@@ -659,10 +654,8 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
659654
else SuperType(eThis, eSuper)
660655
case ExprType(rt) =>
661656
defn.FunctionType(0)
662-
case RefinedType(parent, nme.apply, refinedInfo) if parent.typeSymbol eq defn.PolyFunctionClass =>
663-
erasePolyFunctionApply(refinedInfo)
664-
case RefinedType(parent, nme.apply, refinedInfo: MethodType) if defn.isErasedFunctionType(parent) =>
665-
eraseErasedFunctionApply(refinedInfo)
657+
case RefinedType(parent, nme.apply, refinedInfo) if defn.isPolyOrErasedFunctionType(parent) =>
658+
eraseRefinedFunctionApply(refinedInfo)
666659
case tp: TypeVar if !tp.isInstantiated =>
667660
assert(inSigName, i"Cannot erase uninstantiated type variable $tp")
668661
WildcardType
@@ -943,13 +936,11 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
943936
sigName(defn.FunctionOf(Nil, rt))
944937
case tp: TypeVar if !tp.isInstantiated =>
945938
tpnme.Uninstantiated
946-
case tp @ RefinedType(parent, nme.apply, _) if parent.typeSymbol eq defn.PolyFunctionClass =>
939+
case tp @ RefinedType(parent, nme.apply, _) if defn.isPolyOrErasedFunctionType(parent) =>
947940
// we need this case rather than falling through to the default
948941
// because RefinedTypes <: TypeProxy and it would be caught by
949942
// the case immediately below
950943
sigName(this(tp))
951-
case tp @ RefinedType(parent, nme.apply, refinedInfo) if defn.isErasedFunctionType(parent) =>
952-
sigName(this(tp))
953944
case tp: TypeProxy =>
954945
sigName(tp.underlying)
955946
case tp: WildcardType =>

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,7 +1865,7 @@ object Types {
18651865
* @param alwaysDependent if true, always create a dependent function type.
18661866
*/
18671867
def toFunctionType(isJava: Boolean, dropLast: Int = 0, alwaysDependent: Boolean = false)(using Context): Type = this match {
1868-
case mt: MethodType if !mt.isParamDependent =>
1868+
case mt: MethodType if !mt.isParamDependent && !mt.hasErasedParams =>
18691869
val formals1 = if (dropLast == 0) mt.paramInfos else mt.paramInfos dropRight dropLast
18701870
val isContextual = mt.isContextualMethod && !ctx.erasedTypes
18711871
val result1 = mt.nonDependentResultApprox match {
@@ -1878,6 +1878,9 @@ object Types {
18781878
if alwaysDependent || mt.isResultDependent then
18791879
RefinedType(funType, nme.apply, mt)
18801880
else funType
1881+
case mt: MethodType if !mt.isParamDependent =>
1882+
assert(mt.hasErasedParams)
1883+
RefinedType(defn.ErasedFunctionType, nme.apply, mt)
18811884
}
18821885

18831886
/** The signature of this type. This is by default NotAMethod,
@@ -2760,7 +2763,7 @@ object Types {
27602763
final def withPrefix(prefix: Type)(using Context): Type = {
27612764
def reload(): NamedType = {
27622765
val sym =
2763-
if lastSymbol.nn.isValidInCurrentRun then lastSymbol.nn
2766+
if lastSymbol.nn.isValidInCurrentRun then lastSymbol.nn
27642767
else computeSymbol
27652768
val allowPrivate = !sym.exists || sym.is(Private)
27662769
var d = memberDenot(prefix, name, allowPrivate)
@@ -4054,9 +4057,9 @@ object Types {
40544057
def addInto(tp: Type): Type = tp match
40554058
case tp @ AppliedType(tycon, args) if tycon.typeSymbol == defn.RepeatedParamClass =>
40564059
tp.derivedAppliedType(tycon, addInto(args.head) :: Nil)
4057-
case tp @ AppliedType(tycon, args) if defn.isFunctionType(tp) =>
4060+
case tp @ AppliedType(tycon, args) if defn.isFunctionNType(tp) =>
40584061
wrapConvertible(tp.derivedAppliedType(tycon, args.init :+ addInto(args.last)))
4059-
case tp @ RefinedType(parent, rname, rinfo) if defn.isFunctionOrPolyType(tp) =>
4062+
case tp @ RefinedType(parent, rname, rinfo) if defn.isFunctionType(tp) =>
40604063
wrapConvertible(tp.derivedRefinedType(parent, rname, addInto(rinfo)))
40614064
case tp: MethodOrPoly =>
40624065
tp.derivedLambdaType(resType = addInto(tp.resType))

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
266266
if !printDebug && appliedText(tp.asInstanceOf[HKLambda].resType).isEmpty =>
267267
// don't eta contract if the application would be printed specially
268268
toText(tycon)
269-
case tp: RefinedType if defn.isFunctionOrPolyType(tp) && !printDebug =>
269+
case tp: RefinedType if defn.isFunctionType(tp) && !printDebug =>
270270
toTextMethodAsFunction(tp.refinedInfo,
271271
isPure = Feature.pureFunsEnabled && !tp.typeSymbol.name.isImpureFunction)
272272
case tp: TypeRef =>
@@ -763,7 +763,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
763763
override protected def toTextCapturing(tp: Type, refsText: Text, boxText: Text): Text = tp match
764764
case tp: AppliedType if defn.isFunctionSymbol(tp.typeSymbol) && !printDebug =>
765765
boxText ~ toTextFunction(tp, refsText)
766-
case tp: RefinedType if defn.isFunctionOrPolyType(tp) && !printDebug =>
766+
case tp: RefinedType if defn.isFunctionType(tp) && !printDebug =>
767767
boxText ~ toTextMethodAsFunction(tp.refinedInfo, isPure = !tp.typeSymbol.name.isImpureFunction, refsText)
768768
case _ =>
769769
super.toTextCapturing(tp, refsText, boxText)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ object BetaReduce:
9090
recur(expr, argss)
9191
case _ => None
9292
tree match
93-
case Apply(Select(fn, nme.apply), args) if defn.isFunctionType(fn.tpe) =>
93+
case Apply(Select(fn, nme.apply), args) if defn.isFunctionNType(fn.tpe) =>
9494
recur(fn, List(args)) match
9595
case Some(reduced) =>
9696
seq(bindingsBuf.result(), reduced).withSpan(tree.span)

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -677,10 +677,8 @@ 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 qualTp.derivesFrom(defn.PolyFunctionClass) then
681-
erasePolyFunctionApply(qualTp.select(nme.apply).widen).classSymbol
682-
else if defn.isErasedFunctionType(qualTp) then
683-
eraseErasedFunctionApply(qualTp.select(nme.apply).widen.asInstanceOf[MethodType]).classSymbol
680+
if defn.isPolyOrErasedFunctionType(qualTp) then
681+
eraseRefinedFunctionApply(qualTp.select(nme.apply).widen).classSymbol
684682
else
685683
NoSymbol
686684
}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -445,14 +445,12 @@ object TreeChecker {
445445
assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase)
446446
val tpe = tree.typeOpt
447447

448-
// Polymorphic apply methods stay structural until Erasure
449-
val isPolyFunctionApply = (tree.name eq nme.apply) && tree.qualifier.typeOpt.derivesFrom(defn.PolyFunctionClass)
450-
// Erased functions stay structural until Erasure
451-
val isErasedFunctionApply = (tree.name eq nme.apply) && tree.qualifier.typeOpt.derivesFrom(defn.ErasedFunctionClass)
448+
// PolyFunction and ErasedFunction apply methods stay structural until Erasure
449+
val isRefinedFunctionApply = (tree.name eq nme.apply) && defn.isPolyOrErasedFunctionType(tree.qualifier.typeOpt)
452450
// Outer selects are pickled specially so don't require a symbol
453451
val isOuterSelect = tree.name.is(OuterSelectName)
454452
val isPrimitiveArrayOp = ctx.erasedTypes && nme.isPrimitiveName(tree.name)
455-
if !(tree.isType || isPolyFunctionApply || isErasedFunctionApply || isOuterSelect || isPrimitiveArrayOp) then
453+
if !(tree.isType || isRefinedFunctionApply || isOuterSelect || isPrimitiveArrayOp) then
456454
val denot = tree.denot
457455
assert(denot.exists, i"Selection $tree with type $tpe does not have a denotation")
458456
assert(denot.symbol.exists, i"Denotation $denot of selection $tree with type $tpe does not have a symbol, qualifier type = ${tree.qualifier.typeOpt}")

0 commit comments

Comments
 (0)