Skip to content

Commit 0391436

Browse files
author
Adriaan Moors
committed
move synthetic case symbol detection to treeInfo
encapsulate creating synthetic case labels while we're at it
1 parent f5f7570 commit 0391436

File tree

6 files changed

+28
-17
lines changed

6 files changed

+28
-17
lines changed

src/compiler/scala/tools/nsc/ast/TreeGen.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
7272
Annotated(Ident(nme.synthSwitch), expr)
7373
}
7474

75-
def hasSynthCaseSymbol(t: Tree) = (t.symbol ne null) && (t.symbol hasFlag (CASE | SYNTHETIC))
76-
7775
// TODO: would be so much nicer if we would know during match-translation (i.e., type checking)
7876
// whether we should emit missingCase-style apply (and isDefinedAt), instead of transforming trees post-factum
7977
class MatchMatcher {
@@ -94,13 +92,13 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
9492
case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr )
9593
caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher)
9694
// optimized version of virtpatmat
97-
case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) =>
95+
case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) =>
9896
// the assumption is once we encounter a case, the remainder of the block will consist of cases
9997
// the prologue may be empty, usually it is the valdef that stores the scrut
10098
val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
10199
caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity)
102100
// optimized version of virtpatmat
103-
case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) =>
101+
case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) =>
104102
val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
105103
caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m))
106104
case other =>

src/compiler/scala/tools/nsc/transform/TailCalls.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ abstract class TailCalls extends Transform {
3636
}
3737
}
3838

39-
import gen.hasSynthCaseSymbol
39+
import treeInfo.hasSynthCaseSymbol
4040

