@@ -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
@@ -88,7 +89,7 @@ class Definitions {
88
89
*
89
90
* FunctionN traits follow this template:
90
91
*
91
- * trait FunctionN[T0,...T{N-1}, R] extends Object {
92
+ * trait FunctionN[- T0,...- T{N-1}, + R] extends Object {
92
93
* def apply($x0: T0, ..., $x{N_1}: T{N-1}): R
93
94
* }
94
95
*
@@ -98,46 +99,65 @@ class Definitions {
98
99
*
99
100
* ContextFunctionN traits follow this template:
100
101
*
101
- * trait ContextFunctionN[T0,...,T{N-1}, R] extends Object {
102
+ * trait ContextFunctionN[- T0,...,- T{N-1}, + R] extends Object {
102
103
* def apply(using $x0: T0, ..., $x{N_1}: T{N-1}): R
103
104
* }
104
105
*
105
106
* ErasedFunctionN traits follow this template:
106
107
*
107
- * trait ErasedFunctionN[T0,...,T{N-1}, R] extends Object {
108
+ * trait ErasedFunctionN[- T0,...,- T{N-1}, + R] extends Object {
108
109
* def apply(erased $x0: T0, ..., $x{N_1}: T{N-1}): R
109
110
* }
110
111
*
111
112
* ErasedContextFunctionN traits follow this template:
112
113
*
113
- * trait ErasedContextFunctionN[T0,...,T{N-1}, R] extends Object {
114
+ * trait ErasedContextFunctionN[- T0,...,- T{N-1}, + R] extends Object {
114
115
* def apply(using erased $x0: T0, ..., $x{N_1}: T{N-1}): R
115
116
* }
116
117
*
117
118
* ErasedFunctionN and ErasedContextFunctionN erase to Function0.
119
+ *
120
+ * EffXYZFunctionN afollow this template:
121
+ *
122
+ * type EffXYZFunctionN[-T0,...,-T{N-1}, +R] = {*} XYZFunctionN[T0,...,T{N-1}, R]
118
123
*/
119
- def newFunctionNTrait (name : TypeName ): ClassSymbol = {
124
+ private def newFunctionNType (name : TypeName ): Symbol = {
125
+ val impure = name.startsWith(" Impure" )
120
126
val completer = new LazyType {
121
127
def complete (denot : SymDenotation )(using Context ): Unit = {
122
- val cls = denot.asClass.classSymbol
123
- val decls = newScope
124
128
val arity = name.functionArity
125
- val paramNamePrefix = tpnme.scala ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR
126
- val argParamRefs = List .tabulate(arity) { i =>
127
- enterTypeParam(cls, paramNamePrefix ++ " T" ++ (i + 1 ).toString, Contravariant , decls).typeRef
128
- }
129
- val resParamRef = enterTypeParam(cls, paramNamePrefix ++ " R" , Covariant , decls).typeRef
130
- val methodType = MethodType .companion(
131
- isContextual = name.isContextFunction,
132
- isImplicit = false ,
133
- isErased = name.isErasedFunction)
134
- decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
135
- denot.info =
136
- ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: Nil , decls)
129
+ if impure then
130
+ val argParamNames = List .tabulate(arity)(tpnme.syntheticTypeParamName)
131
+ val argVariances = List .fill(arity)(Contravariant )
132
+ val underlyingName = name.asSimpleName.drop(6 )
133
+ val underlyingClass = ScalaPackageVal .requiredClass(underlyingName)
134
+ denot.info = TypeAlias (
135
+ HKTypeLambda (argParamNames :+ " R" .toTypeName, argVariances :+ Covariant )(
136
+ tl => List .fill(arity + 1 )(TypeBounds .empty),
137
+ tl => CapturingType (underlyingClass.typeRef.appliedTo(tl.paramRefs),
138
+ CaptureSet .universal, boxed = false )
139
+ ))
140
+ else
141
+ val cls = denot.asClass.classSymbol
142
+ val decls = newScope
143
+ val paramNamePrefix = tpnme.scala ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR
144
+ val argParamRefs = List .tabulate(arity) { i =>
145
+ enterTypeParam(cls, paramNamePrefix ++ " T" ++ (i + 1 ).toString, Contravariant , decls).typeRef
146
+ }
147
+ val resParamRef = enterTypeParam(cls, paramNamePrefix ++ " R" , Covariant , decls).typeRef
148
+ val methodType = MethodType .companion(
149
+ isContextual = name.isContextFunction,
150
+ isImplicit = false ,
151
+ isErased = name.isErasedFunction)
152
+ decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
153
+ denot.info =
154
+ ClassInfo (ScalaPackageClass .thisType, cls, ObjectType :: Nil , decls)
137
155
}
138
156
}
139
- val flags = Trait | NoInits
140
- newPermanentClassSymbol(ScalaPackageClass , name, flags, completer)
157
+ if impure then
158
+ newPermanentSymbol(ScalaPackageClass , name, EmptyFlags , completer)
159
+ else
160
+ newPermanentClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
141
161
}
142
162
143
163
private def newMethod (cls : ClassSymbol , name : TermName , info : Type , flags : FlagSet = EmptyFlags ): TermSymbol =
@@ -211,7 +231,7 @@ class Definitions {
211
231
val cls = ScalaPackageVal .moduleClass.asClass
212
232
cls.info.decls.openForMutations.useSynthesizer(
213
233
name =>
214
- if (name.isTypeName && name.isSyntheticFunction) newFunctionNTrait (name.asTypeName)
234
+ if (name.isTypeName && name.isSyntheticFunction) newFunctionNType (name.asTypeName)
215
235
else NoSymbol )
216
236
cls
217
237
}
@@ -1285,39 +1305,55 @@ class Definitions {
1285
1305
1286
1306
@ tu lazy val TupleType : Array [TypeRef ] = mkArityArray(" scala.Tuple" , MaxTupleArity , 1 )
1287
1307
1308
+ /** Cached function types of arbitary arities.
1309
+ * Function types are created on demand with newFunctionNTrait, which is
1310
+ * called from a synthesizer installed in ScalaPackageClass.
1311
+ */
1288
1312
private class FunType (prefix : String ):
1289
1313
private var classRefs : Array [TypeRef ] = new Array (22 )
1314
+
1290
1315
def apply (n : Int ): TypeRef =
1291
1316
while n >= classRefs.length do
1292
1317
val classRefs1 = new Array [TypeRef ](classRefs.length * 2 )
1293
1318
Array .copy(classRefs, 0 , classRefs1, 0 , classRefs.length)
1294
1319
classRefs = classRefs1
1320
+ val funName = s " scala. $prefix$n"
1295
1321
if classRefs(n) == null then
1296
- classRefs(n) = requiredClassRef(prefix + n.toString)
1322
+ classRefs(n) =
1323
+ if prefix.startsWith(" Impure" )
1324
+ then staticRef(funName.toTypeName).symbol.typeRef
1325
+ else requiredClassRef(funName)
1297
1326
classRefs(n)
1298
-
1299
- private val erasedContextFunType = FunType (" scala.ErasedContextFunction" )
1300
- private val contextFunType = FunType (" scala.ContextFunction" )
1301
- private val erasedFunType = FunType (" scala.ErasedFunction" )
1302
- private val funType = FunType (" scala.Function" )
1303
-
1304
- def FunctionClass (n : Int , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): Symbol =
1305
- ( if isContextual && isErased then erasedContextFunType(n)
1306
- else if isContextual then contextFunType(n)
1307
- else if isErased then erasedFunType(n)
1308
- else funType(n)
1309
- ).symbol.asClass
1327
+ end FunType
1328
+
1329
+ private def funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ): Int =
1330
+ (if isContextual then 1 else 0 )
1331
+ + (if isErased then 2 else 0 )
1332
+ + (if isImpure then 4 else 0 )
1333
+
1334
+ private val funTypeArray : IArray [FunType ] =
1335
+ val arr = Array .ofDim[FunType ](8 )
1336
+ val choices = List (false , true )
1337
+ for contxt <- choices; erasd <- choices; impure <- choices do
1338
+ var str = " Function"
1339
+ if contxt then str = " Context" + str
1340
+ if erasd then str = " Erased" + str
1341
+ if impure then str = " Impure" + str
1342
+ arr(funTypeIdx(contxt, erasd, impure)) = FunType (str)
1343
+ IArray .unsafeFromArray(arr)
1344
+
1345
+ def FunctionSymbol (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1346
+ funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
1310
1347
1311
1348
@ tu lazy val Function0_apply : Symbol = Function0 .requiredMethod(nme.apply)
1312
- @ tu lazy val ContextFunction0_apply : Symbol = ContextFunction0 .requiredMethod(nme.apply)
1313
1349
1314
- @ tu lazy val Function0 : Symbol = FunctionClass (0 )
1315
- @ tu lazy val Function1 : Symbol = FunctionClass (1 )
1316
- @ tu lazy val Function2 : Symbol = FunctionClass (2 )
1317
- @ tu lazy val ContextFunction0 : Symbol = FunctionClass (0 , isContextual = true )
1350
+ @ tu lazy val Function0 : Symbol = FunctionSymbol (0 )
1351
+ @ tu lazy val Function1 : Symbol = FunctionSymbol (1 )
1352
+ @ tu lazy val Function2 : Symbol = FunctionSymbol (2 )
1353
+ @ tu lazy val ContextFunction0 : Symbol = FunctionSymbol (0 , isContextual = true )
1318
1354
1319
- def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): TypeRef =
1320
- FunctionClass (n, isContextual && ! ctx.erasedTypes, isErased).typeRef
1355
+ def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1356
+ FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isErased, isImpure ).typeRef
1321
1357
1322
1358
lazy val PolyFunctionClass = requiredClass(" scala.PolyFunction" )
1323
1359
def PolyFunctionType = PolyFunctionClass .typeRef
@@ -1359,6 +1395,10 @@ class Definitions {
1359
1395
*/
1360
1396
def isFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isFunction
1361
1397
1398
+ /** Is a function class, or an impure function type alias */
1399
+ def isFunctionSymbol (sym : Symbol ): Boolean =
1400
+ sym.isType && (sym.owner eq ScalaPackageClass ) && sym.name.isFunction
1401
+
1362
1402
/** Is a function class where
1363
1403
* - FunctionN for N >= 0 and N != XXL
1364
1404
*/
@@ -1565,7 +1605,7 @@ class Definitions {
1565
1605
1566
1606
def isSpecializableFunction (cls : ClassSymbol , paramTypes : List [Type ], retType : Type )(using Context ): Boolean =
1567
1607
paramTypes.length <= 2
1568
- && (cls.derivesFrom(FunctionClass (paramTypes.length)) || isByNameFunctionClass(cls))
1608
+ && (cls.derivesFrom(FunctionSymbol (paramTypes.length)) || isByNameFunctionClass(cls))
1569
1609
&& isSpecializableFunctionSAM(paramTypes, retType)
1570
1610
1571
1611
/** If the Single Abstract Method of a Function class has this type, is it specializable? */
0 commit comments