@@ -86,7 +86,7 @@ class Definitions {
86
86
newPermanentClassSymbol(ScalaPackageClass , name, Artifact , completer).entered
87
87
}
88
88
89
- /** The trait FunctionN, ContextFunctionN, ErasedFunctionN or ErasedContextFunction, for some N
89
+ /** The trait FunctionN and ContextFunctionN for some N
90
90
* @param name The name of the trait to be created
91
91
*
92
92
* FunctionN traits follow this template:
@@ -104,21 +104,6 @@ class Definitions {
104
104
* trait ContextFunctionN[-T0,...,-T{N-1}, +R] extends Object {
105
105
* def apply(using $x0: T0, ..., $x{N_1}: T{N-1}): R
106
106
* }
107
- *
108
- * ErasedFunctionN traits follow this template:
109
- *
110
- * trait ErasedFunctionN[-T0,...,-T{N-1}, +R] extends Object {
111
- * def apply(erased $x0: T0, ..., $x{N_1}: T{N-1}): R
112
- * }
113
- *
114
- * ErasedContextFunctionN traits follow this template:
115
- *
116
- * trait ErasedContextFunctionN[-T0,...,-T{N-1}, +R] extends Object {
117
- * def apply(using erased $x0: T0, ..., $x{N_1}: T{N-1}): R
118
- * }
119
- *
120
- * ErasedFunctionN and ErasedContextFunctionN erase to Function0.
121
- *
122
107
* ImpureXYZFunctionN follow this template:
123
108
*
124
109
* type ImpureXYZFunctionN[-T0,...,-T{N-1}, +R] = {*} XYZFunctionN[T0,...,T{N-1}, R]
@@ -150,7 +135,7 @@ class Definitions {
150
135
val methodType = MethodType .companion(
151
136
isContextual = name.isContextFunction,
152
137
isImplicit = false ,
153
- isErased = name.isErasedFunction )
138
+ erasedParams = List () )
154
139
decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
155
140
denot.info =
156
141
ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: Nil , decls)
@@ -1095,15 +1080,24 @@ class Definitions {
1095
1080
sym.owner.linkedClass.typeRef
1096
1081
1097
1082
object FunctionOf {
1098
- def apply (args : List [Type ], resultType : Type , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): Type =
1099
- FunctionType (args.length, isContextual, isErased).appliedTo(args ::: resultType :: Nil )
1100
- def unapply (ft : Type )(using Context ): Option [(List [Type ], Type , Boolean , Boolean )] = {
1101
- val tsym = ft.typeSymbol
1102
- if isFunctionClass(tsym) && ft.isRef(tsym) then
1103
- val targs = ft.dealias.argInfos
1104
- if (targs.isEmpty) None
1105
- else Some (targs.init, targs.last, tsym.name.isContextFunction, tsym.name.isErasedFunction)
1106
- else None
1083
+ def apply (args : List [Type ], resultType : Type , isContextual : Boolean = false , erasedParams : List [Boolean ] = List ())(using Context ): Type =
1084
+ assert(erasedParams.size == 0 || args.size == erasedParams.size)
1085
+ if erasedParams.contains(true ) then
1086
+ val mt = MethodType .companion(isContextual, false , erasedParams.padTo(args.size, false ))(args, resultType)
1087
+ RefinedType (ErasedFunctionClass .typeRef, nme.apply, mt)
1088
+ else
1089
+ FunctionType (args.length, isContextual).appliedTo(args ::: resultType :: Nil )
1090
+ def unapply (ft : Type )(using Context ): Option [(List [Type ], Type , Boolean , List [Boolean ])] = {
1091
+ ft.dealias match
1092
+ case RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) =>
1093
+ Some (mt.paramInfos, mt.resType, mt.isContextualMethod, mt.erasedParams)
1094
+ case _ =>
1095
+ val tsym = ft.dealias.typeSymbol
1096
+ if isFunctionSymbol(tsym) && ft.isRef(tsym) then
1097
+ val targs = ft.dealias.argInfos
1098
+ if (targs.isEmpty) None
1099
+ else Some (targs.init, targs.last, tsym.name.isContextFunction, List .fill(targs.init.size) { false })
1100
+ else None
1107
1101
}
1108
1102
}
1109
1103
@@ -1422,24 +1416,22 @@ class Definitions {
1422
1416
classRefs(n).nn
1423
1417
end FunType
1424
1418
1425
- private def funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ): Int =
1419
+ private def funTypeIdx (isContextual : Boolean , isImpure : Boolean ): Int =
1426
1420
(if isContextual then 1 else 0 )
1427
- + (if isErased then 2 else 0 )
1428
- + (if isImpure then 4 else 0 )
1421
+ + (if isImpure then 2 else 0 )
1429
1422
1430
1423
private val funTypeArray : IArray [FunType ] =
1431
1424
val arr = Array .ofDim[FunType ](8 )
1432
1425
val choices = List (false , true )
1433
- for contxt <- choices; erasd <- choices; impure <- choices do
1426
+ for contxt <- choices; impure <- choices do
1434
1427
var str = " Function"
1435
1428
if contxt then str = " Context" + str
1436
- if erasd then str = " Erased" + str
1437
1429
if impure then str = " Impure" + str
1438
- arr(funTypeIdx(contxt, erasd, impure)) = FunType (str)
1430
+ arr(funTypeIdx(contxt, impure)) = FunType (str)
1439
1431
IArray .unsafeFromArray(arr)
1440
1432
1441
- def FunctionSymbol (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1442
- funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
1433
+ def FunctionSymbol (n : Int , isContextual : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1434
+ funTypeArray(funTypeIdx(isContextual, isImpure))(n).symbol
1443
1435
1444
1436
@ tu lazy val Function0_apply : Symbol = Function0 .requiredMethod(nme.apply)
1445
1437
@ tu lazy val ContextFunction0_apply : Symbol = ContextFunction0 .requiredMethod(nme.apply)
@@ -1449,12 +1441,14 @@ class Definitions {
1449
1441
@ tu lazy val Function2 : Symbol = FunctionSymbol (2 )
1450
1442
@ tu lazy val ContextFunction0 : Symbol = FunctionSymbol (0 , isContextual = true )
1451
1443
1452
- def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1453
- FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isErased, isImpure).typeRef
1444
+ def FunctionType (n : Int , isContextual : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1445
+ FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isImpure).typeRef
1454
1446
1455
1447
lazy val PolyFunctionClass = requiredClass(" scala.PolyFunction" )
1456
1448
def PolyFunctionType = PolyFunctionClass .typeRef
1457
1449
1450
+ lazy val ErasedFunctionClass = requiredClass(" scala.runtime.ErasedFunction" )
1451
+
1458
1452
/** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */
1459
1453
def scalaClassName (cls : Symbol )(using Context ): TypeName = cls.denot match
1460
1454
case clsd : ClassDenotation if clsd.owner eq ScalaPackageClass =>
@@ -1485,10 +1479,9 @@ class Definitions {
1485
1479
1486
1480
/** Is any function class where
1487
1481
* - FunctionXXL
1482
+ * - ErasedFunction
1488
1483
* - FunctionN for N >= 0
1489
1484
* - ContextFunctionN for N >= 0
1490
- * - ErasedFunctionN for N > 0
1491
- * - ErasedContextFunctionN for N > 0
1492
1485
*/
1493
1486
def isFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isFunction
1494
1487
@@ -1507,12 +1500,6 @@ class Definitions {
1507
1500
*/
1508
1501
def isContextFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isContextFunction
1509
1502
1510
- /** Is an erased function class.
1511
- * - ErasedFunctionN for N > 0
1512
- * - ErasedContextFunctionN for N > 0
1513
- */
1514
- def isErasedFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isErasedFunction
1515
-
1516
1503
/** Is either FunctionXXL or a class that will be erased to FunctionXXL
1517
1504
* - FunctionXXL
1518
1505
* - FunctionN for N >= 22
@@ -1549,8 +1536,7 @@ class Definitions {
1549
1536
*/
1550
1537
def functionTypeErasure (cls : Symbol ): Type =
1551
1538
val arity = scalaClassName(cls).functionArity
1552
- if cls.name.isErasedFunction then FunctionType (0 )
1553
- else if arity > 22 then FunctionXXLClass .typeRef
1539
+ if arity > 22 then FunctionXXLClass .typeRef
1554
1540
else if arity >= 0 then FunctionType (arity)
1555
1541
else NoType
1556
1542
@@ -1681,13 +1667,13 @@ class Definitions {
1681
1667
arity >= 0
1682
1668
&& isFunctionClass(sym)
1683
1669
&& tp.isRef(
1684
- FunctionType (arity, sym.name.isContextFunction, sym.name.isErasedFunction ).typeSymbol,
1670
+ FunctionType (arity, sym.name.isContextFunction).typeSymbol,
1685
1671
skipRefined = false )
1686
1672
end isNonRefinedFunction
1687
1673
1688
1674
/** Is `tp` a representation of a (possibly dependent) function type or an alias of such? */
1689
1675
def isFunctionType (tp : Type )(using Context ): Boolean =
1690
- isNonRefinedFunction(tp.dropDependentRefinement)
1676
+ isNonRefinedFunction(tp.dropDependentRefinement) || isErasedFunctionType(tp)
1691
1677
1692
1678
def isFunctionOrPolyType (tp : Type )(using Context ): Boolean =
1693
1679
isFunctionType(tp) || (tp.typeSymbol eq defn.PolyFunctionClass )
@@ -1779,7 +1765,7 @@ class Definitions {
1779
1765
@ tu lazy val FunctionSpecializedApplyNames : collection.Set [Name ] =
1780
1766
Function0SpecializedApplyNames ++ Function1SpecializedApplyNames ++ Function2SpecializedApplyNames
1781
1767
1782
- def functionArity (tp : Type )(using Context ): Int = tp.dropDependentRefinement.dealias.argInfos .length - 1
1768
+ def functionArity (tp : Type )(using Context ): Int = tp.functionArgInfos .length - 1
1783
1769
1784
1770
/** Return underlying context function type (i.e. instance of an ContextFunctionN class)
1785
1771
* or NoType if none exists. The following types are considered as underlying types:
@@ -1791,6 +1777,8 @@ class Definitions {
1791
1777
tp.stripTypeVar.dealias match
1792
1778
case tp1 : TypeParamRef if ctx.typerState.constraint.contains(tp1) =>
1793
1779
asContextFunctionType(TypeComparer .bounds(tp1).hiBound)
1780
+ case tp1 @ RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) && mt.isContextualMethod =>
1781
+ tp1
1794
1782
case tp1 =>
1795
1783
if tp1.typeSymbol.name.isContextFunction && isFunctionType(tp1) then tp1
1796
1784
else NoType
@@ -1804,18 +1792,28 @@ class Definitions {
1804
1792
* types `As`, the result type `B` and a whether the type is an erased context function.
1805
1793
*/
1806
1794
object ContextFunctionType :
1807
- def unapply (tp : Type )(using Context ): Option [(List [Type ], Type , Boolean )] =
1795
+ def unapply (tp : Type )(using Context ): Option [(List [Type ], Type , List [ Boolean ] )] =
1808
1796
if ctx.erasedTypes then
1809
1797
atPhase(erasurePhase)(unapply(tp))
1810
1798
else
1811
- val tp1 = asContextFunctionType(tp)
1812
- if tp1.exists then
1813
- val args = tp1.dropDependentRefinement.argInfos
1814
- Some ((args.init, args.last, tp1.typeSymbol.name.isErasedFunction))
1815
- else None
1799
+ asContextFunctionType(tp) match
1800
+ case RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) =>
1801
+ Some ((mt.paramInfos, mt.resType, mt.erasedParams))
1802
+ case tp1 if tp1.exists =>
1803
+ val args = tp1.functionArgInfos
1804
+ val erasedParams = erasedFunctionParameters(tp1)
1805
+ Some ((args.init, args.last, erasedParams))
1806
+ case _ => None
1807
+
1808
+ /* Returns a list of erased booleans marking whether parameters are erased, for a function type. */
1809
+ def erasedFunctionParameters (tp : Type )(using Context ): List [Boolean ] = tp.dealias match {
1810
+ case RefinedType (parent, nme.apply, mt : MethodType ) => mt.erasedParams
1811
+ case tp if isFunctionType(tp) => List .fill(functionArity(tp)) { false }
1812
+ case _ => Nil
1813
+ }
1816
1814
1817
1815
def isErasedFunctionType (tp : Type )(using Context ): Boolean =
1818
- tp.dealias.typeSymbol.name.isErasedFunction && isFunctionType(tp )
1816
+ tp.derivesFrom(defn. ErasedFunctionClass )
1819
1817
1820
1818
/** A whitelist of Scala-2 classes that are known to be pure */
1821
1819
def isAssuredNoInits (sym : Symbol ): Boolean =
0 commit comments