Skip to content

Commit 562c72e

Browse files
committed
Use extension Label.break to inline prefix
1 parent 964bccf commit 562c72e

File tree

3 files changed

+14
-21
lines changed

3 files changed

+14
-21
lines changed

compiler/src/dotty/tools/dotc/transform/DropBreaks.scala

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,11 @@ class DropBreaks extends MiniPhase:
102102

103103
/** `(local, arg)` provided `tree` matches inlined
104104
*
105-
* val Label_this: ... = local
106-
* throw new Break[...](Label_this, arg)
105+
* throw new Break[...](local, arg): Nothing
107106
*/
108107
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))
108+
case Apply(throww, Apply(constr, Inlined(_, _, id: Ident) :: arg :: Nil) :: Nil)
112109
if throww.symbol == defn.throwMethod
113-
&& label_this1 == nme.Label_this && label_this2 == nme.Label_this
114110
&& id.symbol.name == nme.local
115111
&& constr.symbol.isClassConstructor && constr.symbol.owner == defn.BreakClass =>
116112
Some((id.symbol, arg))
@@ -168,20 +164,18 @@ class DropBreaks extends MiniPhase:
168164

169165
/** Rewrite a BreakThrow
170166
*
171-
* val Label_this: ... = local
172-
* throw new Break[...](Label_this, arg)
167+
* throw new Break[...](local, arg)
173168
*
174169
* where `local` is defined in the current method and is not included in
175-
* LabeldShowedByTry to
170+
* LabeledShowedByTry to
176171
*
177172
* return[target] arg
178173
*
179174
* where `target` is the `goto` return label associated with `local`.
180175
* Adjust associated ref counts accordingly. The local refcount is increased
181-
* and the non-local refcount is decreased, since `local` the `Label_this`
182-
* binding containing `local` is dropped.
176+
* and the non-local refcount is decreased.
183177
*/
184-
override def transformInlined(tree: Inlined)(using Context): Tree = tree match
178+
override def transformApply(tree: Apply)(using Context): Tree = tree match
185179
case BreakThrow(lbl, arg) =>
186180
report.log(i"trans inlined $arg, ${arg.source}, ${ctx.outer.source}, ${tree.source}")
187181
labelUsage(lbl) match
@@ -191,10 +185,7 @@ class DropBreaks extends MiniPhase:
191185
=>
192186
uses.otherRefs -= 1
193187
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-
})
188+
Return(arg, ref(uses.goto)).withSpan(arg.span)
198189
case _ =>
199190
tree
200191
case _ =>

library/src/scala/util/boundary.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import control.ControlException
1212
* The `Break` exception class extends `ControlException` which is a regular
1313
* `RuntimeException`, optimized so that stack trace generation is suppressed.
1414
* - Better performance: breaks to enclosing scopes in the same method can
15-
* be rwritten to jumps.
15+
* be rewritten to jumps.
1616
*/
1717
object boundary:
1818

@@ -23,8 +23,10 @@ object boundary:
2323

2424
/** Labels are targets indicating which boundary will be exited by a `break`.
2525
*/
26-
class Label[T]:
27-
transparent inline def break(value: T): Nothing = throw Break(this, value)
26+
class Label[T]
27+
28+
extension [T](label: Label[T])
29+
inline def break(inline value: T): Nothing = throw Break(label, value)
2830

2931
/** Run `body` with freshly generated label as implicit argument. Catch any
3032
* breaks associated with that label and return their results instead of

library/src/scala/util/break.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ object break:
88
/** Abort current computation and instead return `value` as the value of
99
* the enclosing `boundary` call that created `label`.
1010
*/
11-
transparent inline def apply[T](value: T)(using l: boundary.Label[T]): Nothing =
11+
inline def apply[T](value: T)(using inline l: boundary.Label[T]): Nothing =
1212
l.break(value)
1313

1414
/** Abort current computation and instead continue after the `boundary` call that
1515
* created `label`.
1616
*/
17-
transparent inline def apply()(using l: boundary.Label[Unit]): Nothing =
17+
inline def apply()(using inline l: boundary.Label[Unit]): Nothing =
1818
apply(())
1919

2020
end break

0 commit comments

Comments
 (0)