@@ -8,6 +8,7 @@ import Flags._, Scopes._, Decorators._, NameOps._, Periods._, NullOpsDecorator._
8
8
import unpickleScala2 .Scala2Unpickler .ensureConstructor
9
9
import scala .collection .mutable
10
10
import collection .mutable
11
+ import Denotations .{SingleDenotation , staticRef }
11
12
import util .{SimpleIdentityMap , SourceFile , NoSource }
12
13
import typer .ImportInfo .RootRef
13
14
import Comments .CommentsContext
@@ -89,7 +90,7 @@ class Definitions {
89
90
*
90
91
* FunctionN traits follow this template:
91
92
*
92
- * trait FunctionN[T0,...T{N-1}, R] extends Object {
93
+ * trait FunctionN[- T0,...- T{N-1}, + R] extends Object {
93
94
* def apply($x0: T0, ..., $x{N_1}: T{N-1}): R
94
95
* }
95
96
*
@@ -99,46 +100,65 @@ class Definitions {
99
100
*
100
101
* ContextFunctionN traits follow this template:
101
102
*
102
- * trait ContextFunctionN[T0,...,T{N-1}, R] extends Object {
103
+ * trait ContextFunctionN[- T0,...,- T{N-1}, + R] extends Object {
103
104
* def apply(using $x0: T0, ..., $x{N_1}: T{N-1}): R
104
105
* }
105
106
*
106
107
* ErasedFunctionN traits follow this template:
107
108
*
108
- * trait ErasedFunctionN[T0,...,T{N-1}, R] extends Object {
109
+ * trait ErasedFunctionN[- T0,...,- T{N-1}, + R] extends Object {
109
110
* def apply(erased $x0: T0, ..., $x{N_1}: T{N-1}): R
110
111
* }
111
112
*
112
113
* ErasedContextFunctionN traits follow this template:
113
114
*
114
- * trait ErasedContextFunctionN[T0,...,T{N-1}, R] extends Object {
115
+ * trait ErasedContextFunctionN[- T0,...,- T{N-1}, + R] extends Object {
115
116
* def apply(using erased $x0: T0, ..., $x{N_1}: T{N-1}): R
116
117
* }
117
118
*
118
119
* ErasedFunctionN and ErasedContextFunctionN erase to Function0.
120
+ *
121
+ * EffXYZFunctionN afollow this template:
122
+ *
123
+ * type EffXYZFunctionN[-T0,...,-T{N-1}, +R] = {*} XYZFunctionN[T0,...,T{N-1}, R]
119
124
*/
120
- def newFunctionNTrait (name : TypeName ): ClassSymbol = {
125
+ private def newFunctionNType (name : TypeName ): Symbol = {
126
+ val impure = name.startsWith(" Impure" )
121
127
val completer = new LazyType {
122
128
def complete (denot : SymDenotation )(using Context ): Unit = {
123
- val cls = denot.asClass.classSymbol
124
- val decls = newScope
125
129
val arity = name.functionArity
126
- val paramNamePrefix = tpnme.scala ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR
127
- val argParamRefs = List .tabulate(arity) { i =>
128
- enterTypeParam(cls, paramNamePrefix ++ " T" ++ (i + 1 ).toString, Contravariant , decls).typeRef
129
- }
130
- val resParamRef = enterTypeParam(cls, paramNamePrefix ++ " R" , Covariant , decls).typeRef
131
- val methodType = MethodType .companion(
132
- isContextual = name.isContextFunction,
133
- isImplicit = false ,
134
- isErased = name.isErasedFunction)
135
- decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
136
- denot.info =
137
- ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: Nil , decls)
130
+ if impure then
131
+ val argParamNames = List .tabulate(arity)(tpnme.syntheticTypeParamName)
132
+ val argVariances = List .fill(arity)(Contravariant )
133
+ val underlyingName = name.asSimpleName.drop(6 )
134
+ val underlyingClass = ScalaPackageVal .requiredClass(underlyingName)
135
+ denot.info = TypeAlias (
136
+ HKTypeLambda (argParamNames :+ " R" .toTypeName, argVariances :+ Covariant )(
137
+ tl => List .fill(arity + 1 )(TypeBounds .empty),
138
+ tl => CapturingType (underlyingClass.typeRef.appliedTo(tl.paramRefs),
139
+ CaptureSet .universal, boxed = false )
140
+ ))
141
+ else
142
+ val cls = denot.asClass.classSymbol
143
+ val decls = newScope
144
+ val paramNamePrefix = tpnme.scala ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR
145
+ val argParamRefs = List .tabulate(arity) { i =>
146
+ enterTypeParam(cls, paramNamePrefix ++ " T" ++ (i + 1 ).toString, Contravariant , decls).typeRef
147
+ }
148
+ val resParamRef = enterTypeParam(cls, paramNamePrefix ++ " R" , Covariant , decls).typeRef
149
+ val methodType = MethodType .companion(
150
+ isContextual = name.isContextFunction,
151
+ isImplicit = false ,
152
+ isErased = name.isErasedFunction)
153
+ decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
154
+ denot.info =
155
+ ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: Nil , decls)
138
156
}
139
157
}
140
- val flags = Trait | NoInits
141
- newPermanentClassSymbol(ScalaPackageClass , name, flags, completer)
158
+ if impure then
159
+ newPermanentSymbol(ScalaPackageClass , name, EmptyFlags , completer)
160
+ else
161
+ newPermanentClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
142
162
}
143
163
144
164
private def newMethod (cls : ClassSymbol , name : TermName , info : Type , flags : FlagSet = EmptyFlags ): TermSymbol =
@@ -212,7 +232,7 @@ class Definitions {
212
232
val cls = ScalaPackageVal .moduleClass.asClass
213
233
cls.info.decls.openForMutations.useSynthesizer(
214
234
name =>
215
- if (name.isTypeName && name.isSyntheticFunction) newFunctionNTrait (name.asTypeName)
235
+ if (name.isTypeName && name.isSyntheticFunction) newFunctionNType (name.asTypeName)
216
236
else NoSymbol )
217
237
cls
218
238
}
@@ -1342,39 +1362,54 @@ class Definitions {
1342
1362
def SpecializedTuple (base : Symbol , args : List [Type ])(using Context ): Symbol =
1343
1363
base.owner.requiredClass(base.name.specializedName(args))
1344
1364
1365
+ /** Cached function types of arbitary arities.
1366
+ * Function types are created on demand with newFunctionNTrait, which is
1367
+ * called from a synthesizer installed in ScalaPackageClass.
1368
+ */
1345
1369
private class FunType (prefix : String ):
1346
1370
private var classRefs : Array [TypeRef | Null ] = new Array (22 )
1347
1371
def apply (n : Int ): TypeRef =
1348
1372
while n >= classRefs.length do
1349
1373
val classRefs1 = new Array [TypeRef | Null ](classRefs.length * 2 )
1350
1374
Array .copy(classRefs, 0 , classRefs1, 0 , classRefs.length)
1351
1375
classRefs = classRefs1
1376
+ val funName = s " scala. $prefix$n"
1352
1377
if classRefs(n) == null then
1353
- classRefs(n) = requiredClassRef(prefix + n.toString)
1378
+ classRefs(n) =
1379
+ if prefix.startsWith(" Impure" )
1380
+ then staticRef(funName.toTypeName).symbol.typeRef
1381
+ else requiredClassRef(funName)
1354
1382
classRefs(n).nn
1355
-
1356
- private val erasedContextFunType = FunType (" scala.ErasedContextFunction" )
1357
- private val contextFunType = FunType (" scala.ContextFunction" )
1358
- private val erasedFunType = FunType (" scala.ErasedFunction" )
1359
- private val funType = FunType (" scala.Function" )
1360
-
1361
- def FunctionClass (n : Int , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): Symbol =
1362
- ( if isContextual && isErased then erasedContextFunType(n)
1363
- else if isContextual then contextFunType(n)
1364
- else if isErased then erasedFunType(n)
1365
- else funType(n)
1366
- ).symbol.asClass
1383
+ end FunType
1384
+
1385
+ private def funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ): Int =
1386
+ (if isContextual then 1 else 0 )
1387
+ + (if isErased then 2 else 0 )
1388
+ + (if isImpure then 4 else 0 )
1389
+
1390
+ private val funTypeArray : IArray [FunType ] =
1391
+ val arr = Array .ofDim[FunType ](8 )
1392
+ val choices = List (false , true )
1393
+ for contxt <- choices; erasd <- choices; impure <- choices do
1394
+ var str = " Function"
1395
+ if contxt then str = " Context" + str
1396
+ if erasd then str = " Erased" + str
1397
+ if impure then str = " Impure" + str
1398
+ arr(funTypeIdx(contxt, erasd, impure)) = FunType (str)
1399
+ IArray .unsafeFromArray(arr)
1400
+
1401
+ def FunctionSymbol (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1402
+ funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
1367
1403
1368
1404
@ tu lazy val Function0_apply : Symbol = Function0 .requiredMethod(nme.apply)
1369
- @ tu lazy val ContextFunction0_apply : Symbol = ContextFunction0 .requiredMethod(nme.apply)
1370
1405
1371
- @ tu lazy val Function0 : Symbol = FunctionClass (0 )
1372
- @ tu lazy val Function1 : Symbol = FunctionClass (1 )
1373
- @ tu lazy val Function2 : Symbol = FunctionClass (2 )
1374
- @ tu lazy val ContextFunction0 : Symbol = FunctionClass (0 , isContextual = true )
1406
+ @ tu lazy val Function0 : Symbol = FunctionSymbol (0 )
1407
+ @ tu lazy val Function1 : Symbol = FunctionSymbol (1 )
1408
+ @ tu lazy val Function2 : Symbol = FunctionSymbol (2 )
1409
+ @ tu lazy val ContextFunction0 : Symbol = FunctionSymbol (0 , isContextual = true )
1375
1410
1376
- def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): TypeRef =
1377
- FunctionClass (n, isContextual && ! ctx.erasedTypes, isErased).typeRef
1411
+ def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1412
+ FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isErased, isImpure ).typeRef
1378
1413
1379
1414
lazy val PolyFunctionClass = requiredClass(" scala.PolyFunction" )
1380
1415
def PolyFunctionType = PolyFunctionClass .typeRef
@@ -1416,6 +1451,10 @@ class Definitions {
1416
1451
*/
1417
1452
def isFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isFunction
1418
1453
1454
+ /** Is a function class, or an impure function type alias */
1455
+ def isFunctionSymbol (sym : Symbol ): Boolean =
1456
+ sym.isType && (sym.owner eq ScalaPackageClass ) && sym.name.isFunction
1457
+
1419
1458
/** Is a function class where
1420
1459
* - FunctionN for N >= 0 and N != XXL
1421
1460
*/
@@ -1649,7 +1688,7 @@ class Definitions {
1649
1688
1650
1689
def isSpecializableFunction (cls : ClassSymbol , paramTypes : List [Type ], retType : Type )(using Context ): Boolean =
1651
1690
paramTypes.length <= 2
1652
- && (cls.derivesFrom(FunctionClass (paramTypes.length)) || isByNameFunctionClass(cls))
1691
+ && (cls.derivesFrom(FunctionSymbol (paramTypes.length)) || isByNameFunctionClass(cls))
1653
1692
&& isSpecializableFunctionSAM(paramTypes, retType)
1654
1693
1655
1694
/** If the Single Abstract Method of a Function class has this type, is it specializable? */
0 commit comments