@@ -8,7 +8,7 @@ import Flags._, Scopes._, Decorators._, NameOps._, Periods._, NullOpsDecorator._
88import  unpickleScala2 .Scala2Unpickler .ensureConstructor 
99import  scala .collection .mutable 
1010import  collection .mutable 
11- import  Denotations .SingleDenotation 
11+ import  Denotations .{ SingleDenotation ,  staticRef } 
1212import  util .{SimpleIdentityMap , SourceFile , NoSource }
1313import  typer .ImportInfo .RootRef 
1414import  Comments .CommentsContext 
@@ -86,7 +86,7 @@ class Definitions {
8686 * 
8787 * FunctionN traits follow this template: 
8888 * 
89-  * trait FunctionN[T0,...T{N-1}, R] extends Object { 
89+  * trait FunctionN[- T0,...- T{N-1}, + R] extends Object { 
9090 * def apply($x0: T0, ..., $x{N_1}: T{N-1}): R 
9191 * } 
9292 * 
@@ -96,46 +96,65 @@ class Definitions {
9696 * 
9797 * ContextFunctionN traits follow this template: 
9898 * 
99-  * trait ContextFunctionN[T0,...,T{N-1}, R] extends Object { 
99+  * trait ContextFunctionN[- T0,...,- T{N-1}, + R] extends Object { 
100100 * def apply(using $x0: T0, ..., $x{N_1}: T{N-1}): R 
101101 * } 
102102 * 
103103 * ErasedFunctionN traits follow this template: 
104104 * 
105-  * trait ErasedFunctionN[T0,...,T{N-1}, R] extends Object { 
105+  * trait ErasedFunctionN[- T0,...,- T{N-1}, + R] extends Object { 
106106 * def apply(erased $x0: T0, ..., $x{N_1}: T{N-1}): R 
107107 * } 
108108 * 
109109 * ErasedContextFunctionN traits follow this template: 
110110 * 
111-  * trait ErasedContextFunctionN[T0,...,T{N-1}, R] extends Object { 
111+  * trait ErasedContextFunctionN[- T0,...,- T{N-1}, + R] extends Object { 
112112 * def apply(using erased $x0: T0, ..., $x{N_1}: T{N-1}): R 
113113 * } 
114114 * 
115115 * ErasedFunctionN and ErasedContextFunctionN erase to Function0. 
116+  * 
117+  * EffXYZFunctionN afollow this template: 
118+  * 
119+  * type EffXYZFunctionN[-T0,...,-T{N-1}, +R] = {*} XYZFunctionN[T0,...,T{N-1}, R] 
116120 */  
117-  def  newFunctionNTrait (name : TypeName ):  ClassSymbol  =  {
121+  private  def  newFunctionNType (name : TypeName ):  Symbol  =  {
122+  val  impure  =  name.startsWith(" Impure" 
118123 val  completer  =  new  LazyType  {
119124 def  complete (denot : SymDenotation )(using  Context ):  Unit  =  {
120-  val  cls  =  denot.asClass.classSymbol
121-  val  decls  =  newScope
122125 val  arity  =  name.functionArity
123-  val  paramNamePrefix  =  tpnme.scala ++  str.NAME_JOIN  ++  name ++  str.EXPAND_SEPARATOR 
124-  val  argParamRefs  =  List .tabulate(arity) { i => 
125-  enterTypeParam(cls, paramNamePrefix ++  " T" ++  (i +  1 ).toString, Contravariant , decls).typeRef
126-  }
127-  val  resParamRef  =  enterTypeParam(cls, paramNamePrefix ++  " R" Covariant , decls).typeRef
128-  val  methodType  =  MethodType .companion(
129-  isContextual =  name.isContextFunction,
130-  isImplicit =  false ,
131-  isErased =  name.isErasedFunction)
132-  decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
133-  denot.info = 
134-  ClassInfo (ScalaPackageClass .thisType, cls, ObjectType  ::  Nil , decls)
126+  if  impure then 
127+  val  argParamNames  =  List .tabulate(arity)(tpnme.syntheticTypeParamName)
128+  val  argVariances  =  List .fill(arity)(Contravariant )
129+  val  underlyingName  =  name.asSimpleName.drop(6 )
130+  val  underlyingClass  =  ScalaPackageVal .requiredClass(underlyingName)
131+  denot.info =  TypeAlias (
132+  HKTypeLambda (argParamNames :+  " R" :+  Covariant )(
133+  tl =>  List .fill(arity +  1 )(TypeBounds .empty),
134+  tl =>  CapturingType (underlyingClass.typeRef.appliedTo(tl.paramRefs),
135+  CaptureSet .universal, boxed =  false )
136+  ))
137+  else 
138+  val  cls  =  denot.asClass.classSymbol
139+  val  decls  =  newScope
140+  val  paramNamePrefix  =  tpnme.scala ++  str.NAME_JOIN  ++  name ++  str.EXPAND_SEPARATOR 
141+  val  argParamRefs  =  List .tabulate(arity) { i => 
142+  enterTypeParam(cls, paramNamePrefix ++  " T" ++  (i +  1 ).toString, Contravariant , decls).typeRef
143+  }
144+  val  resParamRef  =  enterTypeParam(cls, paramNamePrefix ++  " R" Covariant , decls).typeRef
145+  val  methodType  =  MethodType .companion(
146+  isContextual =  name.isContextFunction,
147+  isImplicit =  false ,
148+  isErased =  name.isErasedFunction)
149+  decls.enter(newMethod(cls, nme.apply, methodType(argParamRefs, resParamRef), Deferred ))
150+  denot.info = 
151+  ClassInfo (ScalaPackageClass .thisType, cls, ObjectType  ::  Nil , decls)
135152 }
136153 }
137-  val  flags  =  Trait  |  NoInits 
138-  newPermanentClassSymbol(ScalaPackageClass , name, flags, completer)
154+  if  impure then 
155+  newPermanentSymbol(ScalaPackageClass , name, EmptyFlags , completer)
156+  else 
157+  newPermanentClassSymbol(ScalaPackageClass , name, Trait  |  NoInits , completer)
139158 }
140159
141160 private  def  newMethod (cls : ClassSymbol , name : TermName , info : Type , flags : FlagSet  =  EmptyFlags ):  TermSymbol  = 
@@ -209,7 +228,7 @@ class Definitions {
209228 val  cls  =  ScalaPackageVal .moduleClass.asClass
210229 cls.info.decls.openForMutations.useSynthesizer(
211230 name => 
212-  if  (name.isTypeName &&  name.isSyntheticFunction) newFunctionNTrait (name.asTypeName)
231+  if  (name.isTypeName &&  name.isSyntheticFunction) newFunctionNType (name.asTypeName)
213232 else  NoSymbol )
214233 cls
215234 }
@@ -1273,37 +1292,55 @@ class Definitions {
12731292
12741293 @ tu lazy  val  TupleType :  Array [TypeRef ] =  mkArityArray(" scala.Tuple" MaxTupleArity , 1 )
12751294
1295+  /**  Cached function types of arbitary arities. 
1296+  * Function types are created on demand with newFunctionNTrait, which is 
1297+  * called from a synthesizer installed in ScalaPackageClass. 
1298+  */  
12761299 private  class  FunType (prefix : String ): 
12771300 private  var  classRefs :  Array [TypeRef ] =  new  Array (22 )
1301+ 
12781302 def  apply (n : Int ):  TypeRef  = 
12791303 while  n >=  classRefs.length do 
12801304 val  classRefs1  =  new  Array [TypeRef ](classRefs.length *  2 )
12811305 Array .copy(classRefs, 0 , classRefs1, 0 , classRefs.length)
12821306 classRefs =  classRefs1
1307+  val  funName  =  prefix +  n.toString
12831308 if  classRefs(n) ==  null  then 
1284-  classRefs(n) =  requiredClassRef(prefix +  n.toString)
1309+  classRefs(n) = 
1310+  if  prefix.startsWith(" Impure" 
1311+  then  staticRef(funName.toTypeName).symbol.typeRef
1312+  else  requiredClassRef(funName)
12851313 classRefs(n)
1314+  end  FunType 
1315+ 
1316+  private  val  (funTypeCache, funTypeArray) = 
1317+  val  funTypeCache  =  mutable.Map [String , FunType ]()
1318+  val  funTypeArray  =  Array .ofDim[FunType ](2 , 2 , 2 )
1319+ 
1320+  for  contxt <-  0  to 1 ; erasd <-  0  to 1 ; impure <-  0  to 1  do 
1321+  var  str  =  " Function" 
1322+  if  contxt ==  1  then  str =  " Context" +  str
1323+  if  erasd ==  1  then  str =  " Erased" +  str
1324+  if  impure ==  1  then  str =  " Impure" +  str
1325+  val  funType  =  FunType (" scala." +  str)
1326+  funTypeCache(str) =  funType
1327+  funTypeArray(contxt)(erasd)(impure) =  funType
12861328
1287-  private  val  erasedContextFunType  =  FunType (" scala.ErasedContextFunction" 
1288-  private  val  contextFunType  =  FunType (" scala.ContextFunction" 
1289-  private  val  erasedFunType  =  FunType (" scala.ErasedFunction" 
1290-  private  val  funType  =  FunType (" scala.Function" 
1329+  (funTypeCache : collection.Map [String , FunType ], IArray .unsafeFromArray(funTypeArray))
1330+  end val 
12911331
1292-  def  FunctionClass (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false )(using  Context ):  Symbol  = 
1293-  ( if  isContextual &&  isErased then  erasedContextFunType(n)
1294-  else  if  isContextual then  contextFunType(n)
1295-  else  if  isErased then  erasedFunType(n)
1296-  else  funType(n)
1297-  ).symbol.asClass
1332+  def  FunctionSymbol (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false , isEffectful : Boolean  =  false )(using  Context ):  Symbol  = 
1333+  def  ord (b : Boolean ):  Int  =  if  b then  1  else  0 
1334+  funTypeArray(ord(isContextual))(ord(isErased))(ord(isEffectful))(n).symbol
12981335
12991336 @ tu lazy  val  Function0_apply :  Symbol  =  Function0 .requiredMethod(nme.apply)
13001337
1301-  @ tu lazy  val  Function0 :  Symbol  =  FunctionClass (0 )
1302-  @ tu lazy  val  Function1 :  Symbol  =  FunctionClass (1 )
1303-  @ tu lazy  val  Function2 :  Symbol  =  FunctionClass (2 )
1338+  @ tu lazy  val  Function0 :  Symbol  =  FunctionSymbol (0 )
1339+  @ tu lazy  val  Function1 :  Symbol  =  FunctionSymbol (1 )
1340+  @ tu lazy  val  Function2 :  Symbol  =  FunctionSymbol (2 )
13041341
1305-  def  FunctionType (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false )(using  Context ):  TypeRef  = 
1306-  FunctionClass (n, isContextual &&  ! ctx.erasedTypes, isErased).typeRef
1342+  def  FunctionType (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false ,  isEffectful :  Boolean   =   false )(using  Context ):  TypeRef  = 
1343+  FunctionSymbol (n, isContextual &&  ! ctx.erasedTypes, isErased, isEffectful ).typeRef
13071344
13081345 lazy  val  PolyFunctionClass  =  requiredClass(" scala.PolyFunction" 
13091346 def  PolyFunctionType  =  PolyFunctionClass .typeRef
@@ -1550,7 +1587,7 @@ class Definitions {
15501587 new  PerRun (Function2SpecializedReturnTypes .map(_.symbol))
15511588
15521589 def  isSpecializableFunction (cls : ClassSymbol , paramTypes : List [Type ], retType : Type )(using  Context ):  Boolean  = 
1553-  paramTypes.length <=  2  &&  cls.derivesFrom(FunctionClass (paramTypes.length))
1590+  paramTypes.length <=  2  &&  cls.derivesFrom(FunctionSymbol (paramTypes.length))
15541591 &&  isSpecializableFunctionSAM(paramTypes, retType)
15551592
15561593 /**  If the Single Abstract Method of a Function class has this type, is it specializable? */  
0 commit comments