Skip to content

Commit e7961f2

Browse files
committed
Restructure Try node.
Now Try node always has cases as handlers. In case handler is an Ident of type Throwable => T than it's desugared to a CaseDef during parsing.
1 parent be03a4d commit e7961f2

13 files changed

+55
-59
lines changed

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ object Trees {
611611
*
612612
* Match(EmptyTree, <case x: Throwable => $anonfun(x)>)
613613
*/
614-
case class Try[-T >: Untyped] private[ast] (expr: Tree[T], handler: Tree[T], finalizer: Tree[T])
614+
case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])
615615
extends TermTree[T] {
616616
type ThisTree[-T >: Untyped] = Try[T]
617617
}
@@ -1027,9 +1027,9 @@ object Trees {
10271027
case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree
10281028
case _ => finalize(tree, untpd.Return(expr, from))
10291029
}
1030-
def Try(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try = tree match {
1031-
case tree: Try if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree
1032-
case _ => finalize(tree, untpd.Try(expr, handler, finalizer))
1030+
def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = tree match {
1031+
case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree
1032+
case _ => finalize(tree, untpd.Try(expr, cases, finalizer))
10331033
}
10341034
def Throw(tree: Tree)(expr: Tree)(implicit ctx: Context): Throw = tree match {
10351035
case tree: Throw if (expr eq tree.expr) => tree
@@ -1131,8 +1131,8 @@ object Trees {
11311131
Closure(tree: Tree)(env, meth, tpt)
11321132
def CaseDef(tree: CaseDef)(pat: Tree = tree.pat, guard: Tree = tree.guard, body: Tree = tree.body)(implicit ctx: Context): CaseDef =
11331133
CaseDef(tree: Tree)(pat, guard, body)
1134-
def Try(tree: Try)(expr: Tree = tree.expr, handler: Tree = tree.handler, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
1135-
Try(tree: Tree)(expr, handler, finalizer)
1134+
def Try(tree: Try)(expr: Tree = tree.expr, cases: List[CaseDef] = tree.cases, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
1135+
Try(tree: Tree)(expr, cases, finalizer)
11361136
def UnApply(tree: UnApply)(fun: Tree = tree.fun, implicits: List[Tree] = tree.implicits, patterns: List[Tree] = tree.patterns): UnApply =
11371137
UnApply(tree: Tree)(fun, implicits, patterns)
11381138
def ValDef(tree: ValDef)(mods: Modifiers = tree.mods, name: TermName = tree.name, tpt: Tree = tree.tpt, rhs: Tree = tree.rhs): ValDef =
@@ -1184,8 +1184,8 @@ object Trees {
11841184
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
11851185
case Return(expr, from) =>
11861186
cpy.Return(tree)(transform(expr), transformSub(from))
1187-
case Try(block, handler, finalizer) =>
1188-
cpy.Try(tree)(transform(block), transform(handler), transform(finalizer))
1187+
case Try(block, cases, finalizer) =>
1188+
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
11891189
case Throw(expr) =>
11901190
cpy.Throw(tree)(transform(expr))
11911191
case SeqLiteral(elems) =>

src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
112112
def Return(expr: Tree, from: Tree)(implicit ctx: Context): Return =
113113
ta.assignType(untpd.Return(expr, from))
114114

115-
def Try(block: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try =
116-
ta.assignType(untpd.Try(block, handler, finalizer), block, handler)
115+
def Try(block: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try =
116+
ta.assignType(untpd.Try(block, cases, finalizer), block, cases)
117117

118118
def Throw(expr: Tree)(implicit ctx: Context): Throw =
119119
ta.assignType(untpd.Throw(expr))
@@ -456,11 +456,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
456456
override def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return =
457457
ta.assignType(untpd.cpy.Return(tree)(expr, from))
458458

459-
override def Try(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try = {
460-
val tree1 = untpd.cpy.Try(tree)(expr, handler, finalizer)
459+
override def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = {
460+
val tree1 = untpd.cpy.Try(tree)(expr, cases, finalizer)
461461
tree match {
462-
case tree: Try if (expr.tpe eq tree.expr.tpe) && (handler.tpe eq tree.handler.tpe) => tree1.withTypeUnchecked(tree.tpe)
463-
case _ => ta.assignType(tree1, expr, handler)
462+
case tree: Try if (expr.tpe eq tree.expr.tpe) && (sameTypes(cases, tree.cases)) => tree1.withTypeUnchecked(tree.tpe)
463+
case _ => ta.assignType(tree1, expr, cases)
464464
}
465465
}
466466

@@ -489,8 +489,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
489489
Closure(tree: Tree)(env, meth, tpt)
490490
override def CaseDef(tree: CaseDef)(pat: Tree = tree.pat, guard: Tree = tree.guard, body: Tree = tree.body)(implicit ctx: Context): CaseDef =
491491
CaseDef(tree: Tree)(pat, guard, body)
492-
override def Try(tree: Try)(expr: Tree = tree.expr, handler: Tree = tree.handler, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
493-
Try(tree: Tree)(expr, handler, finalizer)
492+
override def Try(tree: Try)(expr: Tree = tree.expr, cases: List[CaseDef] = tree.cases, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
493+
Try(tree: Tree)(expr, cases, finalizer)
494494
}
495495

496496
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {

src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
123123
def Match(selector: Tree, cases: List[CaseDef]): Match = new Match(selector, cases)
124124
def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body)
125125
def Return(expr: Tree, from: Tree): Return = new Return(expr, from)
126-
def Try(expr: Tree, handler: Tree, finalizer: Tree): Try = new Try(expr, handler, finalizer)
126+
def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree): Try = new Try(expr, cases, finalizer)
127127
def Throw(expr: Tree): Throw = new Throw(expr)
128128
def SeqLiteral(elems: List[Tree]): SeqLiteral = new SeqLiteral(elems)
129129
def JavaSeqLiteral(elems: List[Tree]): JavaSeqLiteral = new JavaSeqLiteral(elems)

src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ object StdNames {
121121
val SUPER_PREFIX: N = "super$"
122122
val TRAIT_SETTER_PREFIX: N = "_setter_$"
123123
val WHILE_PREFIX: N = "while$"
124+
val DEFAULT_EXCEPTION_NAME: N = "ex$"
124125

125126
// value types (and AnyRef) are all used as terms as well
126127
// as (at least) arguments to the @specialize annotation.

src/dotty/tools/dotc/core/pickling/UnPickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
10351035
val block = readTreeRef()
10361036
val finalizer = readTreeRef()
10371037
val catches = until(end, readCaseDefRef)
1038-
Try(block, Match(EmptyTree, catches), finalizer)
1038+
Try(block, catches, finalizer)
10391039

10401040
case THROWtree =>
10411041
Throw(readTreeRef())

src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,15 @@ object Parsers {
914914
val finalizer =
915915
if (handler.isEmpty || in.token == FINALLY) { accept(FINALLY); expr() }
916916
else EmptyTree
917-
Try(body, handler, finalizer)
917+
handler match {
918+
case Match(sel, cases) => Try(body, cases, finalizer)
919+
case EmptyTree => Try(body, Nil, finalizer)
920+
case _ =>
921+
Try(body,
922+
List(CaseDef(Ident(nme.DEFAULT_EXCEPTION_NAME), EmptyTree, Apply(handler, Ident(nme.DEFAULT_EXCEPTION_NAME)))),
923+
finalizer)
924+
}
925+
918926
}
919927
case THROW =>
920928
atPos(in.skipToken()) { Throw(expr()) }

src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
141141
super.toText(tp)
142142
}
143143

144+
def blockText[T >: Untyped](trees: List[Tree[T]]): Text =
145+
"{" ~ toText(trees, "\n") ~ "}"
146+
144147
override def toText[T >: Untyped](tree: Tree[T]): Text = controlled {
145148

146149
def optDotPrefix(name: Name) = optText(name)(_ ~ ".")
@@ -155,8 +158,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
155158
def addVparamssText(txt: Text, vparamss: List[List[ValDef[T]]]): Text =
156159
(txt /: vparamss)((txt, vparams) => txt ~ "(" ~ toText(vparams, ", ") ~ ")")
157160

158-
def blockText(trees: List[Tree[T]]): Text =
159-
"{" ~ toText(trees, "\n") ~ "}"
161+
160162

161163
def caseBlockText(tree: Tree[T]): Text = tree match {
162164
case Block(stats, expr) => toText(stats :+ expr, "\n")
@@ -261,9 +263,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
261263
"case " ~ toText(pat) ~ optText(guard)(" if " ~ _) ~ " => " ~ caseBlockText(body)
262264
case Return(expr, from) =>
263265
changePrec(GlobalPrec) { "return" ~ optText(expr)(" " ~ _) }
264-
case Try(expr, handler, finalizer) =>
266+
case Try(expr, cases, finalizer) =>
265267
changePrec(GlobalPrec) {
266-
"try " ~ toText(expr) ~ optText(handler)(" catch " ~ _) ~ optText(finalizer)(" finally " ~ _)
268+
"try " ~ toText(expr) ~ optText(cases)(" catch " ~ _) ~ optText(finalizer)(" finally " ~ _)
267269
}
268270
case Throw(expr) =>
269271
changePrec(GlobalPrec) {
@@ -461,6 +463,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
461463
def optText[T >: Untyped](tree: Tree[T])(encl: Text => Text): Text =
462464
if (tree.isEmpty) "" else encl(toText(tree))
463465

466+
def optText[T >: Untyped](tree: List[Tree[T]])(encl: Text => Text): Text =
467+
if (tree.exists(!_.isEmpty)) "" else encl(blockText(tree))
468+
464469
override protected def polyParamName(name: TypeName): TypeName =
465470
name.unexpandedName()
466471

src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,18 +217,15 @@ class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer
217217
val compute = {
218218
val handlerSymbol = ctx.newSymbol(methodSymbol, "$anonfun".toTermName, Flags.Synthetic,
219219
MethodType(List("x$1".toTermName), List(defn.ThrowableType), defn.IntType))
220-
221-
val handler = Closure(handlerSymbol, {
222-
args =>
223-
val exception = args.head.head
224-
val complete = setFlagState.appliedTo(thiz, offset, initState, Literal(Constant(ord)))
225-
Block(List(complete), Throw(exception))
226-
})
220+
val caseSymbol = ctx.newSymbol(methodSymbol, nme.DEFAULT_EXCEPTION_NAME, Flags.Synthetic, defn.ThrowableType)
221+
val complete = setFlagState.appliedTo(thiz, offset, initState, Literal(Constant(ord)))
222+
val handler = CaseDef(Bind(caseSymbol, ref(caseSymbol)), EmptyTree,
223+
Block(List(complete), Throw(ref(caseSymbol))
224+
))
227225

228226
val compute = Assign(ref(resultSymbol), rhs)
229-
val tr = Try(compute, handler, EmptyTree)
227+
val tr = Try(compute, List(handler), EmptyTree)
230228
val assign = Assign(ref(target), ref(resultSymbol))
231-
val complete = setFlagState.appliedTo(thiz, offset, computedState, Literal(Constant(ord)))
232229
val noRetry = Assign(ref(retrySymbol), Literal(Constants.Constant(false)))
233230
val body = If(casFlag.appliedTo(thiz, offset, ref(flagSymbol), computeState, Literal(Constant(ord))),
234231
Block(tr :: assign :: complete :: noRetry :: Nil, Literal(Constant(()))),

src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
5151
override def transformMatch(tree: Match)(implicit ctx: Context, info: TransformerInfo): Tree = {
5252
val translated = new Translator()(ctx).translator.translateMatch(tree)
5353

54-
Typed(translated.ensureConforms(tree.tpe), TypeTree(tree.tpe))
54+
translated.ensureConforms(tree.tpe)
5555
}
5656

5757
class Translator(implicit ctx: Context) {

src/dotty/tools/dotc/transform/TailRec.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,8 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
156156
def noTailTransform(tree: Tree)(implicit c: Context): Tree =
157157
transform(tree, noTailContext)
158158

159-
160-
def noTailTransforms(trees: List[Tree])(implicit c: Context) =
161-
trees map (noTailTransform)
159+
def noTailTransforms[Tr <: Tree](trees: List[Tr])(implicit c: Context): List[Tr] =
160+
trees.map(noTailTransform).asInstanceOf[List[Tr]]
162161

163162
override def transform(tree: Tree)(implicit c: Context): Tree = {
164163
/* A possibly polymorphic apply to be considered for tail call transformation. */
@@ -247,14 +246,14 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
247246
// SI-1672 Catches are in tail position when there is no finalizer
248247
tpd.cpy.Try(tree)(
249248
noTailTransform(tree.expr),
250-
transformHandlers(tree.handler),
249+
transformSub(tree.cases),
251250
EmptyTree
252251
)
253252
}
254253
else {
255254
tpd.cpy.Try(tree)(
256255
noTailTransform(tree.expr),
257-
noTailTransform(tree.handler),
256+
noTailTransforms(tree.cases),
258257
noTailTransform(tree.finalizer)
259258
)
260259
}

src/dotty/tools/dotc/transform/TreeTransform.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,9 +1104,9 @@ object TreeTransforms {
11041104
if (mutatedInfo eq null) tree
11051105
else {
11061106
val block = transform(tree.expr, mutatedInfo, cur)
1107-
val handler = transform(tree.handler, mutatedInfo, cur)
1107+
val cases1 = tree.cases.mapConserve(transform(_, mutatedInfo, cur)).asInstanceOf[List[CaseDef]]
11081108
val finalizer = transform(tree.finalizer, mutatedInfo, cur)
1109-
goTry(cpy.Try(tree)(block, handler, finalizer), mutatedInfo.nx.nxTransTry(cur))
1109+
goTry(cpy.Try(tree)(block, cases1, finalizer), mutatedInfo.nx.nxTransTry(cur))
11101110
}
11111111
case tree: Throw =>
11121112
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForThrow, info.nx.nxPrepThrow, tree, cur)

src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,9 @@ trait TypeAssigner {
299299
def assignType(tree: untpd.Return)(implicit ctx: Context) =
300300
tree.withType(defn.NothingType)
301301

302-
def assignType(tree: untpd.Try, expr: Tree, handler: Tree)(implicit ctx: Context) = {
303-
if(handler.isEmpty) tree.withType(expr.tpe)
304-
else if(handler.tpe.derivesFrom(defn.FunctionClass(1))) {
305-
val handlerTypeArgs = handler.tpe.baseArgTypesHi(defn.FunctionClass(1))
306-
tree.withType(if (handlerTypeArgs.nonEmpty) expr.tpe | handlerTypeArgs(1) else expr.tpe /*| Object, as function returns boxed value ??? */)
307-
} else tree.withType(expr.tpe | handler.tpe)
302+
def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) = {
303+
if (cases.isEmpty) tree.withType(expr.tpe)
304+
else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes))
308305
}
309306

310307
def assignType(tree: untpd.Throw)(implicit ctx: Context) =

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -675,20 +675,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
675675

676676
def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = track("typedTry") {
677677
val expr1 = typed(tree.expr, pt)
678-
val handler1: Tree = tree.handler match {
679-
case h: untpd.Match if ((h.selector eq EmptyTree) // comes from parser
680-
|| (h.selector eq ExceptionHandlerSel)) => // during retyping
681-
val cases1 = typedCases(h.cases, defn.ThrowableType, pt)
682-
assignType(untpd.Match(Typed(ExceptionHandlerSel, TypeTree(defn.ThrowableType)), cases1), cases1)
683-
case Typed(handler, tpe) if ctx.phaseId > ctx.patmatPhase.id => // we are retyping an expanded pattern
684-
typed(tree.handler, pt)
685-
case Apply(bx, List(Typed(handler, tpe))) if ctx.erasedTypes && Boxing.isBox(bx.symbol) =>
686-
typed(tree.handler, pt)
687-
case _ => typed(tree.handler, defn.FunctionType(defn.ThrowableType :: Nil, pt))
688-
689-
}
678+
val cases1 = typedCases(tree.cases, defn.ThrowableType, pt)
690679
val finalizer1 = typed(tree.finalizer, defn.UnitType)
691-
assignType(cpy.Try(tree)(expr1, handler1, finalizer1), expr1, handler1)
680+
assignType(cpy.Try(tree)(expr1, cases1, finalizer1), expr1, cases1)
692681
}
693682

694683
def typedThrow(tree: untpd.Throw)(implicit ctx: Context): Throw = track("typedThrow") {

0 commit comments

Comments
 (0)