@@ -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,54 @@ 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)
1286- 
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" 
1291- 
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
1314+  end  FunType 
1315+ 
1316+  private  def  funTypeIdx (isContextual : Boolean , isErased : Boolean , isImpure : Boolean ):  Int  = 
1317+  (if  isContextual then  1  else  0 )
1318+  +  (if  isErased then  2  else  0 )
1319+  +  (if  isImpure then  4  else  0 )
1320+ 
1321+  private  val  funTypeArray :  IArray [FunType ] = 
1322+  val  arr  =  Array .ofDim[FunType ](8 )
1323+  val  choices  =  List (false , true )
1324+  for  contxt <-  choices; erasd <-  choices; impure <-  choices do 
1325+  var  str  =  " Function" 
1326+  if  contxt then  str =  " Context" +  str
1327+  if  erasd then  str =  " Erased" +  str
1328+  if  impure then  str =  " Impure" +  str
1329+  arr(funTypeIdx(contxt, erasd, impure)) =  FunType (" scala." +  str)
1330+  IArray .unsafeFromArray(arr)
1331+ 
1332+  def  FunctionSymbol (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false , isImpure : Boolean  =  false )(using  Context ):  Symbol  = 
1333+  funTypeArray(funTypeIdx(isContextual, isErased, isImpure))(n).symbol
12981334
12991335 @ tu lazy  val  Function0_apply :  Symbol  =  Function0 .requiredMethod(nme.apply)
13001336
1301-  @ tu lazy  val  Function0 :  Symbol  =  FunctionClass (0 )
1302-  @ tu lazy  val  Function1 :  Symbol  =  FunctionClass (1 )
1303-  @ tu lazy  val  Function2 :  Symbol  =  FunctionClass (2 )
1337+  @ tu lazy  val  Function0 :  Symbol  =  FunctionSymbol (0 )
1338+  @ tu lazy  val  Function1 :  Symbol  =  FunctionSymbol (1 )
1339+  @ tu lazy  val  Function2 :  Symbol  =  FunctionSymbol (2 )
13041340
1305-  def  FunctionType (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false )(using  Context ):  TypeRef  = 
1306-  FunctionClass (n, isContextual &&  ! ctx.erasedTypes, isErased).typeRef
1341+  def  FunctionType (n : Int , isContextual : Boolean  =  false , isErased : Boolean  =  false ,  isImpure :  Boolean   =   false )(using  Context ):  TypeRef  = 
1342+  FunctionSymbol (n, isContextual &&  ! ctx.erasedTypes, isErased, isImpure ).typeRef
13071343
13081344 lazy  val  PolyFunctionClass  =  requiredClass(" scala.PolyFunction" 
13091345 def  PolyFunctionType  =  PolyFunctionClass .typeRef
@@ -1550,7 +1586,7 @@ class Definitions {
15501586 new  PerRun (Function2SpecializedReturnTypes .map(_.symbol))
15511587
15521588 def  isSpecializableFunction (cls : ClassSymbol , paramTypes : List [Type ], retType : Type )(using  Context ):  Boolean  = 
1553-  paramTypes.length <=  2  &&  cls.derivesFrom(FunctionClass (paramTypes.length))
1589+  paramTypes.length <=  2  &&  cls.derivesFrom(FunctionSymbol (paramTypes.length))
15541590 &&  isSpecializableFunctionSAM(paramTypes, retType)
15551591
15561592 /**  If the Single Abstract Method of a Function class has this type, is it specializable? */  
0 commit comments