@@ -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)
@@ -1094,15 +1079,24 @@ class Definitions {
1094
1079
sym.owner.linkedClass.typeRef
1095
1080
1096
1081
object FunctionOf {
1097
- def apply (args : List [Type ], resultType : Type , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): Type =
1098
- FunctionType (args.length, isContextual, isErased).appliedTo(args ::: resultType :: Nil )
1099
- def unapply (ft : Type )(using Context ): Option [(List [Type ], Type , Boolean , Boolean )] = {
1100
- val tsym = ft.typeSymbol
1101
- if isFunctionClass(tsym) && ft.isRef(tsym) then
1102
- val targs = ft.dealias.argInfos
1103
- if (targs.isEmpty) None
1104
- else Some (targs.init, targs.last, tsym.name.isContextFunction, tsym.name.isErasedFunction)
1105
- else None
1082
+ def apply (args : List [Type ], resultType : Type , isContextual : Boolean = false , erasedParams : List [Boolean ] = List ())(using Context ): Type =
1083
+ assert(erasedParams.size == 0 || args.size == erasedParams.size)
1084
+ if erasedParams.contains(true ) then
1085
+ val mt = MethodType .companion(isContextual, false , erasedParams.padTo(args.size, false ))(args, resultType)
1086
+ RefinedType (ErasedFunctionType , nme.apply, mt)
1087
+ else
1088
+ FunctionType (args.length, isContextual).appliedTo(args ::: resultType :: Nil )
1089
+ def unapply (ft : Type )(using Context ): Option [(List [Type ], Type , Boolean , List [Boolean ])] = {
1090
+ ft.dealias match
1091
+ case RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) =>
1092
+ Some (mt.paramInfos, mt.resType, mt.isContextualMethod, mt.erasedParams)
1093
+ case _ =>
1094
+ val tsym = ft.dealias.typeSymbol
1095
+ if isFunctionSymbol(tsym) && ft.isRef(tsym) then
1096
+ val targs = ft.dealias.argInfos
1097
+ if (targs.isEmpty) None
1098
+ else Some (targs.init, targs.last, tsym.name.isContextFunction, List .fill(targs.init.size) { false })
1099
+ else None
1106
1100
}
1107
1101
}
1108
1102
@@ -1421,24 +1415,22 @@ class Definitions {
1421
1415
classRefs(n).nn
1422
1416
end FunType
1423
1417
1424
- private def funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ): Int =
1418
+ private def funTypeIdx (isContextual : Boolean , isImpure : Boolean ): Int =
1425
1419
(if isContextual then 1 else 0 )
1426
- + (if isErased then 2 else 0 )
1427
- + (if isImpure then 4 else 0 )
1420
+ + (if isImpure then 2 else 0 )
1428
1421
1429
1422
private val funTypeArray : IArray [FunType ] =
1430
1423
val arr = Array .ofDim[FunType ](8 )
1431
1424
val choices = List (false , true )
1432
- for contxt <- choices; erasd <- choices; impure <- choices do
1425
+ for contxt <- choices; impure <- choices do
1433
1426
var str = " Function"
1434
1427
if contxt then str = " Context" + str
1435
- if erasd then str = " Erased" + str
1436
1428
if impure then str = " Impure" + str
1437
- arr(funTypeIdx(contxt, erasd, impure)) = FunType (str)
1429
+ arr(funTypeIdx(contxt, impure)) = FunType (str)
1438
1430
IArray .unsafeFromArray(arr)
1439
1431
1440
- def FunctionSymbol (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1441
- funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
1432
+ def FunctionSymbol (n : Int , isContextual : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1433
+ funTypeArray(funTypeIdx(isContextual, isImpure))(n).symbol
1442
1434
1443
1435
@ tu lazy val Function0_apply : Symbol = Function0 .requiredMethod(nme.apply)
1444
1436
@ tu lazy val ContextFunction0_apply : Symbol = ContextFunction0 .requiredMethod(nme.apply)
@@ -1448,12 +1440,15 @@ class Definitions {
1448
1440
@ tu lazy val Function2 : Symbol = FunctionSymbol (2 )
1449
1441
@ tu lazy val ContextFunction0 : Symbol = FunctionSymbol (0 , isContextual = true )
1450
1442
1451
- def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1452
- FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isErased, isImpure).typeRef
1443
+ def FunctionType (n : Int , isContextual : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1444
+ FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isImpure).typeRef
1453
1445
1454
1446
lazy val PolyFunctionClass = requiredClass(" scala.PolyFunction" )
1455
1447
def PolyFunctionType = PolyFunctionClass .typeRef
1456
1448
1449
+ lazy val ErasedFunctionClass = requiredClass(" scala.ErasedFunction" )
1450
+ def ErasedFunctionType = ErasedFunctionClass .typeRef
1451
+
1457
1452
/** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */
1458
1453
def scalaClassName (cls : Symbol )(using Context ): TypeName = cls.denot match
1459
1454
case clsd : ClassDenotation if clsd.owner eq ScalaPackageClass =>
@@ -1484,10 +1479,9 @@ class Definitions {
1484
1479
1485
1480
/** Is any function class where
1486
1481
* - FunctionXXL
1482
+ * - ErasedFunction
1487
1483
* - FunctionN for N >= 0
1488
1484
* - ContextFunctionN for N >= 0
1489
- * - ErasedFunctionN for N > 0
1490
- * - ErasedContextFunctionN for N > 0
1491
1485
*/
1492
1486
def isFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isFunction
1493
1487
@@ -1506,12 +1500,6 @@ class Definitions {
1506
1500
*/
1507
1501
def isContextFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isContextFunction
1508
1502
1509
- /** Is an erased function class.
1510
- * - ErasedFunctionN for N > 0
1511
- * - ErasedContextFunctionN for N > 0
1512
- */
1513
- def isErasedFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isErasedFunction
1514
-
1515
1503
/** Is either FunctionXXL or a class that will be erased to FunctionXXL
1516
1504
* - FunctionXXL
1517
1505
* - FunctionN for N >= 22
@@ -1548,8 +1536,7 @@ class Definitions {
1548
1536
*/
1549
1537
def functionTypeErasure (cls : Symbol ): Type =
1550
1538
val arity = scalaClassName(cls).functionArity
1551
- if cls.name.isErasedFunction then FunctionType (0 )
1552
- else if arity > 22 then FunctionXXLClass .typeRef
1539
+ if arity > 22 then FunctionXXLClass .typeRef
1553
1540
else if arity >= 0 then FunctionType (arity)
1554
1541
else NoType
1555
1542
@@ -1680,13 +1667,13 @@ class Definitions {
1680
1667
arity >= 0
1681
1668
&& isFunctionClass(sym)
1682
1669
&& tp.isRef(
1683
- FunctionType (arity, sym.name.isContextFunction, sym.name.isErasedFunction ).typeSymbol,
1670
+ FunctionType (arity, sym.name.isContextFunction).typeSymbol,
1684
1671
skipRefined = false )
1685
1672
end isNonRefinedFunction
1686
1673
1687
1674
/** Is `tp` a representation of a (possibly dependent) function type or an alias of such? */
1688
1675
def isFunctionType (tp : Type )(using Context ): Boolean =
1689
- isNonRefinedFunction(tp.dropDependentRefinement)
1676
+ isNonRefinedFunction(tp.dropDependentRefinement) || isErasedFunctionType(tp)
1690
1677
1691
1678
def isFunctionOrPolyType (tp : Type )(using Context ): Boolean =
1692
1679
isFunctionType(tp) || (tp.typeSymbol eq defn.PolyFunctionClass )
@@ -1778,7 +1765,7 @@ class Definitions {
1778
1765
@ tu lazy val FunctionSpecializedApplyNames : collection.Set [Name ] =
1779
1766
Function0SpecializedApplyNames ++ Function1SpecializedApplyNames ++ Function2SpecializedApplyNames
1780
1767
1781
- 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
1782
1769
1783
1770
/** Return underlying context function type (i.e. instance of an ContextFunctionN class)
1784
1771
* or NoType if none exists. The following types are considered as underlying types:
@@ -1790,6 +1777,8 @@ class Definitions {
1790
1777
tp.stripTypeVar.dealias match
1791
1778
case tp1 : TypeParamRef if ctx.typerState.constraint.contains(tp1) =>
1792
1779
asContextFunctionType(TypeComparer .bounds(tp1).hiBound)
1780
+ case tp1 @ RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) && mt.isContextualMethod =>
1781
+ tp1
1793
1782
case tp1 =>
1794
1783
if tp1.typeSymbol.name.isContextFunction && isFunctionType(tp1) then tp1
1795
1784
else NoType
@@ -1803,18 +1792,28 @@ class Definitions {
1803
1792
* types `As`, the result type `B` and a whether the type is an erased context function.
1804
1793
*/
1805
1794
object ContextFunctionType :
1806
- def unapply (tp : Type )(using Context ): Option [(List [Type ], Type , Boolean )] =
1795
+ def unapply (tp : Type )(using Context ): Option [(List [Type ], Type , List [ Boolean ] )] =
1807
1796
if ctx.erasedTypes then
1808
1797
atPhase(erasurePhase)(unapply(tp))
1809
1798
else
1810
- val tp1 = asContextFunctionType(tp)
1811
- if tp1.exists then
1812
- val args = tp1.dropDependentRefinement.argInfos
1813
- Some ((args.init, args.last, tp1.typeSymbol.name.isErasedFunction))
1814
- 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
+ }
1815
1814
1816
1815
def isErasedFunctionType (tp : Type )(using Context ): Boolean =
1817
- tp.dealias.typeSymbol.name.isErasedFunction && isFunctionType(tp )
1816
+ tp.derivesFrom(defn. ErasedFunctionClass )
1818
1817
1819
1818
/** A whitelist of Scala-2 classes that are known to be pure */
1820
1819
def isAssuredNoInits (sym : Symbol ): Boolean =
0 commit comments