From 0c57ba75d056a75e88db4bcf890abd58cd8fcb2d Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Thu, 8 Oct 2009 21:11:19 +0000 Subject: Reworked exhaustiveness checking yet further, a... Reworked exhaustiveness checking yet further, and moved it and some other pieces into their own file. --- src/compiler/scala/tools/nsc/matching/Matrix.scala | 3 +- .../scala/tools/nsc/matching/MatrixAdditions.scala | 239 +++++++++++++++++++++ .../tools/nsc/matching/ParallelMatching.scala | 153 ++++--------- .../tools/nsc/matching/PatternOptimizer.scala | 137 ------------ .../scala/tools/nsc/matching/TransMatcher.scala | 2 +- 5 files changed, 281 insertions(+), 253 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala delete mode 100644 src/compiler/scala/tools/nsc/matching/PatternOptimizer.scala (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index f5bad3ed22..07923059c1 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -8,8 +8,9 @@ package matching import transform.ExplicitOuter import util.Position +import symtab.Flags -trait Matrix extends PatternOptimizer { +trait Matrix extends MatrixAdditions { self: ExplicitOuter with ParallelMatching => import global.{ typer => _, _ } diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala new file mode 100644 index 0000000000..c1364af806 --- /dev/null +++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala @@ -0,0 +1,239 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2009 LAMP/EPFL + * Author: Paul Phillips + */ + +package scala.tools.nsc +package matching + +import transform.ExplicitOuter + +/** Traits which are mixed into MatchMatrix, but separated out as + * (somewhat) independent components to keep them on the sidelines. + */ +trait MatrixAdditions extends ast.TreeDSL +{ + self: ExplicitOuter with ParallelMatching => + + import global.{ typer => _, _ } + import symtab.Flags + import CODE._ + import Debug._ + + /** The Squeezer, responsible for all the squeezing. + */ + private[matching] trait Squeezer { + self: MatrixContext => + + def squeezedBlock(vds: List[Tree], exp: Tree): Tree = + if (settings_squeeze) Block(Nil, squeezedBlock1(vds, exp)) + else Block(vds, exp) + + private def squeezedBlock1(vds: List[Tree], exp: Tree): Tree = { + class RefTraverser(sym: Symbol) extends Traverser { + var nref, nsafeRef = 0 + override def traverse(tree: Tree) = tree match { + case t: Ident if t.symbol eq sym => + nref += 1 + if (sym.owner == currentOwner) // oldOwner should match currentOwner + nsafeRef += 1 + + case LabelDef(_, args, rhs) => + (args dropWhile(_.symbol ne sym)) match { + case Nil => + case _ => nref += 2 // cannot substitute this one + } + traverse(rhs) + case t if nref > 1 => // abort, no story to tell + case t => + super.traverse(t) + } + } + + class Subst(sym: Symbol, rhs: Tree) extends Transformer { + var stop = false + override def transform(tree: Tree) = tree match { + case t: Ident if t.symbol == sym => + stop = true + rhs + case _ => if (stop) tree else super.transform(tree) + } + } + + lazy val squeezedTail = squeezedBlock(vds.tail, exp) + def default = squeezedTail match { + case Block(vds2, exp2) => Block(vds.head :: vds2, exp2) + case exp2 => Block(vds.head :: Nil, exp2) + } + + if (vds.isEmpty) exp + else vds.head match { + case vd: ValDef => + val sym = vd.symbol + val rt = new RefTraverser(sym) + rt.atOwner (owner) (rt traverse squeezedTail) + + rt.nref match { + case 0 => squeezedTail + case 1 if rt.nsafeRef == 1 => new Subst(sym, vd.rhs) transform squeezedTail + case _ => default + } + case _ => + default + } + } + } + + /** The Optimizer, responsible for some of the optimizing. + */ + private[matching] trait MatchMatrixOptimizer { + self: MatchMatrix => + + import self.context._ + + final def optimize(tree: Tree): Tree = { + // Extractors which can spot pure true/false expressions + // even through the haze of braces + abstract class SeeThroughBlocks[T] { + protected def unapplyImpl(x: Tree): T + def unapply(x: Tree): T = x match { + case Block(Nil, expr) => unapply(expr) + case _ => unapplyImpl(x) + } + } + object IsTrue extends SeeThroughBlocks[Boolean] { + protected def unapplyImpl(x: Tree): Boolean = x equalsStructure TRUE + } + object IsFalse extends SeeThroughBlocks[Boolean] { + protected def unapplyImpl(x: Tree): Boolean = x equalsStructure FALSE + } + object lxtt extends Transformer { + override def transform(tree: Tree): Tree = tree match { + case blck @ Block(vdefs, ld @ LabelDef(name, params, body)) => + def shouldInline(t: FinalState) = t.isReachedOnce && (t.label eq ld.symbol) + + if (targets exists shouldInline) squeezedBlock(vdefs, body) + else blck + + case t => + super.transform(t match { + // note - it is too early for any other true/false related optimizations + case If(cond, IsTrue(), IsFalse()) => cond + + case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) => + IF (cond1 AND cond2) THEN thenp ELSE elsep1 + case If(cond1, If(cond2, thenp, Apply(jmp, Nil)), ld: LabelDef) if jmp.symbol eq ld.symbol => + IF (cond1 AND cond2) THEN thenp ELSE ld + case t => t + }) + } + } + object resetTraverser extends Traverser { + import Flags._ + def reset(vd: ValDef) = + if (vd.symbol hasFlag SYNTHETIC) vd.symbol resetFlag (TRANS_FLAG|MUTABLE) + + override def traverse(x: Tree): Unit = x match { + case vd: ValDef => reset(vd) + case _ => super.traverse(x) + } + } + + returning[Tree](resetTraverser traverse _)(lxtt transform tree) + } + } + + /** The Exhauster. + */ + private[matching] trait MatrixExhaustiveness { + self: MatchMatrix => + + import self.context._ + + /** Exhaustiveness checking requires looking for sealed classes + * and if found, making sure all children are covered by a pattern. + */ + class ExhaustivenessChecker(rep: Rep) { + val Rep(tvars, rows) = rep + + import Flags.{ MUTABLE, ABSTRACT, SEALED, TRANS_FLAG } + + private case class Combo(index: Int, sym: Symbol) { + // is this combination covered by the given pattern? + def isCovered(p: Pattern) = { + def cmpSymbols(t1: Type, t2: Type) = t1.typeSymbol eq t2.typeSymbol + def coversSym = { + val tpe = decodedEqualsType(p.tpe) + lazy val lmoc = sym.linkedModuleOfClass + val symtpe = + if ((sym hasFlag Flags.MODULE) && (lmoc ne NoSymbol)) + singleType(sym.tpe.prefix, lmoc) // e.g. None, Nil + else sym.tpe + + (tpe.typeSymbol == sym) || + (symtpe <:< tpe) || + (symtpe.parents exists (x => cmpSymbols(x, tpe))) || // e.g. Some[Int] <: Option[&b] + ((tpe.prefix memberType sym) <:< tpe) // outer, see combinator.lexical.Scanner + } + + cond(p.tree) { + case _: UnApply | _: ArrayValue => true + case x => p.isDefault || coversSym + } + } + } + + /* True if the patterns in 'row' cover the given type symbol combination, and has no guard. */ + private def rowCoversCombo(row: Row, combos: List[Combo]) = + row.guard.isEmpty && (combos forall (c => c isCovered row.pats(c.index))) + + private def requiresExhaustive(s: Symbol) = + (s hasFlag MUTABLE) && // indicates that have not yet checked exhaustivity + !(s hasFlag TRANS_FLAG) && // indicates @unchecked + (s.tpe.typeSymbol hasFlag SEALED) && + { s resetFlag MUTABLE ; true } // side effects MUTABLE flag + + private def sealedSymsFor(s: Symbol): Set[Symbol] = { + def countSealed(child: Symbol) = { + // include base class only if non-abstract + def baseSet = if (child hasFlag ABSTRACT) Set() else Set(child) + sealedSymsFor(child) ++ baseSet + } + if (s hasFlag SEALED) s.children flatMap countSealed + else Set() + } + private lazy val inexhaustives: List[List[Combo]] = { + val collected = + for ((sym, i) <- tvars.zipWithIndex ; if requiresExhaustive(sym)) yield + i -> sealedSymsFor(sym.tpe.typeSymbol) + + val folded = + collected.foldRight(List[List[Combo]]())((c, xs) => { + val (i, syms) = c match { case (i, set) => (i, set.toList) } + xs match { + case Nil => syms map (s => List(Combo(i, s))) + case _ => for (s <- syms ; rest <- xs) yield Combo(i, s) :: rest + } + }) + + folded filterNot (combo => rows exists (r => rowCoversCombo(r, combo))) + } + + private def mkPad(xs: List[Combo], i: Int): String = xs match { + case Nil => pad("*") + case Combo(j, sym) :: rest => if (j == i) pad(sym.name.toString) else mkPad(rest, i) + } + private def mkMissingStr(open: List[Combo]) = + "missing combination %s\n" format tvars.indices.map(mkPad(open, _)).mkString + + /** The only public method. */ + def check = { + def errMsg = (inexhaustives map mkMissingStr).mkString + if (inexhaustives.nonEmpty) + cunit.warning(tvars.head.pos, "match is not exhaustive!\n" + errMsg) + + rep + } + } + } +} \ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 558d1b0f1f..45a8e5939c 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -22,7 +22,6 @@ trait ParallelMatching extends ast.TreeDSL with Matrix with Patterns with PatternBindings - with PatternOptimizer { self: ExplicitOuter => @@ -133,7 +132,7 @@ trait ParallelMatching extends ast.TreeDSL def toPats(xs: List[Tree]): List[Pattern] = xs map Pattern.apply /** The umbrella matrix class. **/ - class MatchMatrix(val context: MatrixContext, data: MatrixInit) extends MatchMatrixOptimizer { + class MatchMatrix(val context: MatrixContext, data: MatrixInit) extends MatchMatrixOptimizer with MatrixExhaustiveness { import context._ val MatrixInit(roots, cases, failTree) = data @@ -162,7 +161,7 @@ trait ParallelMatching extends ast.TreeDSL // shortcut if (bx < 0) Apply(ID(shortCuts(-bx-1)), Nil) // first time this bx is requested - might be bound elsewhere - else if (target.isNotReached) target.createLabelBody("body%"+bx, patternVars, patternValDefs) + else if (target.isNotReached) target.createLabelBody(bx, patternVars, patternValDefs) // call label "method" if possible else target.getLabelBody(idents, patternValDefs) } @@ -748,31 +747,25 @@ trait ParallelMatching extends ast.TreeDSL /*** States, Rows, Etc. ***/ - case class Row(pat: List[Pattern], subst: Bindings, guard: Guard, bx: Int) { - if (pat exists (p => !p.isDefault)) - traceCategory("Row", "%s", pp(pat)) + case class Row(pats: List[Pattern], subst: Bindings, guard: Guard, bx: Int) { + if (pats exists (p => !p.isDefault)) + traceCategory("Row", "%s", pp(pats)) - def insert(h: Pattern) = copy(pat = h :: pat) - def insert(hs: List[Pattern]) = copy(pat = hs ::: pat) // prepends supplied pattern - def replace(hs: List[Pattern]) = copy(pat = hs) // substitutes for patterns + def insert(h: Pattern) = copy(pats = h :: pats) + def insert(hs: List[Pattern]) = copy(pats = hs ::: pats) // prepends supplied pattern + def replace(hs: List[Pattern]) = copy(pats = hs) // substitutes for patterns def rebind(b: Bindings) = copy(subst = b) // substitutes for bindings def rebind2(vs: Iterable[Symbol], tvars: Symbol) = copy(subst = subst.add(vs, tvars)) def insert2(hs: List[Pattern], vs: Iterable[Symbol], tvars: Symbol) = // prepends and prepends - copy(pat = hs ::: pat, subst = subst.add(vs, tvars)) - - /** returns true if the patterns in this rows cover a type symbols "combination" and there is no guard - * @param comb pairs of (column index, type symbol) - */ - def covers(combos: List[Combo]) = - guard.isEmpty && (combos forall (c => c isCovered pat(c.index))) + copy(pats = hs ::: pats, subst = subst.add(vs, tvars)) // returns this rows with alternatives expanded def expandAlternatives(classifyPat: (Pattern, Int) => Pattern): List[Row] = { // classify all the top level patterns - alternatives come back unaltered - val newPats: List[Pattern] = pat.zipWithIndex map tupled(classifyPat) + val newPats: List[Pattern] = pats.zipWithIndex map tupled(classifyPat) // expand alternatives if any are present (newPats indexWhere (_.isAlternative)) match { case -1 => List(replace(newPats)) @@ -782,7 +775,7 @@ trait ParallelMatching extends ast.TreeDSL extractBindings(alts.boundTree) map (x => replace(prefix ::: Pattern(x) :: suffix)) } } - override def toString() = pp(bx -> (pat, subst)) + override def toString() = pp(bx -> (pats, subst)) } object ExpandedMatrix { @@ -830,7 +823,8 @@ trait ParallelMatching extends ast.TreeDSL abort(msg.format(name, pp(labelParamTypes), pp(idents), pp(vdefs))) } - def createLabelBody(name: String, args: List[Symbol], vdefs: List[Tree]) = { + def createLabelBody(index: Int, args: List[Symbol], vdefs: List[Tree]) = { + val name = "body%" + index require(_labelSym == null) referenceCount += 1 @@ -866,31 +860,6 @@ trait ParallelMatching extends ast.TreeDSL override def toString() = pp("Final%d%s".format(bx, pp(freeVars)) -> body) } - - case class Combo(index: Int, sym: Symbol) { - // is this combination covered by the given pattern? - def isCovered(p: Pattern) = { - def cmpSymbols(t1: Type, t2: Type) = t1.typeSymbol eq t2.typeSymbol - def coversSym = { - val tpe = decodedEqualsType(p.tpe) - lazy val lmoc = sym.linkedModuleOfClass - val symtpe = - if ((sym hasFlag Flags.MODULE) && (lmoc ne NoSymbol)) - singleType(sym.tpe.prefix, lmoc) // e.g. None, Nil - else sym.tpe - - (tpe.typeSymbol == sym) || - (symtpe <:< tpe) || - (symtpe.parents exists (x => cmpSymbols(x, tpe))) || // e.g. Some[Int] <: Option[&b] - ((tpe.prefix memberType sym) <:< tpe) // outer, see combinator.lexical.Scanner - } - - cond(p.tree) { - case _: UnApply | _: ArrayValue => true - case x => p.isDefault || coversSym - } - } - } case class Branch[T](action: T, succ: Rep, fail: Option[Rep]) case class UnapplyCall(ua: Tree, vdefs: List[Tree]) { def matchCondition: Tree = @@ -899,44 +868,32 @@ trait ParallelMatching extends ast.TreeDSL } case class Rep(val tvars: List[Symbol], val rows: List[Row]) { - import Flags._ + lazy val Row(pats, subst, guard, index) = rows.head + lazy val guardedRest = if (guard.isEmpty) NoRep else make(tvars, rows.tail) + lazy val (defaults, others) = pats span (_.isDefault) /** Converts this to a tree - recursively acquires subreps. */ final def toTree(): Tree = typer typed this.applyRule.tree() - /** Exhaustiveness checking requires looking for sealed classes - * and if found, making sure all children are covered by a pattern. - */ - private def requiresExhaustive(s: Symbol) = - (s hasFlag MUTABLE) && // indicates that have not yet checked exhaustivity - !(s hasFlag TRANS_FLAG) && // indicates @unchecked - (s.tpe.typeSymbol hasFlag SEALED) && - { s resetFlag MUTABLE ; true } // side effects MUTABLE flag - - private def sealedSymsFor(s: Symbol): Set[Symbol] = { - def countSealed(child: Symbol) = { - // include base class only if non-abstract - def baseSet = if (child hasFlag ABSTRACT) Set() else Set(child) - sealedSymsFor(child) ++ baseSet - } - if (s hasFlag SEALED) s.children flatMap countSealed - else Set() + /** The VariableRule. */ + private def variable() = { + val binding = (defaults map (_.boundVariables) zip tvars) . + foldLeft(subst)((b, pair) => b.add(pair._1, pair._2)) + + VariableRule(binding, guard, guardedRest, index) } - private lazy val inexhaustives: List[List[Combo]] = { - val collected = - for ((sym, i) <- tvars.zipWithIndex ; if requiresExhaustive(sym)) yield - i -> sealedSymsFor(sym.tpe.typeSymbol) - - val folded = - collected.foldRight(List[List[Combo]]())((c, xs) => { - val (i, syms) = c match { case (i, set) => (i, set.toList) } - xs match { - case Nil => syms map (s => List(Combo(i, s))) - case _ => for (s <- syms ; rest <- xs) yield Combo(i, s) :: rest - } - }) - folded filterNot (combo => rows exists (_ covers combo)) + /** The MixtureRule. */ + def mixture() = { + /** cut out the column containing the non-default pattern. */ + val newIndex = defaults.size + + val rpat = others.head + val column = rpat :: (rows.tail map (_ pats newIndex)) + val restTemp = dropIndex(tvars, newIndex) + val restRows = rows map (r => r replace dropIndex(r.pats, newIndex)) + + MixtureRule(new Scrutinee(tvars(newIndex)), column, make(restTemp, restRows)) } /** Applying the rule will result in one of: @@ -945,47 +902,15 @@ trait ParallelMatching extends ast.TreeDSL * MixtureRule - if one or more patterns are not default patterns * ErrorRule - if there are no rows remaining */ - final def applyRule(): RuleApplication = { - def dropIndex[T](xs: List[T], n: Int) = (xs take n) ::: (xs drop (n + 1)) - - lazy val Row(pmatch, subst, guard, index) = rows.head - lazy val guardedRest = if (guard.isEmpty) NoRep else make(tvars, rows.tail) - lazy val (defaults, others) = pmatch span (_.isDefault) - lazy val ndIndex = defaults.size // index of non-default pattern in pmatch - + final def applyRule(): RuleApplication = if (rows.isEmpty) ErrorRule() - else if (others.isEmpty) { - /** top-most rows contains only variables/wildcards */ - val binding = (defaults map (_.boundVariables) zip tvars) . - foldLeft(subst)((b, pair) => b.add(pair._1, pair._2)) - - VariableRule(binding, guard, guardedRest, index) - } - else { - /** cut out the column (px) containing the non-default pattern. */ - val rpat = others.head - val vs = rpat.boundVariables - val column = rpat :: (rows.tail map (_ pat ndIndex)) - val restTemp = dropIndex(tvars, ndIndex) - val restRows = rows map (r => r replace dropIndex(r.pat, ndIndex)) - - MixtureRule(new Scrutinee(tvars(ndIndex)), column, make(restTemp, restRows)) - } - } + else if (others.isEmpty) variable() + else mixture() - def checkExhaustive: this.type = { - if (inexhaustives.nonEmpty) { - def mkPad(xs: List[Combo], i: Int): String = xs match { - case Nil => pad("*") - case Combo(j, sym) :: rest => if (j == i) pad(sym.name.toString) else mkPad(rest, i) - } - def mkMissingStr(open: List[Combo]) = - "missing combination %s\n" format tvars.indices.map(mkPad(open, _)).mkString + def checkExhaustive = new ExhaustivenessChecker(this).check - cunit.warning(tvars.head.pos, "match is not exhaustive!\n" + (inexhaustives map mkMissingStr).mkString) - } - this - } + private def dropIndex[T](xs: List[T], n: Int) = + (xs take n) ::: (xs drop (n + 1)) override def toString() = if (tvars.size == 0) "Rep(%d) = %s".format(rows.size, pp(rows)) diff --git a/src/compiler/scala/tools/nsc/matching/PatternOptimizer.scala b/src/compiler/scala/tools/nsc/matching/PatternOptimizer.scala deleted file mode 100644 index aa51ea4bd3..0000000000 --- a/src/compiler/scala/tools/nsc/matching/PatternOptimizer.scala +++ /dev/null @@ -1,137 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2009 LAMP/EPFL - * Author: Paul Phillips - */ - -package scala.tools.nsc -package matching - -import transform.ExplicitOuter - -trait PatternOptimizer extends ast.TreeDSL -{ - self: ExplicitOuter with ParallelMatching => - - import global.{ typer => _, _ } - import symtab.Flags - import CODE._ - - private[matching] trait Squeezer { - self: MatrixContext => - - def squeezedBlock(vds: List[Tree], exp: Tree): Tree = - if (settings_squeeze) Block(Nil, squeezedBlock1(vds, exp)) - else Block(vds, exp) - - private def squeezedBlock1(vds: List[Tree], exp: Tree): Tree = { - class RefTraverser(sym: Symbol) extends Traverser { - var nref, nsafeRef = 0 - override def traverse(tree: Tree) = tree match { - case t: Ident if t.symbol eq sym => - nref += 1 - if (sym.owner == currentOwner) // oldOwner should match currentOwner - nsafeRef += 1 - - case LabelDef(_, args, rhs) => - (args dropWhile(_.symbol ne sym)) match { - case Nil => - case _ => nref += 2 // cannot substitute this one - } - traverse(rhs) - case t if nref > 1 => // abort, no story to tell - case t => - super.traverse(t) - } - } - - class Subst(sym: Symbol, rhs: Tree) extends Transformer { - var stop = false - override def transform(tree: Tree) = tree match { - case t: Ident if t.symbol == sym => - stop = true - rhs - case _ => if (stop) tree else super.transform(tree) - } - } - - lazy val squeezedTail = squeezedBlock(vds.tail, exp) - def default = squeezedTail match { - case Block(vds2, exp2) => Block(vds.head :: vds2, exp2) - case exp2 => Block(vds.head :: Nil, exp2) - } - - if (vds.isEmpty) exp - else vds.head match { - case vd: ValDef => - val sym = vd.symbol - val rt = new RefTraverser(sym) - rt.atOwner (owner) (rt traverse squeezedTail) - - rt.nref match { - case 0 => squeezedTail - case 1 if rt.nsafeRef == 1 => new Subst(sym, vd.rhs) transform squeezedTail - case _ => default - } - case _ => - default - } - } - } - - private[matching] trait MatchMatrixOptimizer { - self: MatchMatrix => - - import self.context._ - - final def optimize(tree: Tree): Tree = { - // Extractors which can spot pure true/false expressions - // even through the haze of braces - abstract class SeeThroughBlocks[T] { - protected def unapplyImpl(x: Tree): T - def unapply(x: Tree): T = x match { - case Block(Nil, expr) => unapply(expr) - case _ => unapplyImpl(x) - } - } - object IsTrue extends SeeThroughBlocks[Boolean] { - protected def unapplyImpl(x: Tree): Boolean = x equalsStructure TRUE - } - object IsFalse extends SeeThroughBlocks[Boolean] { - protected def unapplyImpl(x: Tree): Boolean = x equalsStructure FALSE - } - object lxtt extends Transformer { - override def transform(tree: Tree): Tree = tree match { - case blck @ Block(vdefs, ld @ LabelDef(name, params, body)) => - def shouldInline(t: FinalState) = t.isReachedOnce && (t.label eq ld.symbol) - - if (targets exists shouldInline) squeezedBlock(vdefs, body) - else blck - - case t => - super.transform(t match { - // note - it is too early for any other true/false related optimizations - case If(cond, IsTrue(), IsFalse()) => cond - - case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) => - IF (cond1 AND cond2) THEN thenp ELSE elsep1 - case If(cond1, If(cond2, thenp, Apply(jmp, Nil)), ld: LabelDef) if jmp.symbol eq ld.symbol => - IF (cond1 AND cond2) THEN thenp ELSE ld - case t => t - }) - } - } - object resetTraverser extends Traverser { - import Flags._ - def reset(vd: ValDef) = - if (vd.symbol hasFlag SYNTHETIC) vd.symbol resetFlag (TRANS_FLAG|MUTABLE) - - override def traverse(x: Tree): Unit = x match { - case vd: ValDef => reset(vd) - case _ => super.traverse(x) - } - } - - returning[Tree](resetTraverser traverse _)(lxtt transform tree) - } - } -} \ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala index c6a61984bf..6a31a68989 100644 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala @@ -19,7 +19,7 @@ import scala.util.NameTransformer.decode * @author Burak Emir */ trait TransMatcher extends ast.TreeDSL with CompactTreePrinter { - self: ExplicitOuter with ParallelMatching with PatternOptimizer => + self: ExplicitOuter with ParallelMatching => import global.{ typer => _, _ } import analyzer.Typer -- cgit v1.2.3