4141
/**
4242
* A Tail Call Transformer

src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
113113
import definitions._
114114
import analyzer._ //Typer
115115

116-
val SYNTH_CASE = Flags.CASE | SYNTHETIC
117116

118117
case class DefaultOverrideMatchAttachment(default: Tree)
119118

@@ -241,7 +240,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
241240
// append the default to the list of cases and suppress the unreachable case error that may arise (once we detect that...)
242241
val matchFailGenOverride = match_.attachments.get[DefaultOverrideMatchAttachment].map{case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)}
243242

244-
val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag SYNTH_CASE
243+
val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag treeInfo.SYNTH_CASE_FLAGS
244+
245245
// pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental
246246
val combined = combineCases(selector, selectorSym, cases map translateCase(selectorSym, pt), pt, matchOwner, matchFailGenOverride)
247247

@@ -1316,6 +1316,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
13161316
def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x") =
13171317
NoSymbol.newTermSymbol(freshName(prefix), pos) setInfo tp
13181318

1319+
def newSynthCaseLabel(name: String) =
1320+
NoSymbol.newLabel(freshName(name), NoPosition) setFlag treeInfo.SYNTH_CASE_FLAGS
1321+
13191322
// codegen relevant to the structure of the translation (how extractors are combined)
13201323
trait AbsCodegen {
13211324
def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree
@@ -1486,7 +1489,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
14861489
case object FalseCond extends Cond {override def toString = "F"}
14871490

14881491
case class AndCond(a: Cond, b: Cond) extends Cond {override def toString = a +"/\\"+ b}
1489-
case class OrCond(a: Cond, b: Cond) extends Cond {override def toString = "("+a+") \\/ ("+ b +")"}
1492+
case class OrCond(a: Cond, b: Cond) extends Cond {override def toString = "("+a+") \\/ ("+ b +")"}
14901493

14911494
object EqualityCond {
14921495
private val uniques = new collection.mutable.HashMap[(Tree, Tree), EqualityCond]
@@ -3108,7 +3111,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
31083111
}
31093112
}
31103113

3111-
private val defaultLabel: Symbol = NoSymbol.newLabel(freshName("default"), NoPosition) setFlag SYNTH_CASE
3114+
private val defaultLabel: Symbol = newSynthCaseLabel("default")
31123115

31133116
/** Collapse guarded cases that switch on the same constant (the last case may be unguarded).
31143117
*
@@ -3476,11 +3479,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
34763479
* if keepGoing is false, the result Some(x) of the naive translation is encoded as matchRes == x
34773480
*/
34783481
def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = {
3479-
val matchEnd = NoSymbol.newLabel(freshName("matchEnd"), NoPosition) setFlag SYNTH_CASE
3482+
val matchEnd = newSynthCaseLabel("matchEnd")
34803483
val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations //
34813484
matchEnd setInfo MethodType(List(matchRes), restpe)
34823485

3483-
def newCaseSym = NoSymbol.newLabel(freshName("case"), NoPosition) setInfo MethodType(Nil, restpe) setFlag SYNTH_CASE
3486+
def newCaseSym = newSynthCaseLabel("case") setInfo MethodType(Nil, restpe)
34843487
var _currCase = newCaseSym
34853488

34863489
val caseDefs = cases map { (mkCase: Casegen => Tree) =>

src/compiler/scala/tools/nsc/typechecker/RefChecks.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
17181718
val pat1 = transform(pat)
17191719
inPattern = false
17201720
treeCopy.CaseDef(tree, pat1, transform(guard), transform(body))
1721-
case LabelDef(_, _, _) if gen.hasSynthCaseSymbol(result) =>
1721+
case LabelDef(_, _, _) if treeInfo.hasSynthCaseSymbol(result) =>
17221722
val old = inPattern
17231723
inPattern = true
17241724
val res = deriveLabelDef(result)(transform)

src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
9999
treeCopy.Block(body, List(transform(selDef)), transformPureMatch(mat, selector, cases))
100100

101101
// virtpatmat
102-
case b@Block(matchStats@((selDef: ValDef) :: cases), matchEnd) if ext.isDefined && pureBody && (matchStats forall gen.hasSynthCaseSymbol) =>
102+
case b@Block(matchStats@((selDef: ValDef) :: cases), matchEnd) if ext.isDefined && pureBody && (matchStats forall treeInfo.hasSynthCaseSymbol) =>
103103
transformPureVirtMatch(b, selDef, cases, matchEnd)
104104

105105
// virtpatmat that stores the scrut separately -- TODO: can we eliminate this case??
106-
case Block(List(selDef0: ValDef), mat@Block(matchStats@((selDef: ValDef) :: cases), matchEnd)) if ext.isDefined && pureBody && (matchStats forall gen.hasSynthCaseSymbol)=>
106+
case Block(List(selDef0: ValDef), mat@Block(matchStats@((selDef: ValDef) :: cases), matchEnd)) if ext.isDefined && pureBody && (matchStats forall treeInfo.hasSynthCaseSymbol)=>
107107
treeCopy.Block(body, List(transform(selDef0)), transformPureVirtMatch(mat, selDef, cases, matchEnd))
108108

109109
case _ =>
@@ -253,7 +253,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
253253
// calling each labeldef is wrong, since some labels may be jumped over
254254
// we can get away with this for now since the only other labels we emit are for tailcalls/while loops,
255255
// which do not have consecutive labeldefs (and thus fall-through is irrelevant)
256-
if (gen.hasSynthCaseSymbol(ldef)) (List(stm1), localTyper.typed{Literal(Constant(()))}, cpsA)
256+
if (treeInfo.hasSynthCaseSymbol(ldef)) (List(stm1), localTyper.typed{Literal(Constant(()))}, cpsA)
257257
else {
258258
assert(params.isEmpty, "problem in ANF transforming label with non-empty params "+ ldef)
259259
(List(stm1), localTyper.typed{Apply(Ident(sym), List())}, cpsA)
@@ -469,9 +469,9 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
469469

470470
val (anfStats, anfExpr) = rec(stms, cpsA, List())
471471
// println("\nanf-block:\n"+ ((stms :+ expr) mkString ("{", "\n", "}")) +"\nBECAME\n"+ ((anfStats :+ anfExpr) mkString ("{", "\n", "}")))
472-
// println("synth case? "+ (anfStats map (t => (t, t.isDef, gen.hasSynthCaseSymbol(t)))))
472+
// println("synth case? "+ (anfStats map (t => (t, t.isDef, treeInfo.hasSynthCaseSymbol(t)))))
473473
// SUPER UGLY HACK: handle virtpatmat-style matches, whose labels have already been turned into DefDefs
474-
if (anfStats.nonEmpty && (anfStats forall (t => !t.isDef || gen.hasSynthCaseSymbol(t)))) {
474+
if (anfStats.nonEmpty && (anfStats forall (t => !t.isDef || treeInfo.hasSynthCaseSymbol(t)))) {
475475
val (prologue, rest) = (anfStats :+ anfExpr) span (s => !s.isInstanceOf[DefDef]) // find first case
476476
// println("rest: "+ rest)
477477
// val (defs, calls) = rest partition (_.isInstanceOf[DefDef])

src/reflect/scala/reflect/internal/TreeInfo.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,16 @@ abstract class TreeInfo {
464464
case _ => false
465465
}
466466

467+
468+
// used in the symbols for labeldefs and valdefs emitted by the pattern matcher
469+
// tailcalls, cps,... use this flag combination to detect translated matches
470+
// TODO: move to Flags
471+
final val SYNTH_CASE_FLAGS = CASE | SYNTHETIC
472+
473+
def isSynthCaseSymbol(sym: Symbol) = sym hasAllFlags SYNTH_CASE_FLAGS
474+
def hasSynthCaseSymbol(t: Tree) = t.symbol != null && isSynthCaseSymbol(t.symbol)
475+
476+
467477
/** The method part of an application node
468478
*/
469479
def methPart(tree: Tree): Tree = tree match {

0 commit comments

Comments
 (0)