@@ -10,14 +10,15 @@ import Names.TypeName
1010
1111import  NullOpsDecorator .* 
1212import  ast .untpd 
13+ import  scala .collection .mutable .ListBuffer 
1314
1415/**  Expand SAM closures that cannot be represented by the JVM as lambdas to anonymous classes.
1516 *  These fall into five categories 
1617 * 
1718 *   1. Partial function closures, we need to generate isDefinedAt and applyOrElse methods for these. 
1819 *   2. Closures implementing non-trait classes 
1920 *   3. Closures implementing classes that inherit from a class other than Object 
20-  *      (a lambda cannot not  be a run-time subtype of such a class) 
21+  *      (a lambda cannot be a run-time subtype of such a class) 
2122 *   4. Closures that implement traits which run initialization code. 
2223 *   5. Closures that get synthesized abstract methods in the transformation pipeline. These methods can be 
2324 *      (1) superaccessors, (2) outer references, (3) accessors for fields. 
@@ -59,7 +60,7 @@ class ExpandSAMs extends MiniPhase:
5960          //  A SAM type is allowed to have type aliases refinements (see
6061          //  SAMType#samParent) which must be converted into type members if
6162          //  the closure is desugared into a class.
62-           val  refinements  =  collection.mutable. ListBuffer [(TypeName , TypeAlias )]() 
63+           val  refinements  =  ListBuffer .empty [(TypeName , TypeAlias )]
6364          def  collectAndStripRefinements (tp : Type ):  Type  =  tp match 
6465            case  RefinedType (parent, name, info : TypeAlias ) => 
6566              val  res  =  collectAndStripRefinements(parent)
@@ -81,34 +82,40 @@ class ExpandSAMs extends MiniPhase:
8182      tree
8283  }
8384
84-   /**  A partial function literal : 
85+   /**  A pattern-matching anonymous function : 
8586   * 
8687   *  ``` 
8788   *  val x: PartialFunction[A, B] = { case C1 => E1; ...; case Cn => En } 
8889   *  ``` 
90+    *  or 
91+    *  ``` 
92+    *  x => e(x) { case C1 => E1; ...; case Cn => En } 
93+    *  ``` 
94+    *  where the expression `e(x)` may be trivially `x` 
8995   * 
9096   *  which desugars to: 
9197   * 
9298   *  ``` 
9399   *  val x: PartialFunction[A, B] = { 
94-    *    def $anonfun(x: A): B = x  match { case C1 => E1; ...; case Cn => En } 
100+    *    def $anonfun(x: A): B = e(x)  match { case C1 => E1; ...; case Cn => En } 
95101   *    closure($anonfun: PartialFunction[A, B]) 
96102   *  } 
97103   *  ``` 
104+    *  where the expression `e(x)` defaults to `x` for a simple block of cases 
98105   * 
99106   *  is expanded to an anonymous class: 
100107   * 
101108   *  ``` 
102109   *  val x: PartialFunction[A, B] = { 
103110   *    class $anon extends AbstractPartialFunction[A, B] { 
104-    *      final def isDefinedAt(x: A): Boolean = x  match { 
111+    *      final def isDefinedAt(x: A): Boolean = e(x)  match { 
105112   *        case C1 => true 
106113   *        ... 
107114   *        case Cn => true 
108115   *        case _  => false 
109116   *      } 
110117   * 
111-    *      final def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = x  match { 
118+    *      final def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = e(x)  match { 
112119   *        case C1 => E1 
113120   *        ... 
114121   *        case Cn => En 
@@ -120,7 +127,7 @@ class ExpandSAMs extends MiniPhase:
120127   *  } 
121128   *  ``` 
122129   */  
123-   private  def  toPartialFunction (tree : Block , tpe : Type )(using  Context ):  Tree  =  { 
130+   private  def  toPartialFunction (tree : Block , tpe : Type )(using  Context ):  Tree  = 
124131    val  closureDef(anon @  DefDef (_, List (List (param)), _, _)) =  tree : @ unchecked
125132
126133    //  The right hand side from which to construct the partial function. This is always a Match.
@@ -146,7 +153,7 @@ class ExpandSAMs extends MiniPhase:
146153      defn.AbstractPartialFunctionClass .typeRef.appliedTo(anonTpe.firstParamTypes.head, anonTpe.resultType),
147154      defn.SerializableType )
148155
149-     AnonClass (anonSym.owner, parents, tree.span) {  pfSym => 
156+     AnonClass (anonSym.owner, parents, tree.span):  pfSym => 
150157      def  overrideSym (sym : Symbol ) =  sym.copy(
151158        owner =  pfSym,
152159        flags =  Synthetic  |  Method  |  Final  |  Override ,
@@ -155,7 +162,8 @@ class ExpandSAMs extends MiniPhase:
155162      val  isDefinedAtFn  =  overrideSym(defn.PartialFunction_isDefinedAt )
156163      val  applyOrElseFn  =  overrideSym(defn.PartialFunction_applyOrElse )
157164
158-       def  translateMatch (tree : Match , pfParam : Symbol , cases : List [CaseDef ], defaultValue : Tree )(using  Context ) =  {
165+       def  translateMatch (owner : Symbol )(pfParam : Symbol , cases : List [CaseDef ], defaultValue : Tree )(using  Context ) = 
166+         val  tree :  Match  =  pfRHS
159167        val  selector  =  tree.selector
160168        val  cases1  =  if  cases.exists(isDefaultCase) then  cases
161169        else 
@@ -165,31 +173,27 @@ class ExpandSAMs extends MiniPhase:
165173          cases :+  defaultCase
166174        cpy.Match (tree)(selector, cases1)
167175          .subst(param.symbol ::  Nil , pfParam ::  Nil )
168-             //  Needed because   a partial function can be written as:
176+             //  Needed because a partial function can be written as:
169177            //  param => param match { case "foo" if foo(param) => param }
170178            //  And we need to update all references to 'param'
171-       } 
179+           .changeOwner(anonSym, owner) 
172180
173-       def  isDefinedAtRhs (paramRefss : List [List [Tree ]])(using  Context ) =  { 
181+       def  isDefinedAtRhs (paramRefss : List [List [Tree ]])(using  Context ) = 
174182        val  tru  =  Literal (Constant (true ))
175-         def  translateCase (cdef : CaseDef ) = 
176-           cpy.CaseDef (cdef)(body =  tru).changeOwner(anonSym, isDefinedAtFn)
183+         def  translateCase (cdef : CaseDef ) =  cpy.CaseDef (cdef)(body =  tru)
177184        val  paramRef  =  paramRefss.head.head
178185        val  defaultValue  =  Literal (Constant (false ))
179-         translateMatch(pfRHS, paramRef.symbol, pfRHS.cases.map(translateCase), defaultValue)
180-       }
186+         translateMatch(isDefinedAtFn)(paramRef.symbol, pfRHS.cases.map(translateCase), defaultValue)
181187
182-       def  applyOrElseRhs (paramRefss : List [List [Tree ]])(using  Context ) =  { 
188+       def  applyOrElseRhs (paramRefss : List [List [Tree ]])(using  Context ) = 
183189        val  List (paramRef, defaultRef) =  paramRefss(1 )
184-         def  translateCase (cdef : CaseDef ) = 
185-           cdef.changeOwner(anonSym, applyOrElseFn)
186190        val  defaultValue  =  defaultRef.select(nme.apply).appliedTo(paramRef)
187-         translateMatch(pfRHS, paramRef.symbol, pfRHS.cases.map(translateCase), defaultValue)
188-       }
191+         translateMatch(applyOrElseFn)(paramRef.symbol, pfRHS.cases, defaultValue)
189192
190-       val  isDefinedAtDef  =  transformFollowingDeep(DefDef (isDefinedAtFn, isDefinedAtRhs(_)(using  ctx.withOwner(isDefinedAtFn))))
191-       val  applyOrElseDef  =  transformFollowingDeep(DefDef (applyOrElseFn, applyOrElseRhs(_)(using  ctx.withOwner(applyOrElseFn))))
193+       val  isDefinedAtDef  =  transformFollowingDeep :
194+         DefDef (isDefinedAtFn, isDefinedAtRhs(_)(using  ctx.withOwner(isDefinedAtFn)))
195+       val  applyOrElseDef  =  transformFollowingDeep :
196+         DefDef (applyOrElseFn, applyOrElseRhs(_)(using  ctx.withOwner(applyOrElseFn)))
192197      List (isDefinedAtDef, applyOrElseDef)
193-     }
194-   }
198+   end  toPartialFunction 
195199end  ExpandSAMs 
0 commit comments