@@ -10,6 +10,7 @@ import MegaPhase._
1010import Types ._ , Contexts ._ , Flags ._ , DenotTransformers ._
1111import Symbols ._ , StdNames ._ , Trees ._
1212import util .Property
13+ import Constants .Constant
1314import Flags .MethodOrLazy
1415
1516object DropBreaks :
@@ -98,26 +99,6 @@ class DropBreaks extends MiniPhase:
9899 None
99100 end BreakBoundary
100101
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-
121102 /** The LabelUsage data associated with `lbl` in the current context */
122103 private def labelUsage (lbl : Symbol )(using Context ): Option [LabelUsage ] =
123104 for
@@ -166,13 +147,29 @@ class DropBreaks extends MiniPhase:
166147 case _ =>
167148 tree
168149
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
170168 *
171- * val Label_this: ... = local
172- * throw new Break[...](Label_this, arg)
169+ * break.apply[...](value)(using lbl)
173170 *
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
176173 *
177174 * return[target] arg
178175 *
@@ -181,22 +178,12 @@ class DropBreaks extends MiniPhase:
181178 * and the non-local refcount is decreased, since `local` the `Label_this`
182179 * binding containing `local` is dropped.
183180 */
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)
200187 case _ =>
201188 tree
202189
0 commit comments