@@ -56,8 +56,47 @@ class ExpandSAMs extends MiniPhase {
5656 tree
5757 }
5858
59+ /** A partial function literal:
60+ *
61+ * ```
62+ * val x: PartialFunction[A, B] = { case C1 => E1; ...; case Cn => En }
63+ * ```
64+ *
65+ * which desugars to:
66+ *
67+ * ```
68+ * val x: PartialFunction[A, B] = {
69+ * def $anonfun(x: A): B = x match { case C1 => E1; ...; case Cn => En }
70+ * closure($anonfun: PartialFunction[A, B])
71+ * }
72+ * ```
73+ *
74+ * is expanded to an anomymous class:
75+ *
76+ * ```
77+ * val x: PartialFunction[A, B] = {
78+ * class $anon extends AbstractPartialFunction[A, B] {
79+ * final def isDefinedAt(x: A): Boolean = x match {
80+ * case C1 => true
81+ * ...
82+ * case Cn => true
83+ * case _ => false
84+ * }
85+ *
86+ * final def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = x match {
87+ * case C1 => E1
88+ * ...
89+ * case Cn => En
90+ * case _ => default(x)
91+ * }
92+ * }
93+ *
94+ * new $anon
95+ * }
96+ * ```
97+ */
5998 private def toPartialFunction (tree : Block , tpe : Type )(implicit ctx : Context ): Tree = {
60- // / ** An extractor for match, either contained in a block or standalone. */
99+ /** An extractor for match, either contained in a block or standalone. */
61100 object PartialFunctionRHS {
62101 def unapply (tree : Tree ): Option [Match ] = tree match {
63102 case Block (Nil , expr) => unapply(expr)
@@ -71,15 +110,18 @@ class ExpandSAMs extends MiniPhase {
71110 case PartialFunctionRHS (pf) =>
72111 val anonSym = anon.symbol
73112
113+ val parents = List (defn.AbstractPartialFunctionType .appliedTo(tpe.argInfos), defn.SerializableType )
114+ val pfSym = ctx.newNormalizedClassSymbol(anonSym.owner, tpnme.ANON_CLASS , Synthetic | Final , parents, coord = tree.pos)
115+
74116 def overrideSym (sym : Symbol ) = sym.copy(
75- owner = anonSym.owner ,
76- flags = Synthetic | Method | Final ,
117+ owner = pfSym ,
118+ flags = Synthetic | Method | Final | Override ,
77119 info = tpe.memberInfo(sym),
78- coord = tree.pos).asTerm
120+ coord = tree.pos).asTerm.entered
79121 val isDefinedAtFn = overrideSym(defn.PartialFunction_isDefinedAt )
80122 val applyOrElseFn = overrideSym(defn.PartialFunction_applyOrElse )
81123
82- def translateMatch (tree : Match , pfParam : Symbol , cases : List [CaseDef ], defaultValue : Tree ) = {
124+ def translateMatch (tree : Match , pfParam : Symbol , cases : List [CaseDef ], defaultValue : Tree )( implicit ctx : Context ) = {
83125 val selector = tree.selector
84126 val selectorTpe = selector.tpe.widen
85127 val defaultSym = ctx.newSymbol(pfParam.owner, nme.WILDCARD , Synthetic , selectorTpe)
@@ -96,7 +138,7 @@ class ExpandSAMs extends MiniPhase {
96138 // And we need to update all references to 'param'
97139 }
98140
99- def isDefinedAtRhs (paramRefss : List [List [Tree ]]) = {
141+ def isDefinedAtRhs (paramRefss : List [List [Tree ]])( implicit ctx : Context ) = {
100142 val tru = Literal (Constant (true ))
101143 def translateCase (cdef : CaseDef ) =
102144 cpy.CaseDef (cdef)(body = tru).changeOwner(anonSym, isDefinedAtFn)
@@ -105,20 +147,19 @@ class ExpandSAMs extends MiniPhase {
105147 translateMatch(pf, paramRef.symbol, pf.cases.map(translateCase), defaultValue)
106148 }
107149
108- def applyOrElseRhs (paramRefss : List [List [Tree ]]) = {
150+ def applyOrElseRhs (paramRefss : List [List [Tree ]])( implicit ctx : Context ) = {
109151 val List (paramRef, defaultRef) = paramRefss.head
110152 def translateCase (cdef : CaseDef ) =
111153 cdef.changeOwner(anonSym, applyOrElseFn)
112154 val defaultValue = defaultRef.select(nme.apply).appliedTo(paramRef)
113155 translateMatch(pf, paramRef.symbol, pf.cases.map(translateCase), defaultValue)
114156 }
115157
116- val isDefinedAtDef = transformFollowingDeep(DefDef (isDefinedAtFn, isDefinedAtRhs(_)))
117- val applyOrElseDef = transformFollowingDeep(DefDef (applyOrElseFn, applyOrElseRhs(_)))
118-
119- val parents = List (defn.AbstractPartialFunctionType .appliedTo(tpe.argInfos), defn.SerializableType )
120- val anonCls = AnonClass (parents, List (isDefinedAtFn, applyOrElseFn), List (nme.isDefinedAt, nme.applyOrElse))
121- cpy.Block (tree)(List (isDefinedAtDef, applyOrElseDef), anonCls)
158+ val constr = ctx.newConstructor(pfSym, Synthetic , Nil , Nil ).entered
159+ val isDefinedAtDef = transformFollowingDeep(DefDef (isDefinedAtFn, isDefinedAtRhs(_)(ctx.withOwner(isDefinedAtFn))))
160+ val applyOrElseDef = transformFollowingDeep(DefDef (applyOrElseFn, applyOrElseRhs(_)(ctx.withOwner(applyOrElseFn))))
161+ val pfDef = ClassDef (pfSym, DefDef (constr), List (isDefinedAtDef, applyOrElseDef))
162+ cpy.Block (tree)(pfDef :: Nil , New (pfSym.typeRef, Nil ))
122163
123164 case _ =>
124165 val found = tpe.baseType(defn.FunctionClass (1 ))
0 commit comments