@@ -10,6 +10,7 @@ import MegaPhase._
10
10
import Types ._ , Contexts ._ , Flags ._ , DenotTransformers ._
11
11
import Symbols ._ , StdNames ._ , Trees ._
12
12
import util .Property
13
+ import Constants .Constant
13
14
import Flags .MethodOrLazy
14
15
15
16
object DropBreaks :
@@ -98,26 +99,6 @@ class DropBreaks extends MiniPhase:
98
99
None
99
100
end BreakBoundary
100
101
101
- private object BreakThrow :
102
-
103
- /** `(local, arg)` provided `tree` matches inlined
104
- *
105
- * val Label_this: ... = local
106
- * throw new Break[...](Label_this, arg)
107
- */
108
- def unapply (tree : Tree )(using Context ): Option [(Symbol , Tree )] = tree match
109
- case Inlined (_,
110
- (vd @ ValDef (label_this1, _, id : Ident )):: Nil ,
111
- Apply (throww, Apply (constr, Inlined (_, _, Ident (label_this2)) :: arg :: Nil ) :: Nil ))
112
- if throww.symbol == defn.throwMethod
113
- && label_this1 == nme.Label_this && label_this2 == nme.Label_this
114
- && id.symbol.name == nme.local
115
- && constr.symbol.isClassConstructor && constr.symbol.owner == defn.BreakClass =>
116
- Some ((id.symbol, arg))
117
- case _ =>
118
- None
119
- end BreakThrow
120
-
121
102
/** The LabelUsage data associated with `lbl` in the current context */
122
103
private def labelUsage (lbl : Symbol )(using Context ): Option [LabelUsage ] =
123
104
for
@@ -166,13 +147,29 @@ class DropBreaks extends MiniPhase:
166
147
case _ =>
167
148
tree
168
149
169
- /** Rewrite a BreakThrow
150
+ private def isBreak (sym : Symbol )(using Context ): Boolean =
151
+ sym.name == nme.apply && sym.owner == defn.breakModule.moduleClass
152
+
153
+ private def transformBreak (tree : Tree , arg : Tree , lbl : Symbol )(using Context ): Tree =
154
+ report.log(i " transform break $tree/ $arg/ $lbl" )
155
+ labelUsage(lbl) match
156
+ case Some (uses : LabelUsage )
157
+ if uses.enclMeth == ctx.owner.enclosingMethod
158
+ && ! ctx.property(LabelsShadowedByTry ).getOrElse(Set .empty).contains(lbl)
159
+ =>
160
+ uses.otherRefs -= 1
161
+ uses.returnRefs += 1
162
+ Return (arg, ref(uses.goto)).withSpan(arg.span)
163
+ case _ =>
164
+ tree
165
+
166
+
167
+ /** Rewrite a break call
170
168
*
171
- * val Label_this: ... = local
172
- * throw new Break[...](Label_this, arg)
169
+ * break.apply[...](value)(using lbl)
173
170
*
174
- * where `local ` is defined in the current method and is not included in
175
- * LabeldShowedByTry to
171
+ * where `lbl ` is a label defined in the current method and is not included in
172
+ * LabelsShadowedByTry to
176
173
*
177
174
* return[target] arg
178
175
*
@@ -181,22 +178,12 @@ class DropBreaks extends MiniPhase:
181
178
* and the non-local refcount is decreased, since `local` the `Label_this`
182
179
* binding containing `local` is dropped.
183
180
*/
184
- override def transformInlined (tree : Inlined )(using Context ): Tree = tree match
185
- case BreakThrow (lbl, arg) =>
186
- report.log(i " trans inlined $arg, ${arg.source}, ${ctx.outer.source}, ${tree.source}" )
187
- labelUsage(lbl) match
188
- case Some (uses : LabelUsage )
189
- if uses.enclMeth == ctx.owner.enclosingMethod
190
- && ! ctx.property(LabelsShadowedByTry ).getOrElse(Set .empty).contains(lbl)
191
- =>
192
- uses.otherRefs -= 1
193
- uses.returnRefs += 1
194
- cpy.Inlined (tree)(tree.call, Nil ,
195
- inContext(ctx.withSource(tree.expansion.source)) {
196
- Return (arg, ref(uses.goto)).withSpan(arg.span)
197
- })
198
- case _ =>
199
- tree
181
+ override def transformApply (tree : Apply )(using Context ): Tree = tree match
182
+ case Apply (Apply (fn, args), (id : Ident ) :: Nil ) if isBreak(fn.symbol) =>
183
+ val arg = (args : @ unchecked) match
184
+ case arg :: Nil => arg
185
+ case Nil => Literal (Constant (())).withSpan(tree.span)
186
+ transformBreak(tree, arg, id.symbol)
200
187
case _ =>
201
188
tree
202
189
0 commit comments