Skip to content

Commit 2e3c4cf

Browse files
committed
Revert "Suppress returns that cross different stack sizes."
This reverts commit 04e7bc1.
1 parent fdad63e commit 2e3c4cf

File tree

4 files changed

+52
-63
lines changed

4 files changed

+52
-63
lines changed

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

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ object DropBreaks:
3838
* - the throw and the boundary are in the same method, and
3939
* - there is no try expression inside the boundary that encloses the throw.
4040
*/
41-
class DropBreaks extends MiniPhase, RecordStackChange:
41+
class DropBreaks extends MiniPhase:
4242
import DropBreaks.*
4343

4444
import tpd._
@@ -158,12 +158,6 @@ class DropBreaks extends MiniPhase, RecordStackChange:
158158
ctx.fresh.setProperty(ShadowedLabels, setSoFar ++ usesMap.keysIterator)
159159
case _ => ctx
160160

161-
/** Need to suppress labeled returns if the stack can change between
162-
* source and target of the jump
163-
*/
164-
protected def stackChange(using Context) =
165-
ctx // if enclosingBoundaries == 0 then ctx else shadowLabels
166-
167161
/** Need to suppress labeled returns if there is an intervening try
168162
*/
169163
override def prepareForTry(tree: Try)(using Context): Context =
@@ -172,18 +166,13 @@ class DropBreaks extends MiniPhase, RecordStackChange:
172166
case LabelTry(_, _) => ctx
173167
case _ => shadowLabels
174168

175-
override def prepareForApply(tree: Apply)(using Context): Context =
176-
if enclosingBoundaries == 0 then ctx
177-
else tree match
178-
case Break(_, _) => ctx
179-
case _ => stackChange
180-
181169
override def prepareForValDef(tree: ValDef)(using Context): Context =
182-
if tree.symbol.is(Lazy) && tree.symbol.owner == ctx.owner.enclosingMethod then shadowLabels
170+
if enclosingBoundaries != 0
171+
&& tree.symbol.is(Lazy)
172+
&& tree.symbol.owner == ctx.owner.enclosingMethod
173+
then shadowLabels // RHS be converted to a lambda
183174
else ctx
184175

185-
// other stack changing operations are handled in RecordStackChange
186-
187176
/** If `tree` is a BreakBoundary, transform it as follows:
188177
* - Wrap it in a labeled block if its label has local uses
189178
* - Drop the try/catch if its label has no other uses
@@ -203,7 +192,27 @@ class DropBreaks extends MiniPhase, RecordStackChange:
203192
case _ =>
204193
tree
205194

206-
/** Rewrite a break with argument `arg` and label `lbl`
195+
private def isBreak(sym: Symbol)(using Context): Boolean =
196+
sym.name == nme.apply && sym.owner == defn.breakModule.moduleClass
197+
198+
private def transformBreak(tree: Tree, arg: Tree, lbl: Symbol)(using Context): Tree =
199+
report.log(i"transform break $tree/$arg/$lbl")
200+
labelUsage(lbl) match
201+
case Some(uses: LabelUsage)
202+
if uses.enclMeth == ctx.owner.enclosingMethod
203+
&& !ctx.property(ShadowedLabels).getOrElse(Set.empty).contains(lbl)
204+
=>
205+
uses.otherRefs -= 1
206+
uses.returnRefs += 1
207+
Return(arg, ref(uses.goto)).withSpan(arg.span)
208+
case _ =>
209+
tree
210+
211+
212+
/** Rewrite a break call
213+
*
214+
* break.apply[...](value)(using lbl)
215+
*
207216
* where `lbl` is a label defined in the current method and is not included in
208217
* ShadowedLabels to
209218
*

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import core.DenotTransformers._
66
import core.Symbols._
77
import core.Contexts._
88
import core.Types._
9-
import core.Decorators._
109
import core.Flags._
10+
import core.Decorators._
1111
import core.NameKinds.LiftedTreeName
1212
import NonLocalReturns._
1313
import util.Store
@@ -27,7 +27,7 @@ import util.Store
2727
* after an exception, so the fact that values on the stack are 'lost' does not matter
2828
* (copied from https://github.com/scala/scala/pull/922).
2929
*/
30-
class LiftTry extends MiniPhase, IdentityDenotTransformer, RecordStackChange { thisPhase =>
30+
class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase =>
3131
import ast.tpd._
3232

3333
override def phaseName: String = LiftTry.name
@@ -40,14 +40,35 @@ class LiftTry extends MiniPhase, IdentityDenotTransformer, RecordStackChange { t
4040
override def initContext(ctx: FreshContext): Unit =
4141
NeedLift = ctx.addLocation(false)
4242

43-
private def liftingCtx(p: Boolean)(using Context): Context =
43+
private def liftingCtx(p: Boolean)(using Context) =
4444
if (needLift == p) ctx else ctx.fresh.updateStore(NeedLift, p)
4545

46-
protected def stackChange(using Context): Context = liftingCtx(true)
46+
override def prepareForApply(tree: Apply)(using Context): Context =
47+
liftingCtx(true)
4748

4849
override def prepareForDefDef(tree: DefDef)(using Context): Context =
4950
liftingCtx(false)
5051

52+
override def prepareForValDef(tree: ValDef)(using Context): Context =
53+
if !tree.symbol.exists
54+
|| tree.symbol.isSelfSym
55+
|| tree.symbol.owner == ctx.owner.enclosingMethod
56+
&& !tree.symbol.is(Lazy)
57+
// The current implementation wraps initializers of lazy vals in
58+
// calls to an initialize method, which means that a `try` in the
59+
// initializer needs to be lifted. Note that the new scheme proposed
60+
// in #6979 would avoid this.
61+
then ctx
62+
else liftingCtx(true)
63+
64+
override def prepareForAssign(tree: Assign)(using Context): Context =
65+
if (tree.lhs.symbol.maybeOwner == ctx.owner.enclosingMethod) ctx
66+
else liftingCtx(true)
67+
68+
override def prepareForReturn(tree: Return)(using Context): Context =
69+
if (!isNonLocalReturn(tree)) ctx
70+
else liftingCtx(true)
71+
5172
override def prepareForTemplate(tree: Template)(using Context): Context =
5273
liftingCtx(false)
5374

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

Lines changed: 0 additions & 41 deletions
This file was deleted.

tests/run/rescue-boundary.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ object lib:
55
extension [T](op: => T) inline def rescue (fallback: => T) =
66
try op
77
catch
8-
case ex: boundary.Break => throw ex
8+
case ex: boundary.Break[_] => throw ex
99
case NonFatal(_) => fallback
1010

1111
extension [T, E <: Throwable](op: => T) inline def rescue (fallback: PartialFunction[E, T]) =

0 commit comments

Comments
 (0)