@@ -8,7 +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
11
+ import Denotations .{ SingleDenotation , staticRef }
12
12
import util .{SimpleIdentityMap , SourceFile , NoSource }
13
13
import typer .ImportInfo .RootRef
14
14
import Comments .CommentsContext
@@ -89,7 +89,7 @@ class Definitions {
89
89
*
90
90
* FunctionN traits follow this template:
91
91
*
92
- * trait FunctionN[T0,...T{N-1}, R] extends Object {
92
+ * trait FunctionN[- T0,...- T{N-1}, + R] extends Object {
93
93
* def apply($x0: T0, ..., $x{N_1}: T{N-1}): R
94
94
* }
95
95
*
@@ -99,46 +99,65 @@ class Definitions {
99
99
*
100
100
* ContextFunctionN traits follow this template:
101
101
*
102
- * trait ContextFunctionN[T0,...,T{N-1}, R] extends Object {
102
+ * trait ContextFunctionN[- T0,...,- T{N-1}, + R] extends Object {
103
103
* def apply(using $x0: T0, ..., $x{N_1}: T{N-1}): R
104
104
* }
105
105
*
106
106
* ErasedFunctionN traits follow this template:
107
107
*
108
- * trait ErasedFunctionN[T0,...,T{N-1}, R] extends Object {
108
+ * trait ErasedFunctionN[- T0,...,- T{N-1}, + R] extends Object {
109
109
* def apply(erased $x0: T0, ..., $x{N_1}: T{N-1}): R
110
110
* }
111
111
*
112
112
* ErasedContextFunctionN traits follow this template:
113
113
*
114
- * trait ErasedContextFunctionN[T0,...,T{N-1}, R] extends Object {
114
+ * trait ErasedContextFunctionN[- T0,...,- T{N-1}, + R] extends Object {
115
115
* def apply(using erased $x0: T0, ..., $x{N_1}: T{N-1}): R
116
116
* }
117
117
*
118
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]
119
123
*/
120
- def newFunctionNTrait (name : TypeName ): ClassSymbol = {
124
+ private def newFunctionNType (name : TypeName ): Symbol = {
125
+ val impure = name.startsWith(" Impure" )
121
126
val completer = new LazyType {
122
127
def complete (denot : SymDenotation )(using Context ): Unit = {
123
- val cls = denot.asClass.classSymbol
124
- val decls = newScope
125
128
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)
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)
138
155
}
139
156
}
140
- val flags = Trait | NoInits
141
- newPermanentClassSymbol(ScalaPackageClass , name, flags, completer)
157
+ if impure then
158
+ newPermanentSymbol(ScalaPackageClass , name, EmptyFlags , completer)
159
+ else
160
+ newPermanentClassSymbol(ScalaPackageClass , name, Trait | NoInits , completer)
142
161
}
143
162
144
163
private def newMethod (cls : ClassSymbol , name : TermName , info : Type , flags : FlagSet = EmptyFlags ): TermSymbol =
@@ -212,7 +231,7 @@ class Definitions {
212
231
val cls = ScalaPackageVal .moduleClass.asClass
213
232
cls.info.decls.openForMutations.useSynthesizer(
214
233
name =>
215
- if (name.isTypeName && name.isSyntheticFunction) newFunctionNTrait (name.asTypeName)
234
+ if (name.isTypeName && name.isSyntheticFunction) newFunctionNType (name.asTypeName)
216
235
else NoSymbol )
217
236
cls
218
237
}
@@ -1289,39 +1308,55 @@ class Definitions {
1289
1308
1290
1309
@ tu lazy val TupleType : Array [TypeRef ] = mkArityArray(" scala.Tuple" , MaxTupleArity , 1 )
1291
1310
1311
+ /** Cached function types of arbitary arities.
1312
+ * Function types are created on demand with newFunctionNTrait, which is
1313
+ * called from a synthesizer installed in ScalaPackageClass.
1314
+ */
1292
1315
private class FunType (prefix : String ):
1293
1316
private var classRefs : Array [TypeRef ] = new Array (22 )
1317
+
1294
1318
def apply (n : Int ): TypeRef =
1295
1319
while n >= classRefs.length do
1296
1320
val classRefs1 = new Array [TypeRef ](classRefs.length * 2 )
1297
1321
Array .copy(classRefs, 0 , classRefs1, 0 , classRefs.length)
1298
1322
classRefs = classRefs1
1323
+ val funName = s " scala. $prefix$n"
1299
1324
if classRefs(n) == null then
1300
- classRefs(n) = requiredClassRef(prefix + n.toString)
1325
+ classRefs(n) =
1326
+ if prefix.startsWith(" Impure" )
1327
+ then staticRef(funName.toTypeName).symbol.typeRef
1328
+ else requiredClassRef(funName)
1301
1329
classRefs(n)
1302
-
1303
- private val erasedContextFunType = FunType (" scala.ErasedContextFunction" )
1304
- private val contextFunType = FunType (" scala.ContextFunction" )
1305
- private val erasedFunType = FunType (" scala.ErasedFunction" )
1306
- private val funType = FunType (" scala.Function" )
1307
-
1308
- def FunctionClass (n : Int , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): Symbol =
1309
- ( if isContextual && isErased then erasedContextFunType(n)
1310
- else if isContextual then contextFunType(n)
1311
- else if isErased then erasedFunType(n)
1312
- else funType(n)
1313
- ).symbol.asClass
1330
+ end FunType
1331
+
1332
+ private def funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ): Int =
1333
+ (if isContextual then 1 else 0 )
1334
+ + (if isErased then 2 else 0 )
1335
+ + (if isImpure then 4 else 0 )
1336
+
1337
+ private val funTypeArray : IArray [FunType ] =
1338
+ val arr = Array .ofDim[FunType ](8 )
1339
+ val choices = List (false , true )
1340
+ for contxt <- choices; erasd <- choices; impure <- choices do
1341
+ var str = " Function"
1342
+ if contxt then str = " Context" + str
1343
+ if erasd then str = " Erased" + str
1344
+ if impure then str = " Impure" + str
1345
+ arr(funTypeIdx(contxt, erasd, impure)) = FunType (str)
1346
+ IArray .unsafeFromArray(arr)
1347
+
1348
+ def FunctionSymbol (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): Symbol =
1349
+ funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
1314
1350
1315
1351
@ tu lazy val Function0_apply : Symbol = Function0 .requiredMethod(nme.apply)
1316
- @ tu lazy val ContextFunction0_apply : Symbol = ContextFunction0 .requiredMethod(nme.apply)
1317
1352
1318
- @ tu lazy val Function0 : Symbol = FunctionClass (0 )
1319
- @ tu lazy val Function1 : Symbol = FunctionClass (1 )
1320
- @ tu lazy val Function2 : Symbol = FunctionClass (2 )
1321
- @ tu lazy val ContextFunction0 : Symbol = FunctionClass (0 , isContextual = true )
1353
+ @ tu lazy val Function0 : Symbol = FunctionSymbol (0 )
1354
+ @ tu lazy val Function1 : Symbol = FunctionSymbol (1 )
1355
+ @ tu lazy val Function2 : Symbol = FunctionSymbol (2 )
1356
+ @ tu lazy val ContextFunction0 : Symbol = FunctionSymbol (0 , isContextual = true )
1322
1357
1323
- def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false )(using Context ): TypeRef =
1324
- FunctionClass (n, isContextual && ! ctx.erasedTypes, isErased).typeRef
1358
+ def FunctionType (n : Int , isContextual : Boolean = false , isErased : Boolean = false , isImpure : Boolean = false )(using Context ): TypeRef =
1359
+ FunctionSymbol (n, isContextual && ! ctx.erasedTypes, isErased, isImpure ).typeRef
1325
1360
1326
1361
lazy val PolyFunctionClass = requiredClass(" scala.PolyFunction" )
1327
1362
def PolyFunctionType = PolyFunctionClass .typeRef
@@ -1363,6 +1398,10 @@ class Definitions {
1363
1398
*/
1364
1399
def isFunctionClass (cls : Symbol ): Boolean = scalaClassName(cls).isFunction
1365
1400
1401
+ /** Is a function class, or an impure function type alias */
1402
+ def isFunctionSymbol (sym : Symbol ): Boolean =
1403
+ sym.isType && (sym.owner eq ScalaPackageClass ) && sym.name.isFunction
1404
+
1366
1405
/** Is a function class where
1367
1406
* - FunctionN for N >= 0 and N != XXL
1368
1407
*/
@@ -1569,7 +1608,7 @@ class Definitions {
1569
1608
1570
1609
def isSpecializableFunction (cls : ClassSymbol , paramTypes : List [Type ], retType : Type )(using Context ): Boolean =
1571
1610
paramTypes.length <= 2
1572
- && (cls.derivesFrom(FunctionClass (paramTypes.length)) || isByNameFunctionClass(cls))
1611
+ && (cls.derivesFrom(FunctionSymbol (paramTypes.length)) || isByNameFunctionClass(cls))
1573
1612
&& isSpecializableFunctionSAM(paramTypes, retType)
1574
1613
1575
1614
/** If the Single Abstract Method of a Function class has this type, is it specializable? */
0 commit comments