summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-02-15 17:30:22 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-02-15 17:30:22 -0800
commit6a7078c598f91fb23f8e43d792415fdd1719b4ff (patch)
treed7326ab52d79305dad437d4003063ee5884245b0 /src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
parent7fdc873c06ac4bacd8447af12495333bd30a0f3c (diff)
downloadscala-6a7078c598f91fb23f8e43d792415fdd1719b4ff.tar.gz
scala-6a7078c598f91fb23f8e43d792415fdd1719b4ff.tar.bz2
scala-6a7078c598f91fb23f8e43d792415fdd1719b4ff.zip
remove unused imports
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala82
1 files changed, 36 insertions, 46 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 1e12975880..39157e3843 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -6,21 +6,12 @@
package scala.tools.nsc.transform.patmat
-import scala.tools.nsc.{ast, symtab, typechecker, transform, Global}
-import transform._
-import typechecker._
-import symtab._
-import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC, ARTIFACT}
import scala.language.postfixOps
-import scala.tools.nsc.transform.TypingTransformers
-import scala.tools.nsc.transform.Transform
import scala.collection.mutable
import scala.reflect.internal.util.Statistics
-import scala.reflect.internal.Types
-import scala.reflect.internal.util.HashSet
+import scala.reflect.internal.util.Position
trait TreeAndTypeAnalysis extends Debugging {
- val global: Global
import global.{Tree, Type, Symbol, definitions, analyzer,
ConstantType, Literal, Constant, appliedType, WildcardType, TypeRef, ModuleClassSymbol,
nestedMemberType, TypeMap, Ident}
@@ -28,7 +19,6 @@ trait TreeAndTypeAnalysis extends Debugging {
import definitions._
import analyzer.Typer
- import debugging.patmatDebug
// we use subtyping as a model for implication between instanceof tests
// i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T]
@@ -70,7 +60,7 @@ trait TreeAndTypeAnalysis extends Debugging {
Some(List(tp))
// make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
case sym if !sym.isSealed || isPrimitiveValueClass(sym) =>
- patmatDebug("enum unsealed "+ (tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))
+ debug.patmat("enum unsealed "+ (tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))
None
case sym =>
val subclasses = (
@@ -78,7 +68,7 @@ trait TreeAndTypeAnalysis extends Debugging {
// symbols which are both sealed and abstract need not be covered themselves, because
// all of their children must be and they cannot otherwise be created.
filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)))
- patmatDebug("enum sealed -- subclasses: "+ (sym, subclasses))
+ debug.patmat("enum sealed -- subclasses: "+ (sym, subclasses))
val tpApprox = typer.infer.approximateAbstracts(tp)
val pre = tpApprox.prefix
@@ -92,11 +82,11 @@ trait TreeAndTypeAnalysis extends Debugging {
val memberType = nestedMemberType(sym, pre, tpApprox.typeSymbol.owner)
val subTp = appliedType(memberType, sym.typeParams.map(_ => WildcardType))
val subTpApprox = typer.infer.approximateAbstracts(subTp) // TODO: needed?
- // patmatDebug("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox))
+ // debug.patmat("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox))
if (subTpApprox <:< tpApprox) Some(checkableType(subTp))
else None
})
- patmatDebug("enum sealed "+ (tp, tpApprox) + " as "+ validSubTypes)
+ debug.patmat("enum sealed "+ (tp, tpApprox) + " as "+ validSubTypes)
Some(validSubTypes)
}
@@ -118,7 +108,7 @@ trait TreeAndTypeAnalysis extends Debugging {
}
val res = typeArgsToWildcardsExceptArray(tp)
- patmatDebug("checkable "+(tp, res))
+ debug.patmat("checkable "+(tp, res))
res
}
@@ -129,7 +119,7 @@ trait TreeAndTypeAnalysis extends Debugging {
val checkable = (
(isTupleType(tp) && tupleComponents(tp).exists(tp => !uncheckableType(tp)))
|| enumerateSubtypes(tp).nonEmpty)
- // if (!checkable) patmatDebug("deemed uncheckable: "+ tp)
+ // if (!checkable) debug.patmat("deemed uncheckable: "+ tp)
!checkable
}
}
@@ -137,8 +127,7 @@ trait TreeAndTypeAnalysis extends Debugging {
trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
import PatternMatchingStats._
- val global: Global
- import global.{Tree, Type, Symbol, CaseDef, Position, atPos, NoPosition,
+ import global.{Tree, Type, Symbol, CaseDef, atPos,
Select, Block, ThisType, SingleType, NoPrefix, NoType, definitions, needsOuterTest,
ConstantType, Literal, Constant, gen, This, analyzer, EmptyTree, map2, NoSymbol, Traverser,
Function, Typed, treeInfo, DefTree, ValDef, nme, appliedType, Name, WildcardType, Ident, TypeRef,
@@ -148,8 +137,6 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
import definitions._
import analyzer.{Typer, ErrorUtils, formalTypes}
- import debugging.patmatDebug
-
/**
* Represent a match as a formula in propositional logic that encodes whether the match matches (abstractly: we only consider types)
*
@@ -196,8 +183,8 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
uniqueTypeProps getOrElseUpdate((testedPath, pt), Eq(Var(testedPath), TypeConst(checkableType(pt))))
// a variable in this set should never be replaced by a tree that "does not consist of a selection on a variable in this set" (intuitively)
- private val pointsToBound = scala.collection.mutable.HashSet(root)
- private val trees = scala.collection.mutable.HashSet.empty[Tree]
+ private val pointsToBound = mutable.HashSet(root)
+ private val trees = mutable.HashSet.empty[Tree]
// the substitution that renames variables to variables in pointsToBound
private var normalize: Substitution = EmptySubstitution
@@ -215,7 +202,7 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
def unique(t: Tree, tpOverride: Type = NoType): Tree =
trees find (a => a.correspondsStructure(t)(sameValue)) match {
case Some(orig) =>
- // patmatDebug("unique: "+ (t eq orig, orig))
+ // debug.patmat("unique: "+ (t eq orig, orig))
orig
case _ =>
trees += t
@@ -253,14 +240,14 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// reverse substitution that would otherwise replace a variable we already encountered by a new variable
// NOTE: this forgets the more precise type we have for these later variables, but that's probably okay
normalize >>= Substitution(boundTo map (_.symbol), boundFrom map (CODE.REF(_)))
- // patmatDebug ("normalize subst: "+ normalize)
+ // debug.patmat ("normalize subst: "+ normalize)
val okSubst = Substitution(unboundFrom, unboundTo map (normalize(_))) // it's important substitution does not duplicate trees here -- it helps to keep hash consing simple, anyway
pointsToBound ++= ((okSubst.from, okSubst.to).zipped filter { (f, t) => pointsToBound exists (sym => t.exists(_.symbol == sym)) })._1
- // patmatDebug("pointsToBound: "+ pointsToBound)
+ // debug.patmat("pointsToBound: "+ pointsToBound)
accumSubst >>= okSubst
- // patmatDebug("accumSubst: "+ accumSubst)
+ // debug.patmat("accumSubst: "+ accumSubst)
}
def handleUnknown(tm: TreeMaker): Prop
@@ -351,18 +338,21 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
/\(tests.takeWhile(t => !t.treeMaker.isInstanceOf[BodyTreeMaker]).map(t => t.prop))
def showTreeMakers(cases: List[List[TreeMaker]]) = {
- patmatDebug("treeMakers:")
- patmatDebug(alignAcrossRows(cases, ">>"))
+ debug.patmat("treeMakers:")
+ debug.patmat(alignAcrossRows(cases, ">>"))
}
def showTests(testss: List[List[Test]]) = {
- patmatDebug("tests: ")
- patmatDebug(alignAcrossRows(testss, "&"))
+ debug.patmat("tests: ")
+ debug.patmat(alignAcrossRows(testss, "&"))
}
}
trait SymbolicMatchAnalysis extends TreeMakerApproximation { self: CodegenCore =>
- // TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil
+ def uncheckedWarning(pos: Position, msg: String) = global.currentUnit.uncheckedWarning(pos, msg)
+ def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}")
+
+ // TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil
// right now hackily implement this by pruning counter-examples
// unreachability would also benefit from a more faithful representation
@@ -403,8 +393,8 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
var reachable = true
var caseIndex = 0
- patmatDebug("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
- patmatDebug("equality axioms:\n"+ cnfString(eqAxiomsOk))
+ debug.patmat("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
+ debug.patmat("equality axioms:\n"+ cnfString(eqAxiomsOk))
// invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
// termination: prefixRest.length decreases by 1
@@ -418,8 +408,8 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
current = current.tail
val model = findModelFor(andFormula(current.head, toFormula(prefix)))
- // patmatDebug("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
- // if (NoModel ne model) patmatDebug("reached: "+ modelString(model))
+ // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
+ // if (NoModel ne model) debug.patmat("reached: "+ modelString(model))
reachable = NoModel ne model
}
@@ -430,7 +420,7 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
if (reachable) None else Some(caseIndex)
} catch {
case ex: AnalysisBudget.Exception =>
- ex.warn(prevBinder.pos, "unreachability")
+ warn(prevBinder.pos, ex, "unreachability")
None // CNF budget exceeded
}
}
@@ -451,7 +441,7 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
val symbolicCases = approx.approximateMatch(cases, approx.onUnknown { tm =>
approx.fullRewrite.applyOrElse[TreeMaker, Prop](tm, {
case BodyTreeMaker(_, _) => True // irrelevant -- will be discarded by symbolCase later
- case _ => // patmatDebug("backing off due to "+ tm)
+ case _ => // debug.patmat("backing off due to "+ tm)
backoff = true
False
})
@@ -474,11 +464,11 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
val matchFails = Not(\/(symbolicCases))
// debug output:
- patmatDebug("analysing:")
+ debug.patmat("analysing:")
showTreeMakers(cases)
- // patmatDebug("\nvars:\n"+ (vars map (_.describe) mkString ("\n")))
- // patmatDebug("\nmatchFails as CNF:\n"+ cnfString(propToSolvable(matchFails)))
+ // debug.patmat("\nvars:\n"+ (vars map (_.describe) mkString ("\n")))
+ // debug.patmat("\nmatchFails as CNF:\n"+ cnfString(propToSolvable(matchFails)))
try {
// find the models (under which the match fails)
@@ -493,7 +483,7 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
pruned
} catch {
case ex : AnalysisBudget.Exception =>
- ex.warn(prevBinder.pos, "exhaustivity")
+ warn(prevBinder.pos, ex, "exhaustivity")
Nil // CNF budget exceeded
}
}
@@ -580,14 +570,14 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// ...
val varAssignment = modelToVarAssignment(model)
- patmatDebug("var assignment for model "+ model +":\n"+ varAssignmentString(varAssignment))
+ debug.patmat("var assignment for model "+ model +":\n"+ varAssignmentString(varAssignment))
// chop a path into a list of symbols
def chop(path: Tree): List[Symbol] = path match {
case Ident(_) => List(path.symbol)
case Select(pre, name) => chop(pre) :+ path.symbol
case _ =>
- // patmatDebug("don't know how to chop "+ path)
+ // debug.patmat("don't know how to chop "+ path)
Nil
}
@@ -647,7 +637,7 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
def toCounterExample(beBrief: Boolean = false): CounterExample =
if (!allFieldAssignmentsLegal) NoExample
else {
- patmatDebug("describing "+ (variable, equalTo, notEqualTo, fields, cls, allFieldAssignmentsLegal))
+ debug.patmat("describing "+ (variable, equalTo, notEqualTo, fields, cls, allFieldAssignmentsLegal))
val res = prunedEqualTo match {
// a definite assignment to a value
case List(eq: ValueConst) if fields.isEmpty => ValueExample(eq)
@@ -688,7 +678,7 @@ trait Analysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// TODO: improve reasoning -- in the mean time, a false negative is better than an annoying false positive
case _ => NoExample
}
- patmatDebug("described as: "+ res)
+ debug.patmat("described as: "+ res)
res
}