@@ -56,8 +56,47 @@ class ExpandSAMs extends MiniPhase {
56
56
tree
57
57
}
58
58
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
+ */
59
98
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. */
61
100
object PartialFunctionRHS {
62
101
def unapply (tree : Tree ): Option [Match ] = tree match {
63
102
case Block (Nil , expr) => unapply(expr)
@@ -71,15 +110,18 @@ class ExpandSAMs extends MiniPhase {
71
110
case PartialFunctionRHS (pf) =>
72
111
val anonSym = anon.symbol
73
112
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
+
74
116
def overrideSym (sym : Symbol ) = sym.copy(
75
- owner = anonSym.owner ,
76
- flags = Synthetic | Method | Final ,
117
+ owner = pfSym ,
118
+ flags = Synthetic | Method | Final | Override ,
77
119
info = tpe.memberInfo(sym),
78
- coord = tree.pos).asTerm
120
+ coord = tree.pos).asTerm.entered
79
121
val isDefinedAtFn = overrideSym(defn.PartialFunction_isDefinedAt )
80
122
val applyOrElseFn = overrideSym(defn.PartialFunction_applyOrElse )
81
123
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 ) = {
83
125
val selector = tree.selector
84
126
val selectorTpe = selector.tpe.widen
85
127
val defaultSym = ctx.newSymbol(pfParam.owner, nme.WILDCARD , Synthetic , selectorTpe)
@@ -96,7 +138,7 @@ class ExpandSAMs extends MiniPhase {
96
138
// And we need to update all references to 'param'
97
139
}
98
140
99
- def isDefinedAtRhs (paramRefss : List [List [Tree ]]) = {
141
+ def isDefinedAtRhs (paramRefss : List [List [Tree ]])( implicit ctx : Context ) = {
100
142
val tru = Literal (Constant (true ))
101
143
def translateCase (cdef : CaseDef ) =
102
144
cpy.CaseDef (cdef)(body = tru).changeOwner(anonSym, isDefinedAtFn)
@@ -105,20 +147,19 @@ class ExpandSAMs extends MiniPhase {
105
147
translateMatch(pf, paramRef.symbol, pf.cases.map(translateCase), defaultValue)
106
148
}
107
149
108
- def applyOrElseRhs (paramRefss : List [List [Tree ]]) = {
150
+ def applyOrElseRhs (paramRefss : List [List [Tree ]])( implicit ctx : Context ) = {
109
151
val List (paramRef, defaultRef) = paramRefss.head
110
152
def translateCase (cdef : CaseDef ) =
111
153
cdef.changeOwner(anonSym, applyOrElseFn)
112
154
val defaultValue = defaultRef.select(nme.apply).appliedTo(paramRef)
113
155
translateMatch(pf, paramRef.symbol, pf.cases.map(translateCase), defaultValue)
114
156
}
115
157
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 ))
122
163
123
164
case _ =>
124
165
val found = tpe.baseType(defn.FunctionClass (1 ))
0 commit comments