summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Checkers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala3
-rw-r--r--src/compiler/scala/tools/nsc/matching/CodeFactory.scala68
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala524
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala87
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala73
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
-rw-r--r--src/library/scala/testing/SUnit.scala10
-rw-r--r--test/files/jvm/unittest_io.scala22
-rw-r--r--test/files/jvm/unittest_xml.scala2
-rw-r--r--test/files/jvm/xml01.scala2
-rw-r--r--test/files/neg/patmatexhaust.check32
-rw-r--r--test/files/neg/patmatexhaust.scala8
-rw-r--r--test/files/pos/patterns.scala9
-rw-r--r--test/files/run/bug789.scala1
-rw-r--r--test/files/run/patmatnew.scala30
-rw-r--r--test/files/run/unapply.scala28
18 files changed, 404 insertions, 502 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index a61d878258..a0429ffd44 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -136,7 +136,6 @@ class Settings(error: String => unit) {
val Xplugtypes = BooleanSetting("-Xplugtypes", "parse but ignore annotations in more locations")
//Xplugtypes.value = true // just while experimenting
val Xkilloption = BooleanSetting("-Xkilloption", "optimizes option types")
- val XprintOuterMatches = BooleanSetting("-XprintOuterMatches", "prints outer-checks caused by pattern matching")
/** A list of all settings */
def allSettings: List[Setting] = allsettings.reverse
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
index e1daa00c13..0bd4de0e10 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
@@ -446,7 +446,8 @@ abstract class Checkers {
kind match {
case REFERENCE(cls) =>
stack.push(kind)
- case _ =>
+ //bq: had to change from _ to null, because otherwise would be unreachable code
+ case null =>
error("NEW call to non-reference type: " + kind)
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index 1bb33a5ca9..2a13a37cfc 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -322,7 +322,8 @@ abstract class CopyPropagation {
Record(cls, new HashMap[Symbol, Value])
else Unknown */
Record(cls, new HashMap[Symbol, Value])
- case _ =>
+ // bq: changed from _ to null, otherwise would be unreachable
+ case null =>
Unknown
}
out.stack = v1 :: out.stack
diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
index afae88ee56..9926fbd915 100644
--- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
+++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala
@@ -229,5 +229,73 @@ trait CodeFactory requires transform.ExplicitOuter {
Apply(Select(tree, nme.eq), List(Literal(Constant(null))))
}
+ // statistics
+ var nremoved = 0
+ var nsubstituted = 0
+ var nstatic = 0
+
+ def squeezedBlock(vds:List[Tree], exp:Tree)(implicit theOwner: Symbol): Tree = {
+ val tpe = exp.tpe
+ class RefTraverser(sym:Symbol) extends Traverser {
+ var nref = 0
+ var nsafeRef = 0
+ override def traverse(tree: Tree) = tree match {
+ case t:Ident if t.symbol == sym =>
+ nref = nref + 1
+ if(sym.owner == currentOwner) { // oldOwner should match currentOwner
+ nsafeRef = nsafeRef + 1
+ } /*else if(nref == 1) {
+ Console.println("sym owner: "+sym.owner+" but currentOwner = "+currentOwner)
+ }*/
+ 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 t if stop =>
+ t
+ case t =>
+ super . transform (t)
+ }
+ }
+ vds match {
+ case Nil => exp
+
+ case (vd:ValDef) :: rest =>
+ // recurse
+ val exp1 = squeezedBlock(rest, exp)
+
+ //Console.println("squeezedBlock for valdef "+vd)
+ val sym = vd.symbol
+ val rt = new RefTraverser(sym)
+ rt.atOwner (theOwner) (rt.traverse(exp1))
+ rt.nref match {
+ case 0 =>
+ nremoved = nremoved + 1
+ exp1
+ case 1 if rt.nsafeRef == 1 =>
+ nsubstituted = nsubstituted + 1
+ new Subst(sym, vd.rhs).transform( exp1 )
+ case _ =>
+ exp1 match {
+ case Block(vds2, exp2) => Block(vd::vds2, exp2)
+ case exp2 => Block(vd::Nil, exp2)
+ }
+ }
+ case x::xs =>
+ squeezedBlock(xs, exp) match {
+ case Block(vds2, exp2) => Block(x::vds2, exp2)
+ case exp2 => Block(x::Nil, exp2)
+ }
+ }
+ }
+
+
}
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index 44ef88c254..c777fa9347 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -14,34 +14,20 @@ import scala.tools.nsc.util.Position
* @author Burak Emir
* @version 1.0
*/
-trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
+trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes with ParallelMatching) {
import global._
import typer.typed
import symtab.Flags
- // -- begin new data structure for matcher
- /*
- abstract class Node
+ abstract class CantHandle extends Exception
+ object CantHandleUnapply extends CantHandle
+ object CantHandleApply extends CantHandle
+ object CantHandleIdent extends CantHandle
+ object CantHandleGuard extends CantHandle
+ //object CantHandleLiteral extends Exception
- class Test(var tpe: Type, var casted: Symbol) extends Node {
- var thenp: Node = _
- var vbles = List[Symbol]()
- def bindTo(v: Symbol): this.type = { vbles = v::vbles; this }
- override def toString() = tpe.toString + "?"
- }
-
- class Load(var expr: Tree) extends Node {
- def tpe = expr.tpe
- var thenp: PatNodeList = Snil
- }
-
- case class Return(b:Tree) extends Node
-
- abstract class PatNodeList
- case class Snoc(sx: PatNodeList, x:Test) extends PatNodeList
- case object Snil extends PatNodeList
-*/
- // -- end
+ var nPatterns = 0
+ var nParallel = 0
class PatternMatcher {
@@ -53,6 +39,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
/** the owner of the pattern matching expression
*/
var owner:Symbol = _
+ implicit def theOwner:Symbol = owner
/** the selector expression
*/
@@ -62,24 +49,20 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
*/
protected var root: PatternNode = _
- // statistics
- var nremoved = 0
- var nsubstituted = 0
- var nstatic = 0
-
- /** the symbol of the result variable
- */
- //protected var resultVar: Symbol = _
+ import global.{ definitions => defs }
- def defs = definitions
var handleOuter: Tree=>Tree = _
- /** init method, also needed in subclass AlgebraicMatcher
- */
+
def initialize(selector: Tree, doCheckExhaustive: Boolean, owner: Symbol, handleOuter:Tree=>Tree): Unit = {
this.owner = owner
this.doCheckExhaustive = doCheckExhaustive
this.selector = selector
this.handleOuter = handleOuter
+ if(settings.debug.value) {
+ Console.println("****")
+ Console.println("**** initalize, selector = "+selector+" selector.tpe = "+selector.tpe)
+ Console.println("**** doCheckExhaustive == "+doCheckExhaustive)
+ }
this.root = pConstrPat(selector.pos, selector.tpe.widen);
this.root.and = pHeader(selector.pos,
selector.tpe.widen,
@@ -88,233 +71,148 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
//this.optimize = this.optimize && (settings.target.value == "jvm");
}
-// ---
- /**
- * @param pos ...
- * @param tpe ...
- * @param len ...
- * @return ...
- */
- def pSequencePat(pos: PositionType, tpe: Type, len: int) = {
- //assert (tpe != null)
- val sym = newVar(FirstPos, tpe)
- val node = new SequencePat(sym, len)
- node.pos = pos
- node.tpe = tpe
- node
- }
+ // factories
- /**
- * @param pos ...
- * @param tpe ...
- * @param castedRest1 ...
- * @param minlen ...
- * @return ...
- */
- def pRightIgnoringSequencePat(pos: PositionType, tpe: Type,
- castedRest: Symbol, minlen: int) = {
- //assert (tpe != null)
- val sym = newVar(FirstPos, tpe)
- val node = new RightIgnoringSequencePat(sym, castedRest, minlen)
- node.pos = pos
- node.tpe = tpe
- node
- }
+ def pSequencePat(pos: PositionType, tpe: Type, len: int) = new SequencePat(newVar(FirstPos, tpe), len) set ((pos,tpe))
- /**
- * @param pos ...
- * @param tpe ...
- * @return ...
- */
- def pDefaultPat(pos: PositionType, tpe: Type) = {
- //assert (tpe != null)
- val node = new DefaultPat()
- node.pos = pos
- node.setType(tpe)
- node
- }
+ def pRightIgnoringSequencePat(pos: PositionType, tpe: Type, castedRest: Symbol, minlen: int) =
+ new RightIgnoringSequencePat(newVar(FirstPos, tpe), castedRest, minlen) set ((pos,tpe))
- def pConstrPat(pos: PositionType, tpe: Type) = {
- //assert (tpe != null)
- val node = new ConstrPat(newVar(pos, tpe))
- node.pos = pos
- node.setType(tpe)
- node
- }
+ def pDefaultPat(pos: PositionType, tpe: Type) = new DefaultPat() set ((pos,tpe))
- def pUnapplyPat(pos: PositionType, fn: Tree) = {
- var tpe = definitions.unapplyUnwrap(fn.tpe)
- if(definitions.isOptionOrSomeType(tpe)) {
- tpe = tpe.typeArgs.head
+ def pConstrPat(pos: PositionType, tpe: Type) = new ConstrPat(newVar(pos, tpe)) set ((pos,tpe))
+
+ def pUnapplyPat(pos: PositionType, fn: Tree) = {
+ var tpe = defs.unapplyUnwrap(fn.tpe)
+ if(defs.isOptionOrSomeType(tpe)) { tpe = tpe.typeArgs.head }
+ new UnapplyPat(newVar(pos, tpe), fn) set ((pos,tpe))
}
- val node = new UnapplyPat(newVar(pos, tpe), fn)
- node.pos = pos
- node.setType(tpe)
- //Console.println("!build unapply, fn.tpe="+fn.tpe+", casted =" + node.casted+" tpe = "+tpe)
- node
- }
- def pConstantPat(pos: PositionType, tpe: Type, value: Any) = {
- //assert (tpe != null)
- val node = new ConstantPat(value)
- node.pos = pos
- node.setType(tpe)
- node
- }
+ def pConstantPat(pos: PositionType, tpe: Type, value: Any) = new ConstantPat(value) set ((pos,tpe))
- def pVariablePat(pos: PositionType, tree: Tree) = {
- //assert (tree.tpe != null)
- val node = new VariablePat(tree)
- node.pos = pos
- node.setType(tree.tpe)
- node
- }
+ def pVariablePat(pos: PositionType, tree: Tree) = new VariablePat(tree) set ((pos,tree.tpe))
- /**
- * @param pos ...
- * @param header ...
- * @return ...
- */
- def pAltPat(pos: PositionType, header: Header) = {
- val node = new AltPat(header)
- node.pos = pos
- node.setType(header.getTpe())
- node
- }
+ def pAltPat(pos: PositionType, header: Header) = new AltPat(header) set ((pos, header.tpe))
- // factories
+ def pHeader(pos: PositionType, tpe: Type, selector: Tree) = new Header(selector, null) set ((pos,tpe))
- def pHeader(pos: PositionType, tpe: Type, selector: Tree) = {
- //assert (tpe != null)
- val node = new Header(selector, null)
- node.pos = pos
- node.setType(tpe)
- node
- }
+ def pBody(pos: PositionType) = {
+ val node = new Body(new Array[Array[ValDef]](0), new Array[Tree](0),new Array[Tree](0))
+ node.pos = pos
+ node
+ }
- def pBody(pos: PositionType) = {
- val node = new Body(new Array[Array[ValDef]](0),
- new Array[Tree](0),
- new Array[Tree](0))
- node.pos = pos
- node
- }
+ def pBody(pos: PositionType, bound: Array[ValDef], guard: Tree, body: Tree) = {
+ val node = new Body(Array(bound), Array(guard), Array(body))
+ node.pos = pos
+ node
+ }
- /**
- * @param pos ...
- * @param bound ...
- * @param guard ...
- * @param body ...
- * @return ...
- */
- def pBody(pos: PositionType, bound: Array[ValDef], guard: Tree, body: Tree) = {
- val node =
- new Body(Array(bound), Array(guard), Array(body))
- node.pos = pos
- node
- }
+ /** pretty printer */
+ def print(): Unit = Console.println(root.and.print("", new StringBuilder()).toString())
- /**
- * @param pos ...
- * @param name ...
- * @param tpe ...
- * @return ...
- */
- def newVar(pos: PositionType, name: Name, tpe: Type): Symbol = {
- val sym = owner.newVariable(pos, name) // careful: pos has special meaning
- sym.setInfo(tpe)
- sym
- }
+ // states ---
+ // states have constructors which implicitly get added to some set of states in scope
- /**
- * @param pos ...
- * @param tpe ...
- * @return ...
- */
- def newVar(pos: PositionType, tpe: Type): Symbol =
- newVar(pos, cunit.fresh.newName("temp"), tpe).setFlag(Flags.SYNTHETIC)
+ // --- states
-// ---
-/* //debug
- def squeezedBlock(vds:List[Tree], exp:Tree): Tree = {
- Block(vds, exp)
- }
-*/
- def squeezedBlock(vds:List[Tree], exp:Tree): Tree = {
- val tpe = exp.tpe
- class RefTraverser(sym:Symbol) extends Traverser {
- var nref = 0
- var nsafeRef = 0
- override def traverse(tree: Tree) = tree match {
- case t:Ident if t.symbol == sym =>
- nref = nref + 1
- if(sym.owner == currentOwner) { // oldOwner should match currentOwner
- nsafeRef = nsafeRef + 1
- } /*else if(nref == 1) {
- Console.println("sym owner: "+sym.owner+" but currentOwner = "+currentOwner)
- }*/
- 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 t if stop =>
- t
- case t =>
- super . transform (t)
+ var dfatree: Tree = null
+
+ /** enters a sequence of cases into the pattern matcher */
+ def construct(cases: List[Tree]): Unit = {
+ nPatterns = nPatterns + 1
+ try {
+ object hasUnapply extends Traverser {
+ override def traverse(x:Tree) = {
+ //Console.println("pat:'"+x+"' / "+x.getClass)
+ x match {
+ case _:UnApply => throw CantHandleUnapply
+ case Ident(n) if n!= nme.WILDCARD =>
+ DEBUG("I can't handle IDENT pattern:"+x)
+ DEBUG("x.tpe.symbols:"+x.tpe.symbol)
+ throw CantHandleIdent
+ case p:Select =>
+ //case p:Select =>
+ // DEBUG("I can't handle SELECT pattern:"+p)
+ // DEBUG("p.tpe.symbols:"+p.tpe.symbol)
+ //throw CantHandleUnapply
+ case p@Apply(_,_) if !p.tpe.symbol.hasFlag(symtab.Flags.CASE) =>
+ DEBUG("I can't handle APPLY pattern:"+p)
+ DEBUG("p.tpe.symbols:"+p.tpe.symbol)
+ throw CantHandleApply
+
+ //case p@Apply(_,_) if !p.tpe.symbol.hasFlag(symtab.Flags.CASE) => throw CantHandleUnapply //@todo
+ case _ => super.traverse(x)
+ }
+ }
}
- }
- vds match {
- case Nil => exp
-
- case (vd:ValDef) :: rest =>
- // recurse
- val exp1 = squeezedBlock(rest, exp)
-
- //Console.println("squeezedBlock for valdef "+vd)
- val sym = vd.symbol
- val rt = new RefTraverser(sym)
- rt.atOwner (PatternMatcher.this.owner) (rt.traverse(exp1))
- rt.nref match {
- case 0 =>
- nremoved = nremoved + 1
- exp1
- case 1 if rt.nsafeRef == 1 =>
- nsubstituted = nsubstituted + 1
- new Subst(sym, vd.rhs).transform( exp1 )
- case _ =>
- exp1 match {
- case Block(vds2, exp2) => Block(vd::vds2, exp2)
- case exp2 => Block(vd::Nil, exp2)
- }
+ cases foreach { case CaseDef(pat,_,_) => hasUnapply.traverse(pat) }
+ if(cases.forall{case CaseDef(_,x,_) => x == EmptyTree}) {
+ val irep = initRep(selector, cases, doCheckExhaustive)
+ val root = irep.temp.head
+
+ implicit val fail: Tree = ThrowMatchError(selector.pos, Ident(root))
+ val vdef = typed{ValDef(root, selector)}
+
+ implicit val memo = new collection.mutable.HashMap[(Symbol,Symbol),Symbol]
+ implicit val theCastMap = new collection.mutable.HashMap[(Symbol,Type),Symbol]
+ implicit val bodies = new collection.mutable.HashMap[Tree, (Tree,Tree,Symbol)]
+ val mch = typed{repToTree(irep, typed, handleOuter)}
+ dfatree = typed{squeezedBlock(List(vdef), mch)}
+
+ DEBUG("**** finished\n"+dfatree.toString)
+
+ val i = cases.findIndexOf { case CaseDef(_,_,b) => bodies.get(b).isEmpty}
+ if(i != -1) {
+ val CaseDef(_,_,b) = cases(i)
+ DEBUG("*** damn, unreachable!")
+ //for(val b <- bodies) {
+ // Console.println(b)
+ //}
+ cunit.error(b.pos, "unreachable code")
}
- case x::xs =>
- squeezedBlock(xs, exp) match {
- case Block(vds2, exp2) => Block(x::vds2, exp2)
- case exp2 => Block(x::Nil, exp2)
+
+ object resetTrav extends Traverser {
+ override def traverse(x:Tree): unit = x match {
+ case vd @ ValDef(_,_,_,_)=>
+ vd.symbol.resetFlag(symtab.Flags.CAPTURED)
+ if(vd.symbol.hasFlag(symtab.Flags.TRANS_FLAG)) {
+ vd.symbol.resetFlag(symtab.Flags.TRANS_FLAG)
+ vd.symbol.resetFlag(symtab.Flags.MUTABLE)
+ }
+ case _ =>
+ super.traverse(x)
+ }
}
- }
- }
+ resetTrav.traverse(dfatree)
-// ---
- /** pretty printer
- */
- def print(): Unit =
- Console.println(root.and.print("", new StringBuilder()).toString())
+ //constructParallel(cases) // ZZZ
+ nParallel = nParallel + 1
+ return
+ } else throw CantHandleGuard
+ } catch {
+ case e: CantHandle => // fall back
+ DEBUG("****")
+ DEBUG("**** falling back, "+e.getClass)
+ DEBUG("****")
- /** enters a sequence of cases into the pattern matcher
- */
- def construct(cases: List[Tree]): Unit =
+ case CantHandleGuard => // fall back (actually already fell back before)
+ case e =>
+
+ if(settings.debug.value) {
+ e.printStackTrace()
+ Console.println("****")
+ Console.println("**** falling back, cause " + e.getMessage)
+ Console.println("****")
+ for(val CaseDef(pat,guard,_) <- cases)
+ Console.println(pat.toString)
+ }
+ }
+ doCheckExhaustive = false
cases foreach enter
+ }
- /** enter a single case into the pattern matcher
- */
+ /** enter a single case into the pattern matcher */
protected def enter(caseDef: Tree): Unit = caseDef match {
case CaseDef(pat, guard, body) =>
val env = new CaseEnv
@@ -333,7 +231,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
//
//print()
//cunit.error(pat.pos, "duplicate case")
- h.or = pDefaultPat(caseDef.pos, target.getTpe)
+ h.or = pDefaultPat(caseDef.pos, target.tpe)
h.or.and = pBody(caseDef.pos, env.getBoundVars(), guard, body)
//print()
//Console.println("tao = "+target.and.or)
@@ -363,40 +261,6 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
tree.body = nb
}
- /** returns the child patterns of a pattern
- */
- protected def patternArgs(tree: Tree): List[Tree] = {
- //Console.println("patternArgs "+tree.toString())
- val res = tree match {
- case Bind(_, pat) =>
- patternArgs(pat)
-
- case a @ Apply(_, List(av @ ArrayValue(_, ts)))
- if isSeqApply(a) && isRightIgnoring(av) =>
- ts.reverse.drop(1).reverse
-
- case a @ Apply(_, List(av @ ArrayValue(_, ts))) if isSeqApply(a) =>
- ts
-
- case a @ Apply(_, args) =>
- args
-
- case a @ UnApply(_, args) =>
- args
-
- case av @ ArrayValue(_, ts) if isRightIgnoring(av) =>
- ts.reverse.drop(1).reverse
-
- case av @ ArrayValue(_, ts) =>
- ts
-
- case _ =>
- List()
- }
- //Console.println("patternArgs returns "+res.toString())
- res
- }
-
protected def patternNode(tree:Tree , header:Header , env: CaseEnv ): PatternNode = {
//Console.println("patternNode("+tree+","+header+")");
//else scala.Predef.error("got null tree in patternNode");
@@ -404,21 +268,15 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
//Console.println("tree.getClass() "+tree.getClass());
val t = tree match {
case Bind(name, Typed(Ident( nme.WILDCARD ), tpe)) => // x@_:Type
- val tpe2test = tree.symbol.tpe // safest! typer does not always use tpe.tpe!
-
- // @todo: this optimization probably not allowed, because of null -- but can rework it
- //if (isSubType(header.getTpe(), tpe2test)) {
- // val node = pDefaultPat(tree.pos, tpe2test)
- // env.newBoundVar(tree.symbol, tree.tpe, header.selector)
- // node
- //} else {
- val node = pConstrPat(tree.pos, tpe2test)
- env.newBoundVar( tree.symbol, tpe2test, typed(Ident( node.casted )));
- node
- //}
+ // @note: safest! typer does not always use tpe.tpe, e.g. in the case of refinement type tests
+ val tpe2test = tree.symbol.tpe
+ // @note: if (isSubType(header.tpe, tpe2test)) then this will be translated to isNull test
+ val node = pConstrPat(tree.pos, tpe2test)
+ env.newBoundVar( tree.symbol, tpe2test, typed(Ident( node.casted )));
+ node
case Bind(name, Ident(nme.WILDCARD)) => // x @ _
- val node = pDefaultPat(tree.pos, header.getTpe())
+ val node = pDefaultPat(tree.pos, header.tpe)
if ((env ne null) && (tree.symbol != defs.PatternWildcard))
env.newBoundVar( tree.symbol, tree.tpe, header.selector);
node
@@ -471,12 +329,12 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
pConstrPat(tree.pos, tree.tpe);
}
case Typed(Ident( nme.WILDCARD ), tpe) => // x@_:Type
- val doTest = isSubType(header.getTpe(), tpe.tpe) // this is already an optimization
+ val doTest = isSubType(header.tpe, tpe.tpe) // this is already an optimization
if (doTest) pDefaultPat(tree.pos, tpe.tpe)
else pConstrPat(tree.pos, tpe.tpe)
case t @ Typed(ident, tpe) => // variable pattern
- // can't optimize using isSubType(header.getTpe(),tpe.tpe);
+ // can't optimize using isSubType(header.tpe,tpe.tpe);
// leave that (null check!) for later
val node =
pConstrPat(tree.pos, tpe.tpe)
@@ -488,7 +346,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
}
node
- case Ident(nme.WILDCARD) => pDefaultPat(tree.pos, header.getTpe())
+ case Ident(nme.WILDCARD) => pDefaultPat(tree.pos, header.tpe)
case Ident(name) => // pattern without args or named constant
assert(!tree.symbol.isPrimaryConstructor) // may not happen
@@ -521,8 +379,8 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
case Alternative(ts) =>
if (ts.length < 2)
Predef.error("ill-formed Alternative")
- val subroot = pConstrPat(header.pos, header.getTpe())
- subroot.and = { val h = pHeader(header.pos, header.getTpe(), header.selector.duplicate); h.isSubHeader = true; h }
+ val subroot = pConstrPat(header.pos, header.tpe)
+ subroot.and = { val h = pHeader(header.pos, header.tpe, header.selector.duplicate); h.isSubHeader = true; h }
val subenv = new CaseEnv
var i = 0; while (i < ts.length) {
val target = enter1(ts(i), -1, subroot, subroot.casted, subenv)
@@ -561,15 +419,14 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
enter1(pat, index, target, casted, env)
}
+ type SelectorMap = collection.mutable.HashMap[(Symbol,Symbol),List[Symbol]]
+ val selectorMap = new SelectorMap
+
private def newHeader(pos: PositionType, casted: Symbol, index: Int): Header = {
//Console.println("newHeader(pos,"+casted+" (has CASE flag? "+casted.tpe.symbol.hasFlag(Flags.CASE)+") of type "+casted.tpe+" with pos "+casted.pos+"(equals FIRSTPOS? "+(casted.pos == Position.FIRSTPOS)+"),"+index+")");
val ident = typed(Ident(casted))
if (casted.pos == Position.FIRSTPOS) { // load the result of casted(i)
//Console.println("FIRSTPOS");
-
- //Console.println("DEBUG")
- //Console.println()
-
val t = typed(
Apply(Select(ident, ident.tpe.member(nme.apply)),
List(Literal(Constant(index)))))
@@ -630,14 +487,14 @@ print()
// special case List()
pat match {
- case UnApply(fn, List(ArrayValue(zs, List()))) if isSameType(definitions.ListModule.tpe, fn.symbol.owner.tpe) =>
- return enter1(posAssigner.atPos(pat.pos){gen.mkAttributedRef(definitions.NilModule)}, index, target, casted, env)
+ case UnApply(fn, List(ArrayValue(zs, List()))) if isSameType(defs.ListModule.tpe, fn.symbol.owner.tpe) =>
+ return enter1(posAssigner.atPos(pat.pos){gen.mkAttributedRef(defs.NilModule)}, index, target, casted, env)
/*
- case UnApply(fn, List(ArrayValue(zs, pats))) if isSameType(definitions.ListModule.tpe, fn.symbol.owner.tpe) =>
+ case UnApply(fn, List(ArrayValue(zs, pats))) if isSameType(defs.ListModule.tpe, fn.symbol.owner.tpe) =>
Console.println("special case List"+pats)
Console.println("special case zs = "+zs)
def makeConsPat(p:Tree) = {
- val constpe = typeRef(definitions.ConsClass.tpe.prefix, definitions.ConsClass, List(zs.tpe))
+ val constpe = typeRef(defs.ConsClass.tpe.prefix, defs.ConsClass, List(zs.tpe))
val patNode = pConstrPat(pat.pos, )
patNode.and = newHeader(pat.pos, )
}
@@ -684,7 +541,13 @@ print()
target.and = curHeader; // (*)
//Console.println("curHeader : "+curHeader)
-
+/* first try at exhaust improvement
+ selectorMap.update((casted, curHeader.selector.symbol),
+ selectorMap.get(casted, curHeader.selector.symbol) match {
+ case Some(xs) => pat.tpe.symbol::xs
+ case _ => pat.tpe.symbol::Nil
+ })
+*/
if (bodycond ne null) target.and = bodycond(target.and) // restores body with the guards
curHeader.or = patternNode(pat, curHeader, env)
@@ -713,7 +576,7 @@ print()
(patNode.isDefaultPat() || next.subsumes(patNode)))) {
// new node is default or subsumed
var header = pHeader(patNode.pos,
- curHeader.getTpe(),
+ curHeader.tpe,
curHeader.selector);
{curHeader.next = header; header};
header.or = patNode;
@@ -792,6 +655,9 @@ print()
//////////// generator methods
def toTree(): Tree = {
+ if(dfatree != null) {
+ return dfatree
+ }
val t = if (isSimpleIntSwitch())
intSwitchToTree()
// else if (false && optimize && isSimpleSwitch())
@@ -822,7 +688,7 @@ print()
case VariablePat(tree) =>
//Konsole.println(((tree.symbol.flags & Flags.CASE) != 0));
case ConstrPat(_) =>
- //Konsole.println(node.getTpe().toString() + " / " + ((node.getTpe().symbol.flags & Flags.CASE) != 0));
+ //Konsole.println(node.tpe.toString() + " / " + ((node.tpe.symbol.flags & Flags.CASE) != 0));
var inner = node.and;
def funct(inner: PatternNode): Boolean = {
//outer: while (true)
@@ -899,7 +765,7 @@ print()
/** This method translates pattern matching expressions that match
* on integers on the top level.
*/
- def intSwitchToTree(): Tree = {
+ private def intSwitchToTree(): Tree = {
def insert1(tag: Int, body: Tree, current: TagBodyPair): TagBodyPair = {
if (current eq null)
new TagBodyPair(tag, body, null)
@@ -1008,7 +874,7 @@ print()
var exit: Symbol = null
/** simple optimization: if the last pattern is `case _' (no guards), we won't generate the ThrowMatchError
*/
- def generalSwitchToTree(): Tree = {
+ private def generalSwitchToTree(): Tree = {
this.exit = owner.newLabel(root.pos, "exit").setInfo(new MethodType(List(resultType), resultType));
val result = exit.newValueParameter(root.pos, "result").setInfo( resultType );
squeezedBlock(
@@ -1128,6 +994,7 @@ print()
return false
}
+ //@todo: can this be simplified? (in particular: drop "dup" method)
protected def toOptTree(node1: PatternNode, selector: Tree): Tree = {
def insert2(tag: Int, node: PatternNode, current: TagNodePair): TagNodePair = {
if (current eq null)
@@ -1143,7 +1010,7 @@ print()
}
def insertNode(tag: int, node: PatternNode, current:TagNodePair): TagNodePair = {
- val newnode = node.dup()
+ val newnode = node.dup
newnode.or = null
insert2(tag, newnode, current)
}
@@ -1154,15 +1021,15 @@ print()
while (node ne null)
node match {
case ConstrPat(casted) =>
- cases = insertNode(node.getTpe().symbol.tag, node, cases)
+ cases = insertNode(node.tpe.symbol.tag, node, cases)
node = node.or
case DefaultPat() =>
defaultCase = node
node = node.or
- case VariablePat(tree) if node.getTpe.symbol.hasFlag(Flags.CASE) =>
- cases = insertNode(node.getTpe().symbol.tag, node, cases)
+ case VariablePat(tree) if node.tpe.symbol.hasFlag(Flags.CASE) =>
+ cases = insertNode(node.tpe.symbol.tag, node, cases)
node = node.or
case _ =>
@@ -1237,6 +1104,7 @@ print()
case e =>
Console.println("failed with "+e.getMessage()+" on: "+t)
+ //System.exit(-1)
//null
t
}
@@ -1253,7 +1121,7 @@ print()
case DefaultPat() =>
return toTree(node.and);
- case UnapplyPat(casted, Apply(fn1, _)) if casted.tpe.symbol == definitions.BooleanClass => // special case
+ case UnapplyPat(casted, Apply(fn1, _)) if casted.tpe.symbol == defs.BooleanClass => // special case
var useSelector = selector
val checkType = fn1.tpe match {
case MethodType(List(argtpe),_) =>
@@ -1295,20 +1163,12 @@ print()
toTree(node.or, selector.duplicate))
case ConstrPat(casted) =>
- def outerAlwaysEqual(left: Type, right: Type) = (left,right) match {
- case (TypeRef(lprefix, _,_), TypeRef(rprefix,_,_)) if lprefix =:= rprefix =>
- true
- case _ =>
- if(settings.XprintOuterMatches.value)
- cunit.warning(node.pos, "can't be sure statically that these outers are equal:"+(left,right).toString)
- false
- }
- val ntpe = node.getTpe
+ val ntpe = node.tpe
var cond: Tree = null
// if type 2 test is same as static type, then just null test
- if(isSubType(selector.tpe, ntpe) && isSubType(ntpe, definitions.AnyRefClass.tpe)) {
+ if(isSubType(selector.tpe, ntpe) && isSubType(ntpe, defs.AnyRefClass.tpe)) {
cond = NotNull(selector.duplicate)
nstatic = nstatic + 1
} else if(ignoreSelectorType) {
@@ -1319,9 +1179,11 @@ print()
// compare outer instance for patterns like foo1.Bar foo2.Bar if not statically known to match
casted.tpe match {
- case TypeRef(prefix,_,_) if
- (prefix.symbol.isTerm && !prefix.symbol.isPackage)
- &&(!outerAlwaysEqual(casted.tpe, selector.tpe)) =>
+ case TypeRef(prefix,_,_) if needsOuterTest(casted.tpe, selector.tpe) =>
+
+ //@attention, deep typer bug: if we omit "typed" here, we crash when typing the tree that contains this fragment
+ cond = typed{ addOuterCondition(cond, casted.tpe, selector.duplicate, handleOuter) }
+ /*
var theRef = gen.mkAttributedRef(prefix.prefix, prefix.symbol)
// needs explicitouter treatment
@@ -1329,29 +1191,25 @@ print()
val outerAcc = outerAccessor(casted.tpe.symbol)
- //if(settings.XprintOuterMatches.value)
- // cunit.warning(node.pos, "outer match "+outerAcc)
-
if(outerAcc != NoSymbol) { // some guys don't have outers
cond = And(cond,
Eq(Apply(Select(
typed(gen.mkAsInstanceOf(selector.duplicate, ntpe, true)), outerAcc),List()), theRef))
- } else if(settings.XprintOuterMatches.value) {
- cunit.warning(node.pos, " no outer accessor for "+casted.tpe.symbol+" of type "+casted.tpe)
}
+ */
case _ =>
//ignore ;
}
- val succ = squeezedBlock(List(ValDef(casted,
- if(isSubType(selector.tpe,ntpe)) selector.duplicate else typed(gen.mkAsInstanceOf(selector.duplicate, ntpe, true)))),
+ val succ = squeezedBlock(List(typed {ValDef(casted,
+ if(isSubType(selector.tpe,ntpe)) selector.duplicate else typed(gen.mkAsInstanceOf(selector.duplicate, ntpe, true)))}),
toTree(node.and))
val fail = toTree(node.or, selector.duplicate)
return myIf(cond, succ, fail)
case SequencePat(casted, len) =>
- val ntpe = node.getTpe
+ val ntpe = node.tpe
val tpetest =
if(!isSubType(selector.tpe, ntpe))
@@ -1376,7 +1234,7 @@ print()
case RightIgnoringSequencePat(casted, castedRest, minlen) =>
- val ntpe = node.getTpe
+ val ntpe = node.tpe
val tpetest =
if(!isSubType(selector.tpe,ntpe))
@@ -1417,7 +1275,7 @@ print()
case VariablePat(tree) =>
// objects are compared by eq, not ==
- val cmp = if(tree.tpe.symbol.isModuleClass && selector.tpe <:< definitions.AnyRefClass.tpe)
+ val cmp = if(tree.tpe.symbol.isModuleClass && selector.tpe <:< defs.AnyRefClass.tpe)
Eq(selector.duplicate, tree)
else
Equals(selector.duplicate, tree)
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 25436e3ba8..7f80ab47a7 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -15,6 +15,32 @@ trait PatternNodes requires transform.ExplicitOuter {
type SymSet = collection.immutable.Set[Symbol]
+ /** returns the child patterns of a pattern
+ */
+ protected def patternArgs(tree: Tree): List[Tree] = { //Console.println("patternArgs "+tree.toString())
+ /*val res = */ tree match {
+ case Bind(_, pat) => patternArgs(pat)
+
+ case a @ Apply(_, List(av @ ArrayValue(_, ts))) if isSeqApply(a) && isRightIgnoring(av) =>
+ ts.reverse.drop(1).reverse
+
+ case a @ Apply(_, List(av @ ArrayValue(_, ts))) if isSeqApply(a) =>
+ ts
+
+ case a @ Apply(_, args) => args
+
+ case a @ UnApply(_, args) => args
+
+ case av @ ArrayValue(_, ts) if isRightIgnoring(av) =>
+ ts.reverse.drop(1).reverse
+
+ case av @ ArrayValue(_, ts) => ts
+
+ case _ => List()
+ }
+ //Console.println("patternArgs returns "+res.toString()) ; res
+ }
+
/** Intermediate data structure for algebraic + pattern matcher
*/
sealed class PatternNode {
@@ -53,9 +79,7 @@ trait PatternNodes requires transform.ExplicitOuter {
null
}
- def getTpe(): Type = tpe
-
- def setType(tpe: Type): Unit = { this.tpe = tpe }
+ def set(p:(PositionType,Type)): this.type = { /*assert(tpe ne null); */ this.pos = p._1; this.tpe = p._2; this }
def dup(): PatternNode = {
var res: PatternNode = this match {
@@ -76,15 +100,15 @@ trait PatternNodes requires transform.ExplicitOuter {
case AltPat(subheader) =>
AltPat(subheader)
case _ =>
- error(""); null
+ error("unexpected pattern"); null
}
- res.pos = pos
- res.tpe = tpe
+ res set ((pos, tpe))
res.or = or
res.and = and
res
}
+ /*
def _symbol: Symbol = this match { // @todo
case UnapplyPat(casted, fn) =>
casted
@@ -97,6 +121,7 @@ trait PatternNodes requires transform.ExplicitOuter {
case _ =>
NoSymbol //.NONE
}
+ */
def nextH(): PatternNode = this match {
case _h:Header => _h.next
@@ -116,14 +141,14 @@ trait PatternNodes requires transform.ExplicitOuter {
case ConstrPat(_) =>
q match {
case ConstrPat(_) =>
- isSameType(q.getTpe(), this.getTpe())
+ isSameType(q.tpe, this.tpe)
case _ =>
false
}
case SequencePat(_, plen) =>
q match {
case SequencePat(_, qlen) =>
- (plen == qlen) && isSameType(q.getTpe(), this.getTpe())
+ (plen == qlen) && isSameType(q.tpe, this.tpe)
case _ =>
false
}
@@ -144,14 +169,14 @@ trait PatternNodes requires transform.ExplicitOuter {
case ConstrPat(_) =>
q match {
case ConstrPat(_) =>
- isSubType(q.getTpe(), this.getTpe())
+ isSubType(q.tpe, this.tpe)
case _ =>
false
}
case SequencePat(_, plen) =>
q match {
case SequencePat(_, qlen) =>
- (plen == qlen) && isSubType(q.getTpe(), this.getTpe())
+ (plen == qlen) && isSubType(q.tpe, this.tpe)
case _ =>
false
}
@@ -226,7 +251,7 @@ trait PatternNodes requires transform.ExplicitOuter {
case _h: Header =>
val selector = _h.selector
val next = _h.next
- sb.append(indent + "HEADER(" + patNode.getTpe() +
+ sb.append(indent + "HEADER(" + patNode.tpe +
", " + selector + ")").append('\n')
if(patNode.or ne null) patNode.or.print(indent + "|", sb)
if (next ne null)
@@ -234,16 +259,16 @@ trait PatternNodes requires transform.ExplicitOuter {
else
sb
case ConstrPat(casted) =>
- val s = ("-- " + patNode.getTpe().symbol.name +
- "(" + patNode.getTpe() + ", " + casted + ") -> ")
+ val s = ("-- " + patNode.tpe.symbol.name +
+ "(" + patNode.tpe + ", " + casted + ") -> ")
val nindent = newIndent(s)
sb.append(nindent + s).append('\n')
patNode.and.print(nindent, sb)
cont
case SequencePat( casted, plen ) =>
- val s = ("-- " + patNode.getTpe().symbol.name + "(" +
- patNode.getTpe() +
+ val s = ("-- " + patNode.tpe.symbol.name + "(" +
+ patNode.tpe +
", " + casted + ", " + plen + ") -> ")
val nindent = newIndent(s)
sb.append(indent + s).append('\n')
@@ -251,8 +276,8 @@ trait PatternNodes requires transform.ExplicitOuter {
cont
case RightIgnoringSequencePat( casted, castedRest, plen ) =>
- val s = ("-- ri " + patNode.getTpe().symbol.name + "(" +
- patNode.getTpe() +
+ val s = ("-- ri " + patNode.tpe.symbol.name + "(" +
+ patNode.tpe +
", " + casted + ", " + plen + ") -> ")
val nindent = newIndent(s)
sb.append(indent + s).append('\n')
@@ -274,7 +299,7 @@ trait PatternNodes requires transform.ExplicitOuter {
cont
case VariablePat(tree) =>
- val s = "-- STABLEID(" + tree + ": " + patNode.getTpe() + ") -> "
+ val s = "-- STABLEID(" + tree + ": " + patNode.tpe + ") -> "
val nindent = newIndent(s)
sb.append(indent + s).append('\n')
patNode.and.print(nindent, sb)
@@ -334,7 +359,7 @@ trait PatternNodes requires transform.ExplicitOuter {
def optimize1(): (Boolean, SymSet, SymSet) = {
import symtab.Flags
- val selType = this.getTpe
+ val selType = this.tpe
if (!isSubType(selType, definitions.ScalaObjectClass.tpe))
return (false, null, emptySymbolSet)
@@ -364,17 +389,17 @@ trait PatternNodes requires transform.ExplicitOuter {
//Console.println("traverse, alts="+alts)
alts match {
case ConstrPat(_) =>
- //Console.print("ConstPat! of"+alts.getTpe.symbol)
- if (alts.getTpe.symbol.hasFlag(Flags.CASE)) {
- coveredCases = coveredCases + alts.getTpe.symbol
- remainingCases = remainingCases - alts.getTpe.symbol
+ //Console.print("ConstPat! of"+alts.tpe.symbol)
+ if (alts.tpe.symbol.hasFlag(Flags.CASE)) {
+ coveredCases = coveredCases + alts.tpe.symbol
+ remainingCases = remainingCases - alts.tpe.symbol
cases = cases + 1
} else {
val covered = remainingCases.filter { x =>
//Console.println("x.tpe is "+x.tpe)
- val y = alts.getTpe.prefix.memberType(x)
- //Console.println(y + " is sub of "+alts.getTpe+" ? "+isSubType(y, alts.getTpe));
- isSubType(y, alts.getTpe)
+ val y = alts.tpe.prefix.memberType(x)
+ //Console.println(y + " is sub of "+alts.tpe+" ? "+isSubType(y, alts.tpe));
+ isSubType(y, alts.tpe)
}
//Console.println(" covered : "+covered)
@@ -466,11 +491,6 @@ trait PatternNodes requires transform.ExplicitOuter {
private var boundVars: Array[ValDef] = new Array[ValDef](4)
private var numVars = 0
- /** substitutes a symbol on the right hand side of a ValDef
- *
- * @param oldSymm ...
- * @param newInit ...
- */
def substitute(oldSym: Symbol, newInit: Tree): Unit = {
var i = 0; while (i < numVars) {
if (boundVars(i).rhs.symbol == oldSym) {
@@ -481,11 +501,6 @@ trait PatternNodes requires transform.ExplicitOuter {
}
}
- /**
- * @param sym ...
- * @param tpe ...
- * @param init ...
- */
def newBoundVar(sym: Symbol, tpe: Type, init: Tree): Unit = {
//if(sym == Symbol.NoSymbol ) {
// scala.Predef.Error("can't add variable with NoSymbol");
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index b07228c305..705bdaaedf 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -9,14 +9,14 @@ package scala.tools.nsc.transform
import symtab._
import Flags._
import scala.collection.mutable.{HashMap, ListBuffer}
-import matching.{TransMatcher, PatternNodes, CodeFactory, PatternMatchers}
+import matching.{TransMatcher, PatternNodes, CodeFactory, ParallelMatching, PatternMatchers}
/** This class ...
*
* @author Martin Odersky
* @version 1.0
*/
-abstract class ExplicitOuter extends InfoTransform with TransMatcher with PatternNodes with CodeFactory with PatternMatchers with TypingTransformers {
+abstract class ExplicitOuter extends InfoTransform with TransMatcher with PatternNodes with CodeFactory with PatternMatchers with ParallelMatching with TypingTransformers {
import global._
import definitions._
import posAssigner.atPos
@@ -65,71 +65,6 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
}
}
-// <removeOption>
- /** returns true if tpe was a real option type at prev phase, i.e.
- * one that admits to extract an element type.
- * @return true for real option type, false for all others, in particular None, scala.None.type, object scala.None
- */
- def wasOption(tpe: Type): Boolean = ( tpe ne null ) && (tpe match {
- case NoType =>
- false
- case SingleType(_,sym) if sym eq definitions.NoneClass =>
- false
-
- case ThisType(sym) if sym eq definitions.SomeClass => // also eliminate Option.this.type?
- false
-
- case SuperType(_,_) =>
- false
-
- case _ =>
- if(definitions.NoneClass eq tpe.symbol.linkedModuleOfClass) {
- return false
- }
- var res: Option[Boolean] = None
- atPhase(phase.prev) {
- val it = tpe.baseClasses.elements; while(it.hasNext && res.isEmpty) {
- val tp = it.next
- if(tp.linkedModuleOfClass eq definitions.NoneClass) {
- res = Some(false) // extremely rare, only appears in refinements, see dbc library
- }
- else if(definitions.isOptionType(tp.tpe)) {
- res = Some(true)
- }
- }
- }
- return if(res.isEmpty) false else res.get
- })
-
- /** like @see wasOption, additionally tests whether argument is a reference type
- */
- def wasOptionRef(tpe:Type): Boolean = try {
- wasOption(tpe) && isSubType(getOptionArg(tpe), definitions.AnyRefClass.tpe)
- } catch {
- case e =>
- atPhase(phase.prev) {
- e.printStackTrace()
- Console.println("boom"+e.getMessage()+" tpe is "+tpe)
- Console.println("baseclasses are "+tpe.baseClasses)
- }
- System.exit(-1)
- false
- }
-
- /** @precond wasOption(tpe)
- */
- def getOptionArg(tpe:Type): Type = {
- //Console.println("huh?"+wasOption(tpe)+" bah: "+tpe)
- if (tpe.isInstanceOf[SingleType])
- getOptionArg(atPhase(phase.prev){tpe.widen})
- else if(tpe.symbol != null && tpe.symbol.isRefinementClass) {
- getOptionArg(tpe.baseType(definitions.OptionClass))
- } else {
- atPhase(phase.prev){tpe}.typeArgs(0)
- }
- }
-
-//</removeOption>
/** <p>
* The type transformation method:
* </p>
@@ -170,7 +105,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
*/
def transformInfo(sym: Symbol, tp: Type): Type = tp match {
case MethodType(formals, restpe1) =>
- val restpe = transformInfo(sym, restpe1) // removeOption
+ val restpe = transformInfo(sym, restpe1)
if (sym.owner.isTrait && ((sym hasFlag SUPERACCESSOR) || sym.isModule)) { // 5
sym.makeNotPrivate(sym.owner)
}
@@ -178,7 +113,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
if (sym.isClassConstructor && isInner(sym.owner)) // 1
MethodType(sym.owner.outerClass.thisType :: formals, restpe)
else if (restpe ne restpe1)
- MethodType(formals, restpe) // removeOption
+ MethodType(formals, restpe)
else tp
case ClassInfoType(parents, decls, clazz) =>
var decls1 = decls
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3ffb1e10bf..f591768e15 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1353,7 +1353,8 @@ trait Typers requires Analyzer {
if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
(e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
if (!e.sym.isErroneous && !e1.sym.isErroneous)
- error(e.sym.pos, e1.sym+" is defined twice");
+ error(e.sym.pos, e1.sym+" is defined twice"+
+ {if(!settings.debug.value) "" else " in "+unit.toString});
e1 = scope.lookupNextEntry(e1);
}
e = e.next
diff --git a/src/library/scala/testing/SUnit.scala b/src/library/scala/testing/SUnit.scala
index 87c8fee0e1..07a7fa0d1b 100644
--- a/src/library/scala/testing/SUnit.scala
+++ b/src/library/scala/testing/SUnit.scala
@@ -70,11 +70,9 @@ object SUnit {
*
* @param name ...
*/
- class TestCase(val name: String) extends Test with Assert {
+ abstract class TestCase(val name: String) extends Test with Assert {
- protected def createResult() = new TestResult()
-
- protected def runTest(): Unit = {}
+ protected def runTest(): Unit
def run(r: TestResult): Unit =
try {
@@ -83,8 +81,6 @@ object SUnit {
case t:Throwable => r.addFailure(this, t)
}
- def run(): Unit = run(createResult())
-
def setUp() = {}
def tearDown() = {}
@@ -125,7 +121,7 @@ object SUnit {
class TestSuite(tests:Test*) extends Test {
def this(names: Seq[String], constr: String => Test) =
- this((names.toList map constr):_*)
+ this((names map constr):_*)
val buf = new ArrayBuffer[Test]()
diff --git a/test/files/jvm/unittest_io.scala b/test/files/jvm/unittest_io.scala
index 59b82ff57e..f4f2e08c7c 100644
--- a/test/files/jvm/unittest_io.scala
+++ b/test/files/jvm/unittest_io.scala
@@ -1,7 +1,11 @@
-object Test {
+import scala.testing.SUnit._
+import scala.io.Source
- import scala.testing.SUnit._
- import scala.io.Source
+object Test extends TestConsoleMain {
+
+ def suite = new TestSuite(
+ new ReadlinesTest
+ )
class ReadlinesTest extends TestCase("scala.io.Source method getLines") {
@@ -11,20 +15,10 @@ it is split on several lines.
isn't it?
""")
- assertEquals("wrong number of lines",src.getLines.toList.length,5) // five new lines in there
+ def runTest() = assertEquals("wrong number of lines",src.getLines.toList.length,5) // five new lines in there
//for(val line <- src.getLines) {
// Console.print(line)
//}
}
- def main(args:Array[String]) = {
- val ts = new TestSuite(
- new ReadlinesTest
- )
- val tr = new TestResult()
- ts.run(tr)
- for(val failure <- tr.failures) {
- Console.println(failure)
- }
- }
}
diff --git a/test/files/jvm/unittest_xml.scala b/test/files/jvm/unittest_xml.scala
index 312b69d529..6fdacbbf75 100644
--- a/test/files/jvm/unittest_xml.scala
+++ b/test/files/jvm/unittest_xml.scala
@@ -64,6 +64,7 @@ object Test {
}
class UtilityTest extends TestCase("scala.xml.Utility") with Assert {
+ def runTest() = {
val x = <foo>
<toomuchws/>
</foo>
@@ -92,6 +93,7 @@ object Test {
assertEquals("pretty print sorted attrib:"+pp.format(q), "<a a=\"2\" g=\"3\" j=\"2\" oo=\"2\"></a>", pp.format(q))
}
+ }
def main(args:Array[String]) = {
val ts = new TestSuite(
diff --git a/test/files/jvm/xml01.scala b/test/files/jvm/xml01.scala
index 8c99cfd358..7de6211e29 100644
--- a/test/files/jvm/xml01.scala
+++ b/test/files/jvm/xml01.scala
@@ -209,6 +209,8 @@ object Test {
//Console.println("char '"+c+"' \u015e");
assertTrue(c == '\u015e');
}
+ // buraq: if the following test fails with 'character x not allowed', it is
+ // related to the mutable variable in a closures in MarkupParser.parsecharref
{
val isr = scala.io.Source.fromString(xmlAttrValueNorm);
val pxmlB = scala.xml.parsing.ConstructingParser.fromSource(isr,false);
diff --git a/test/files/neg/patmatexhaust.check b/test/files/neg/patmatexhaust.check
index 19e79b2928..719f98b8d3 100644
--- a/test/files/neg/patmatexhaust.check
+++ b/test/files/neg/patmatexhaust.check
@@ -1,23 +1,27 @@
-patmatexhaust.scala:8: warning: does not cover case {object Baz}
+patmatexhaust.scala:7: warning: match is not exhaustive!
+missing combination Baz
+
def ma1(x:Foo) = x match {
^
-patmatexhaust.scala:12: warning: does not cover case {class Bar}
+patmatexhaust.scala:11: warning: match is not exhaustive!
+missing combination Bar
+
def ma2(x:Foo) = x match {
^
-patmatexhaust.scala:24: warning: does not cover case {class Kult}
- case (Kult(_), Qult()) => // Kult missing
- ^
-patmatexhaust.scala:26: warning: does not cover case {class Qult}
- case (Qult(), Kult(_)) => // Qult missing
- ^
-patmatexhaust.scala:44: warning: does not cover cases {object Gu,class Gp}
+patmatexhaust.scala:23: warning: match is not exhaustive!
+missing combination Kult Kult
+missing combination Qult Qult
+
+ def ma3(x:Mult) = (x,x) match { // not exhaustive
+ ^
+patmatexhaust.scala:49: warning: match is not exhaustive!
+missing combination Gu
+missing combination Gp
+
def ma4(x:Deep) = x match { // missing cases: Gu, Gp
^
-patmatexhaust.scala:51: warning: does not cover case {class Gp}
- case Ga =>
- ^
-patmatexhaust.scala:65: error: unreachable code
+patmatexhaust.scala:70: error: unreachable code
case 1 =>
^
-6 warnings found
+four warnings found
one error found
diff --git a/test/files/neg/patmatexhaust.scala b/test/files/neg/patmatexhaust.scala
index 204bf2f170..b2d0b8ddd2 100644
--- a/test/files/neg/patmatexhaust.scala
+++ b/test/files/neg/patmatexhaust.scala
@@ -1,5 +1,4 @@
class TestSealedExhaustive { // compile only
-
sealed class Foo
case class Bar(x:Int) extends Foo
@@ -20,6 +19,7 @@ class TestSealedExhaustive { // compile only
def ma33(x:Kult) = x match { // exhaustive
case Kult(_) => // exhaustive
}
+
def ma3(x:Mult) = (x,x) match { // not exhaustive
case (Kult(_), Qult()) => // Kult missing
//case Pair(Kult(_), Kult(_)) =>
@@ -27,6 +27,11 @@ class TestSealedExhaustive { // compile only
//case Pair(Qult(), Qult()) =>
}
+ def ma3u(x:Mult) = ((x,x) : @unchecked) match { // not exhaustive, but not checked!
+ case (Kult(_), Qult()) =>
+ case (Qult(), Kult(_)) =>
+ }
+
sealed class Deep
case object Ga extends Deep
@@ -64,4 +69,5 @@ class TestSealedExhaustive { // compile only
case 1 =>
case 1 =>
}
+
}
diff --git a/test/files/pos/patterns.scala b/test/files/pos/patterns.scala
index 85d8a1b7da..547d692d87 100644
--- a/test/files/pos/patterns.scala
+++ b/test/files/pos/patterns.scala
@@ -27,3 +27,12 @@ object test {
case None => println("nothing")
}
}
+
+// if bodies are duplicated, then we would get an error like "double definition"
+
+trait John[A,B] {
+ def filter(x:Any) = x match {
+ case (x::xs, _) => "ga"
+ case _ => {x:String => "foobar"}
+ }
+}
diff --git a/test/files/run/bug789.scala b/test/files/run/bug789.scala
index 5a3c8d61e8..8cd4102dcf 100644
--- a/test/files/run/bug789.scala
+++ b/test/files/run/bug789.scala
@@ -22,7 +22,6 @@ object Test { // don't do this at home
case _ => "n.a."
}
-
def main(args:Array[String]): Unit = {
// make up some class that has a size
class MyNode extends SizeImpl
diff --git a/test/files/run/patmatnew.scala b/test/files/run/patmatnew.scala
index daa1f9898a..46e980dff0 100644
--- a/test/files/run/patmatnew.scala
+++ b/test/files/run/patmatnew.scala
@@ -13,20 +13,16 @@ trait Shmeez extends AnyRef with Treez {
}
}
-object Test {
- import scala.testing.SUnit._
+import scala.testing.SUnit._
- def main(args:Array[String]): Unit = {
- val tr = new TestResult
- new TestSuite(
+object Test extends TestConsoleMain {
+
+ def suite = new TestSuite(
new TestSimpleIntSwitch,
new Test717,
new TestGuards
- ).run(tr)
+ )
- for(val f <- tr.failures())
- Console println f
- }
class Foo(j:Int) {
case class Bar(i:Int)
@@ -130,5 +126,21 @@ object Test {
case List(1,2,xs @ _*) =>
case Nil =>
}
+
+ def j = (List[Int](), List[Int](1)) match {
+ case (Nil, _) => 'a'
+ case (_, Nil) => 'b'
+ case (h1 :: t1, h2 :: t2) => 'c'
+ }
+
+ def k (x:AnyRef) = x match {
+ case null => 1
+ case _ => 2
+ }
+
+ val FooBar = 42
+ def lala() = 42 match {
+ case FooBar => true
+ }
}
diff --git a/test/files/run/unapply.scala b/test/files/run/unapply.scala
index fb154cf192..d351468bec 100644
--- a/test/files/run/unapply.scala
+++ b/test/files/run/unapply.scala
@@ -1,12 +1,12 @@
import scala.testing.SUnit._
-object Test {
- def main(args:Array[String]) = {
- Foo.run
- Mas.run
- LisSeqArr.run
- StreamFoo.run
- }
+object Test extends TestConsoleMain {
+ def suite = new TestSuite(
+ Foo,
+ Mas,
+ LisSeqArr,
+ StreamFoo
+ )
}
// this class is used for representation
@@ -28,7 +28,7 @@ object FaaPrecise {
object FaaPreciseSome {
def unapply(x: Bar) = Some(x.name) // return type Some[String]
}
-object Foo extends Assert {
+object Foo extends TestCase("Foo") with Assert {
def unapply(x: Any): Option[Product2[Int, String]] = x match {
case y: Bar => Some(Tuple(y.size, y.name))
case _ => None
@@ -48,7 +48,7 @@ object Foo extends Assert {
def doMatch5(b:Bar) = (b:Any) match {
case FaaPreciseSome(n:String) => n
}
- def run {
+ override def runTest {
val b = new Bar
assertEquals(doMatch1(b),(50,"medium"))
assertEquals(doMatch2(b),null)
@@ -59,7 +59,7 @@ object Foo extends Assert {
}
// same, but now object is not top-level
-object Mas extends Assert {
+object Mas extends TestCase("Mas") with Assert {
object Gaz {
def unapply(x: Any): Option[Product2[Int, String]] = x match {
case y: Baz => Some(Tuple(y.size, y.name))
@@ -70,7 +70,7 @@ object Mas extends Assert {
var size: Int = 60
var name: String = "too large"
}
- def run {
+ def runTest {
val b = new Baz
assertEquals(b match {
case Gaz(s:Int, n:String) => (s,n)
@@ -78,8 +78,8 @@ object Mas extends Assert {
}
}
-object LisSeqArr extends Assert {
- def run {
+object LisSeqArr extends TestCase("LisSeqArr") with Assert {
+ def runTest {
assertEquals((List(1,2,3): Any) match { case List(x,y,_*) => (x,y)}, (1,2))
assertEquals((List(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}, (1,2))
assertEquals((Array(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}, (1,2))
@@ -96,7 +96,7 @@ object StreamFoo extends TestCase("unapply for Streams") with Assert {
case Stream.empty => 0
case Stream.cons(hd, tl) => hd + sum(tl)
}
- override def run {
+ override def runTest {
val str: Stream[int] = Stream.fromIterator(List(1,2,3).elements)
assertEquals(sum(str), 6)
}