From 2b03ac41c0f53d7a411e7f232d6814d7d51051a3 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 18 Sep 2013 08:02:32 -0700 Subject: Type housekeeping. Moved ListOfNil somewhere more generally accessible. No reason the compiler should hoard it for itself. Flitted to a few locations with constructs like ".head.head" and ".tail.head" looking for code which could be rewritten. Found some, admittedly not always making use of ListOfNil. Made overdue moves of ConstantType(Constant(true|false|null)) to vals in Definitions. --- .../scala/tools/nsc/transform/patmat/Logic.scala | 17 ++++++++------- .../tools/nsc/transform/patmat/MatchAnalysis.scala | 8 ++++---- .../nsc/transform/patmat/MatchOptimization.scala | 24 ++++++++-------------- .../nsc/transform/patmat/MatchTreeMaking.scala | 4 ++-- .../scala/tools/nsc/transform/patmat/Solving.scala | 6 +++--- 5 files changed, 25 insertions(+), 34 deletions(-) (limited to 'src/compiler/scala/tools/nsc/transform/patmat') diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 45aa1106f0..f7b194a6ca 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -292,6 +292,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis { type Type = global.Type type Tree = global.Tree + import global.definitions.ConstantNull // resets hash consing -- only supposed to be called by TreeMakersToProps def prepareNewAnalysis(): Unit = { Var.resetUniques(); Const.resetUniques() } @@ -320,7 +321,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { val staticTpCheckable: Type = checkableType(staticTp) private[this] var _mayBeNull = false - def registerNull(): Unit = { ensureCanModify(); if (NullTp <:< staticTpCheckable) _mayBeNull = true } + def registerNull(): Unit = { ensureCanModify(); if (ConstantNull <:< staticTpCheckable) _mayBeNull = true } def mayBeNull: Boolean = _mayBeNull // case None => domain is unknown, @@ -568,7 +569,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { object TypeConst extends TypeConstExtractor { def apply(tp: Type) = { - if (tp =:= NullTp) NullConst + if (tp =:= ConstantNull) NullConst else if (tp.isInstanceOf[SingletonType]) ValueConst.fromType(tp) else Const.unique(tp, new TypeConst(tp)) } @@ -577,7 +578,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { // corresponds to a type test that does not imply any value-equality (well, except for outer checks, which we don't model yet) sealed class TypeConst(val tp: Type) extends Const { - assert(!(tp =:= NullTp)) + assert(!(tp =:= ConstantNull)) /*private[this] val id: Int = */ Const.nextTypeId val wideTp = widenToClass(tp) @@ -598,7 +599,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { } def apply(p: Tree) = { val tp = p.tpe.normalize - if (tp =:= NullTp) NullConst + if (tp =:= ConstantNull) NullConst else { val wideTp = widenToClass(tp) @@ -626,16 +627,14 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { } sealed class ValueConst(val tp: Type, val wideTp: Type, override val toString: String) extends Const { // debug.patmat("VC"+(tp, wideTp, toString)) - assert(!(tp =:= NullTp)) // TODO: assert(!tp.isStable) + assert(!(tp =:= ConstantNull)) // TODO: assert(!tp.isStable) /*private[this] val id: Int = */Const.nextValueId def isValue = true } - - lazy val NullTp = ConstantType(Constant(null)) case object NullConst extends Const { - def tp = NullTp - def wideTp = NullTp + def tp = ConstantNull + def wideTp = ConstantNull def isValue = true override def toString = "null" diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index 8feb87210e..7eb899d9d7 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -50,7 +50,7 @@ trait TreeAndTypeAnalysis extends Debugging { case UnitClass => Some(List(UnitTpe)) case BooleanClass => - Some((List(ConstantType(Constant(true)), ConstantType(Constant(false))))) + Some(ConstantTrue :: ConstantFalse :: Nil) // TODO case _ if tp.isTupleType => // recurse into component types case modSym: ModuleClassSymbol => Some(List(tp)) @@ -271,9 +271,9 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT case SubstOnlyTreeMaker(_, _) => True case GuardTreeMaker(guard) => guard.tpe match { - case ConstantType(Constant(true)) => True - case ConstantType(Constant(false)) => False - case _ => handleUnknown(tm) + case ConstantTrue => True + case ConstantFalse => False + case _ => handleUnknown(tm) } case ExtractorTreeMaker(_, _, _) | ProductExtractorTreeMaker(_, _) | diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala index ba78438b66..8a04c67582 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala @@ -402,23 +402,15 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis { private def noGuards(cs: List[CaseDef]): Boolean = !cs.exists(isGuardedCase) // must do this before removing guards from cases and collapsing (SI-6011, SI-6048) - private def unreachableCase(cs: List[CaseDef]): Option[CaseDef] = { - var cases = cs - var unreachable: Option[CaseDef] = None - - while (cases.nonEmpty && unreachable.isEmpty) { - val currCase = cases.head - if (isDefault(currCase) && cases.tail.nonEmpty) // subsumed by the `else if` that follows, but faster - unreachable = Some(cases.tail.head) - else if (!isGuardedCase(currCase) || currCase.guard.tpe =:= ConstantType(Constant(true))) - unreachable = cases.tail.find(caseImplies(currCase)) - else if (currCase.guard.tpe =:= ConstantType(Constant(false))) - unreachable = Some(currCase) - - cases = cases.tail + private def unreachableCase(cases: List[CaseDef]): Option[CaseDef] = { + def loop(cases: List[CaseDef]): Option[CaseDef] = cases match { + case head :: next :: _ if isDefault(head) => Some(next) // subsumed by the next case, but faster + case head :: rest if !isGuardedCase(head) || head.guard.tpe =:= ConstantTrue => rest find caseImplies(head) orElse loop(rest) + case head :: _ if head.guard.tpe =:= ConstantFalse => Some(head) + case _ :: rest => loop(rest) + case _ => None } - - unreachable + loop(cases) } // empty list ==> failure diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index cf26ec3398..317685682d 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -288,8 +288,8 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { def irrefutableExtractorType(tp: Type): Boolean = tp.resultType.dealias match { case TypeRef(_, SomeClass, _) => true // probably not useful since this type won't be inferred nor can it be written down (yet) - case ConstantType(Constant(true)) => true - case _ => false + case ConstantTrue => true + case _ => false } def unapply(xtm: ExtractorTreeMaker): Option[(Tree, Symbol)] = xtm match { diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala index 114bcba5df..6267585ea8 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala @@ -9,6 +9,7 @@ package scala.tools.nsc.transform.patmat import scala.collection.mutable import scala.reflect.internal.util.Statistics import scala.language.postfixOps +import scala.reflect.internal.util.Collections._ // naive CNF translation and simple DPLL solver trait Solving extends Logic { @@ -205,9 +206,8 @@ trait Solving extends Logic { // SI-7020 Linked- for deterministic counter examples. val pos = new mutable.LinkedHashSet[Sym]() val neg = new mutable.LinkedHashSet[Sym]() - f.foreach{_.foreach{ lit => - if (lit.pos) pos += lit.sym else neg += lit.sym - }} + mforeach(f)(lit => if (lit.pos) pos += lit.sym else neg += lit.sym) + // appearing in both positive and negative val impures: mutable.LinkedHashSet[Sym] = pos intersect neg // appearing only in either positive/negative positions -- cgit v1.2.3