@@ -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)
@@ -1101,15 +1086,24 @@ class Definitions {
1101
1086
sym.owner.linkedClass.typeRef
1102
1087
1103
1088
object FunctionOf {
1104
- def apply (args : List [Type ], resultType : Type , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): Type =
1105
- FunctionType (args.length, isContextual, isErased).appliedTo(args ::: resultType :: Nil )
1106
- def unapply (ft : Type )(using Context ): Option [(List [Type ], Type , Boolean , Boolean )] = {
1107
- val tsym = ft.typeSymbol
1108
- if isFunctionClass(tsym) && ft.isRef(tsym) then
1109
- val targs = ft.dealias.argInfos
1110
- if (targs.isEmpty) None
1111
- else Some (targs.init, targs.last, tsym.name.isContextFunction, tsym.name.isErasedFunction)
1112
- else None
1089
+ def apply (args : List [Type ], resultType : Type , isContextual : Boolean = false , erasedParams : List [Boolean ] = List ())(using Context ): Type =
1090
+ assert(erasedParams.size == 0 || args.size == erasedParams.size)
1091
+ if erasedParams.contains(true ) then
1092
+ val mt = MethodType .companion(isContextual, false , erasedParams.padTo(args.size, false ))(args, resultType)
1093
+ RefinedType (ErasedFunctionClass .typeRef, nme.apply, mt)
1094
+ else
1095
+ FunctionType (args.length, isContextual).appliedTo(args ::: resultType :: Nil )
1096
+ def unapply (ft : Type )(using Context ): Option [(List [Type ], Type , Boolean , List [Boolean ])] = {
1097
+ ft.dealias match
1098
+ case RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) =>
1099
+ Some (mt.paramInfos, mt.resType, mt.isContextualMethod, mt.erasedParams)
1100
+ case _ =>
1101
+ val tsym = ft.dealias.typeSymbol
1102
+ if isFunctionSymbol(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, List .fill(targs.init.size) { false })
1106
+ else None
1113
1107
}
1114
1108
}
1115
1109
@@ -1428,24 +1422,22 @@ class Definitions {
1428
1422
classRefs(n).nn
1429
1423
end FunType
1430
1424
1431
- private def funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ): Int =
1425
+ private def funTypeIdx (isContextual : Boolean , isImpure : Boolean ): Int =
1432
1426
(if isContextual then 1 else 0 )
1433
- + (if isErased then 2 else 0 )
1434
- + (if isImpure then 4 else 0 )
1427
+ + (if isImpure then 2 else 0 )
1435
1428
1436
1429
private val funTypeArray : IArray [FunType ] =
1437
1430
val arr = Array .ofDim[FunType ](8 )
1438
1431
val choices = List (false , true )
1439
- for contxt <- choices; erasd <- choices; impure <- choices do
1432
+ for contxt <- choices; impure <- choices do
1440
1433
var str = " Function"
1441
1434
if contxt then str = " Context" + str
1442
- if erasd then str = " Erased" + str
1443
1435
if impure then str = " Impure" + str
1444
- arr(funTypeIdx(contxt, erasd, impure)) = FunType (str)
1436
+ arr(funTypeIdx(contxt, impure)) = FunType (str)
1445
1437
IArray .unsafeFromArray(arr)
1446
1438
1447
- def FunctionSymbol (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1448
- funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
1439
+ def FunctionSymbol (n : Int , isContextual : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1440
+ funTypeArray(funTypeIdx(isContextual, isImpure))(n).symbol
1449
1441
1450
1442
@ tu lazy val Function0_apply : Symbol = Function0 .requiredMethod(nme.apply)
1451
1443
@ tu lazy val ContextFunction0_apply : Symbol = ContextFunction0 .requiredMethod(nme.apply)
@@ -1455,12 +1447,14 @@ class Definitions {
1455
1447
@ tu lazy val Function2 : Symbol = FunctionSymbol (2 )
1456
1448
@ tu lazy val ContextFunction0 : Symbol = FunctionSymbol (0 , isContextual = true )
1457
1449
1458
- def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1459
- FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isErased, isImpure).typeRef
1450
+ def FunctionType (n : Int , isContextual : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1451
+ FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isImpure).typeRef
1460
1452
1461
1453
lazy val PolyFunctionClass = requiredClass(" scala.PolyFunction" )
1462
1454
def PolyFunctionType = PolyFunctionClass .typeRef
1463
1455
1456
+ lazy val ErasedFunctionClass = requiredClass(" scala.runtime.ErasedFunction" )
1457
+
1464
1458
/** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */
1465
1459
def scalaClassName (cls : Symbol )(using Context ): TypeName = cls.denot match
1466
1460
case clsd : ClassDenotation if clsd.owner eq ScalaPackageClass =>
@@ -1491,10 +1485,9 @@ class Definitions {
1491
1485
1492
1486
/** Is any function class where
1493
1487
* - FunctionXXL
1488
+ * - ErasedFunction
1494
1489
* - FunctionN for N >= 0
1495
1490
* - ContextFunctionN for N >= 0
1496
- * - ErasedFunctionN for N > 0
1497
- * - ErasedContextFunctionN for N > 0
1498
1491
*/
1499
1492
def isFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isFunction
1500
1493
@@ -1513,12 +1506,6 @@ class Definitions {
1513
1506
*/
1514
1507
def isContextFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isContextFunction
1515
1508
1516
- /** Is an erased function class.
1517
- * - ErasedFunctionN for N > 0
1518
- * - ErasedContextFunctionN for N > 0
1519
- */
1520
- def isErasedFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isErasedFunction
1521
-
1522
1509
/** Is either FunctionXXL or a class that will be erased to FunctionXXL
1523
1510
* - FunctionXXL
1524
1511
* - FunctionN for N >= 22
@@ -1555,8 +1542,7 @@ class Definitions {
1555
1542
*/
1556
1543
def functionTypeErasure (cls : Symbol ): Type =
1557
1544
val arity = scalaClassName(cls).functionArity
1558
- if cls.name.isErasedFunction then FunctionType (0 )
1559
- else if arity > 22 then FunctionXXLClass .typeRef
1545
+ if arity > 22 then FunctionXXLClass .typeRef
1560
1546
else if arity >= 0 then FunctionType (arity)
1561
1547
else NoType
1562
1548
@@ -1696,13 +1682,13 @@ class Definitions {
1696
1682
arity >= 0
1697
1683
&& isFunctionClass(sym)
1698
1684
&& tp.isRef(
1699
- FunctionType (arity, sym.name.isContextFunction, sym.name.isErasedFunction ).typeSymbol,
1685
+ FunctionType (arity, sym.name.isContextFunction).typeSymbol,
1700
1686
skipRefined = false )
1701
1687
end isNonRefinedFunction
1702
1688
1703
1689
/** Is `tp` a representation of a (possibly dependent) function type or an alias of such? */
1704
1690
def isFunctionType (tp : Type )(using Context ): Boolean =
1705
- isNonRefinedFunction(tp.dropDependentRefinement)
1691
+ isNonRefinedFunction(tp.dropDependentRefinement) || isErasedFunctionType(tp)
1706
1692
1707
1693
def isFunctionOrPolyType (tp : Type )(using Context ): Boolean =
1708
1694
isFunctionType(tp) || (tp.typeSymbol eq defn.PolyFunctionClass )
@@ -1794,7 +1780,7 @@ class Definitions {
1794
1780
@ tu lazy val FunctionSpecializedApplyNames : collection.Set [Name ] =
1795
1781
Function0SpecializedApplyNames ++ Function1SpecializedApplyNames ++ Function2SpecializedApplyNames
1796
1782
1797
- def functionArity (tp : Type )(using Context ): Int = tp.dropDependentRefinement.dealias.argInfos .length - 1
1783
+ def functionArity (tp : Type )(using Context ): Int = tp.functionArgInfos .length - 1
1798
1784
1799
1785
/** Return underlying context function type (i.e. instance of an ContextFunctionN class)
1800
1786
* or NoType if none exists. The following types are considered as underlying types:
@@ -1806,6 +1792,8 @@ class Definitions {
1806
1792
tp.stripTypeVar.dealias match
1807
1793
case tp1 : TypeParamRef if ctx.typerState.constraint.contains(tp1) =>
1808
1794
asContextFunctionType(TypeComparer .bounds(tp1).hiBound)
1795
+ case tp1 @ RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) && mt.isContextualMethod =>
1796
+ tp1
1809
1797
case tp1 =>
1810
1798
if tp1.typeSymbol.name.isContextFunction && isFunctionType(tp1) then tp1
1811
1799
else NoType
@@ -1819,18 +1807,28 @@ class Definitions {
1819
1807
* types `As`, the result type `B` and a whether the type is an erased context function.
1820
1808
*/
1821
1809
object ContextFunctionType :
1822
- def unapply (tp : Type )(using Context ): Option [(List [Type ], Type , Boolean )] =
1810
+ def unapply (tp : Type )(using Context ): Option [(List [Type ], Type , List [ Boolean ] )] =
1823
1811
if ctx.erasedTypes then
1824
1812
atPhase(erasurePhase)(unapply(tp))
1825
1813
else
1826
- val tp1 = asContextFunctionType(tp)
1827
- if tp1.exists then
1828
- val args = tp1.dropDependentRefinement.argInfos
1829
- Some ((args.init, args.last, tp1.typeSymbol.name.isErasedFunction))
1830
- else None
1814
+ asContextFunctionType(tp) match
1815
+ case RefinedType (parent, nme.apply, mt : MethodType ) if isErasedFunctionType(parent) =>
1816
+ Some ((mt.paramInfos, mt.resType, mt.erasedParams))
1817
+ case tp1 if tp1.exists =>
1818
+ val args = tp1.functionArgInfos
1819
+ val erasedParams = erasedFunctionParameters(tp1)
1820
+ Some ((args.init, args.last, erasedParams))
1821
+ case _ => None
1822
+
1823
+ /* Returns a list of erased booleans marking whether parameters are erased, for a function type. */
1824
+ def erasedFunctionParameters (tp : Type )(using Context ): List [Boolean ] = tp.dealias match {
1825
+ case RefinedType (parent, nme.apply, mt : MethodType ) => mt.erasedParams
1826
+ case tp if isFunctionType(tp) => List .fill(functionArity(tp)) { false }
1827
+ case _ => Nil
1828
+ }
1831
1829
1832
1830
def isErasedFunctionType (tp : Type )(using Context ): Boolean =
1833
- tp.dealias.typeSymbol.name.isErasedFunction && isFunctionType(tp )
1831
+ tp.derivesFrom(defn. ErasedFunctionClass )
1834
1832
1835
1833
/** A whitelist of Scala-2 classes that are known to be pure */
1836
1834
def isAssuredNoInits (sym : Symbol ): Boolean =
0 commit comments