diff options
author | Paul Phillips <paulp@improving.org> | 2009-07-02 13:37:14 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-07-02 13:37:14 +0000 |
commit | 8e2090600c9d217a60c0a86a48b0e49b0f81561b (patch) | |
tree | 9eb957a5151ac653ba96fb0410eb8b9ce97dc8d9 /src/compiler | |
parent | 568cba14a3b458977988788fb0281865002916cb (diff) | |
download | scala-8e2090600c9d217a60c0a86a48b0e49b0f81561b.tar.gz scala-8e2090600c9d217a60c0a86a48b0e49b0f81561b.tar.bz2 scala-8e2090600c9d217a60c0a86a48b0e49b0f81561b.zip |
Instilling a little consistency in the pattern ...
Instilling a little consistency in the pattern matcher.
Diffstat (limited to 'src/compiler')
6 files changed, 112 insertions, 142 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 49e0a0385a..658a8121ad 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -33,7 +33,7 @@ trait TreeDSL { // So it's inconsistent until I devise a better way. val TRUE = LIT(true) val FALSE = LIT(false) - def NULL = LIT(null) + val NULL = LIT(null) def UNIT = LIT(()) val ZERO = LIT(0) diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala index 0c81c3d27a..09f4cea5f8 100644 --- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala +++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala @@ -16,16 +16,26 @@ trait CodeFactory extends ast.TreeDSL { self: transform.ExplicitOuter with PatternNodes => - import global.{typer => _, _} + import global.{ typer => _, _ } import analyzer.Typer import definitions._ import CODE._ + // strip bindings to find what tree lies underneath + def unbind(x: Tree): Tree = x match { + case Bind(_, y) => unbind(y) + case y => y + } + + // Create a conditional based on a partial function - for values not defined + // on the partial, it is false. + def cond[T](x: T)(f: PartialFunction[T, Boolean]) = (f isDefinedAt x) && f(x) + final def typedValDef(x: Symbol, rhs: Tree)(implicit typer: Typer) = { val finalRhs = x.tpe match { case WildcardType => rhs setType null - x setInfo typer.typed(rhs).tpe + x setInfo (typer typed rhs).tpe rhs case _ => typer.typed(rhs, x.tpe) diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index c4eef5283f..093b968ff4 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -80,7 +80,7 @@ trait ParallelMatching extends ast.TreeDSL { def assertIsSubtype(other: Type) = assert(isSubType(tpe, other), "problem "+tpe+" not <: "+other) def casted(headType: Type)(implicit theOwner: Symbol) = if (tpe =:= headType) this - else new Scrutinee(newVar(pos, headType, flags)) + else new Scrutinee(newVar(pos, headType, flags = flags)) } case class Pattern(tree: Tree) { @@ -98,26 +98,16 @@ trait ParallelMatching extends ast.TreeDSL { /** * Can this pattern be part of a switch statement? */ - lazy val isSimpleSwitchCandidate = stripped.tree match { - case Literal(const : Constant) if isNumeric(const.tag) => - const.tag match { - case FloatTag | DoubleTag | LongTag => false - case _ => true - } - case _ => false + lazy val isSimpleSwitchCandidate = cond(stripped.tree) { + case Literal(const: Constant) if isNumeric(const.tag) => + !cond(const.tag) { case FloatTag | DoubleTag | LongTag => true } } /** returns if pattern can be considered a no-op test ??for expected type?? */ - final def isDefault: Boolean = isDefaultPattern(tree); - - final def isEquals = tpe match { - case TypeRef(_, sym, _) => sym eq EqualsPatternClass - case _ => false - } + final def isDefault = isDefaultPattern(tree) + final def isEquals = cond(tpe) { case TypeRef(_, EqualsPatternClass, _) => true } final def getAlternativeBranches: List[Tree] = { - - def get_BIND(pctx: Tree => Tree, p: Tree): List[Tree] = p match { case b @ Bind(n, p) => get_BIND((x: Tree) => pctx(treeCopy.Bind(b, n, x) setType x.tpe), p) case Alternative(ps) => ps map pctx @@ -146,7 +136,7 @@ trait ParallelMatching extends ast.TreeDSL { } case class Patterns(scrut: Scrutinee, ps: List[Pattern]) { - private lazy val column = ps.map(_.tree) + private lazy val column = ps map (_.tree) lazy val head = ps.head lazy val tail = Patterns(scrut, ps.tail) lazy val last = ps.last @@ -162,10 +152,7 @@ trait ParallelMatching extends ast.TreeDSL { def isObjectTest(pat: Pattern) = pat isObjectTest headType def isObjectTest(pat: Tree) = Pattern(pat) isObjectTest headType // an unapply for which we don't need a type test - def isUnapplyHead = head.tree match { - case __UnApply(_,argtpe,_) => scrut.tpe <:< argtpe - case _ => false - } + def isUnapplyHead = cond (head.tree) { case __UnApply(_,tpe,_) => scrut.tpe <:< tpe } def isSimpleSwitch: Boolean = scrut.isSimple && ps.init.forall(_.isSimpleSwitchCandidate) && @@ -331,7 +318,8 @@ trait ParallelMatching extends ast.TreeDSL { } } - def newVarCapture(pos: Position,tpe: Type)(implicit theOwner:Symbol) = newVar(pos, tpe, scrut.flags) + def newVarCapture(pos: Position,tpe: Type)(implicit theOwner:Symbol) = + newVar(pos, tpe, flags = scrut.flags) /** returns (unapply-call, success-rep, optional fail-rep*/ final def getTransition(implicit theOwner: Symbol): (Tree, List[Tree], Rep, Option[Rep]) = { @@ -615,10 +603,10 @@ trait ParallelMatching extends ast.TreeDSL { val subtests = if (!ms) subsumed else moreSpecific.zip(subsumed) map { case (mspat, (j, pats)) => (j, mspat::pats) } - val ntriples = for ((j, ps) <- subtests) yield { - val (vs, thePat) = strip(pats(j)) - rest.row(j).insert2(ps, vs, casted.sym) - } + val ntriples = + for ((j, ps) <- subtests ; val Strip(vs, thePat) = pats(j)) yield + (rest row j).insert2(ps, vs, casted.sym) + rep.make(subtestTemps ::: accessorTemps ::: rest.temp, ntriples) } @@ -665,7 +653,7 @@ trait ParallelMatching extends ast.TreeDSL { * @param comb pairs of (column index, type symbol) */ def covers(comb: List[Combo]) = { - lazy val results = for (Combo(i, sym) <- comb ; val p = pat(i).stripped) yield p match { + val results = for (Combo(i, sym) <- comb ; val p = pat(i).stripped) yield p match { case _ if isDefaultPattern(p) => true case _: UnApply | _: ArrayValue => true case _ => p.tpe coversSym sym @@ -676,16 +664,13 @@ trait ParallelMatching extends ast.TreeDSL { // returns this row with alternatives expanded def expand(classifyPat: (Tree, Int) => Tree): List[Row] = { - def isAlternative(p: Tree): Boolean = p.stripped match { - case Alternative(ps) => true - case _ => false - } + def isAlternative(p: Tree) = cond(p.stripped) { case Alternative(_) => true } def getAlternativeBranches(p: Tree): List[Tree] = { def get_BIND(pctx:Tree => Tree, p:Tree): List[Tree] = p match { case b @ Bind(n,p) => get_BIND((x: Tree) => pctx(treeCopy.Bind(b, n, x) setType x.tpe), p) case Alternative(ps) => ps map pctx } - get_BIND(x => x, p) + logAndReturn("get_BIND: ", get_BIND(x => x, p)) } val indexOfAlternative = pat findIndexOf isAlternative @@ -697,14 +682,14 @@ trait ParallelMatching extends ast.TreeDSL { } } - class RepFactory(val handleOuter: Tree => Tree)(implicit val typer : Typer) { + class RepFactory(val handleOuter: Tree => Tree)(implicit val typer: Typer) { var vss: List[List[Symbol]] = _ val labels = new collection.mutable.HashMap[Int, Symbol]() var targets: List[Tree] = _ var reached: BitSet = _ var shortCuts: List[Symbol] = Nil - final def make(temp:List[Symbol], row:List[Row], targets: List[Tree], vss:List[List[Symbol]])(implicit theOwner: Symbol): Rep = { + final def make(temp: List[Symbol], row:List[Row], targets: List[Tree], vss: List[List[Symbol]])(implicit theOwner: Symbol): Rep = { // ensured that labels(i) eq null for all i, cleanup() has to be called after translation this.targets = targets this.vss = vss @@ -712,7 +697,7 @@ trait ParallelMatching extends ast.TreeDSL { make(temp, row) } - final def shortCut(theLabel:Symbol): Int = { + final def shortCut(theLabel: Symbol): Int = { shortCuts = shortCuts ::: List(theLabel) -shortCuts.length } @@ -722,16 +707,18 @@ trait ParallelMatching extends ast.TreeDSL { override def transform(tree: Tree): Tree = tree match { case blck @ Block(vdefs, ld @ LabelDef(name,params,body)) => val bx = labelIndex(ld.symbol) - if (bx >= 0 && !isReachedTwice(bx)) squeezedBlock(vdefs,body) + if (bx >= 0 && !isReachedTwice(bx)) squeezedBlock(vdefs, body) else blck - case If(cond, TRUE, FALSE) => - super.transform(cond) - case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) => - super.transform( 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) => - super.transform( IF (cond1 AND cond2) THEN thenp ELSE ld ) - case t => super.transform(t) + case t => super.transform(t match { + case If(cond, TRUE, FALSE) => + 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 + }) } } val res = lxtt transform tree @@ -751,10 +738,10 @@ trait ParallelMatching extends ast.TreeDSL { final def isReachedTwice(bx: Int) = (bx < 0) || reached(bx) /* @returns bx such that labels(bx) eq label, -1 if no such bx exists */ - final def labelIndex(label: Symbol): Int = { - for ((k, v) <- labels ; if v eq label) return k - -1 - } + final def labelIndex(label: Symbol) = labels find (_._2 eq label) map (_._1) getOrElse (-1) + + /** All trees except those which don't need labels (?) */ + def isLabellable(t: Tree) = !cond(t) { case _: Throw | _: Literal => true } /** first time bx is requested, a LabelDef is returned. next time, a jump. * the function takes care of binding @@ -777,10 +764,10 @@ trait ParallelMatching extends ast.TreeDSL { val label = theOwner.newLabel(body.pos, "body%"+bx) setInfo MethodType(vsyms, tpe) labels(bx) = label - return body match { - case _: Throw | _: Literal => squeezedBlock(vdefs, body.duplicate setType tpe) - case _ => squeezedBlock(vdefs.reverse, LabelDef(label, vsyms, body setType tpe)) - } + return squeezedBlock(vdefs, ( + if (isLabellable(body)) LabelDef(label, vsyms, body setType tpe) + else body.duplicate setType tpe + )) } // if some bx is not reached twice, its LabelDef is replaced with body itself @@ -805,13 +792,10 @@ trait ParallelMatching extends ast.TreeDSL { } log("no consistency problem: calling %s(%s) with (%s)".format(label, fmls, args)) - body match { - case _: Throw | _: Literal => // might be bound elsewhere (see `x @ unapply') - val vdefs = for (v <- vss(bx) ; substv <- subst(v)) yield typedValDef(v, substv) - squeezedBlock(vdefs, body.duplicate setType resultType) - case _ => - Apply(ID(label), args) - } + def vds = for (v <- vss(bx) ; substv <- subst(v)) yield typedValDef(v, substv) + + if (isLabellable(body)) ID(label) APPLY (args) + else squeezedBlock(vds, body.duplicate setType resultType) } /** the injection here handles alternatives and unapply type tests */ @@ -826,8 +810,8 @@ trait ParallelMatching extends ast.TreeDSL { // sType is called. But it ends up mixing the prefix of the other module with the val symbol // which then causes erasure to be confused. def sType(o: Tree) = o.tpe match { - case st @ SingleType(pre, sym) => st - case _ => singleType(o.tpe.prefix, o.symbol) + case st: SingleType => st + case _ => singleType(o.tpe.prefix, o.symbol) } def equalsCheck(o: Tree) = if (o.symbol.isValue) singleType(NoPrefix, o.symbol) else sType(o) def isModule(o: Tree) = o.symbol.isModule || o.tpe.termSymbol.isModule @@ -844,7 +828,10 @@ trait ParallelMatching extends ast.TreeDSL { } def classifyPat(opat: Tree, j: Int): Tree = { - val (vs, strippedPat) = strip(opat) match { case (vset, pat) => (vset.toList, pat) } + val (vs, strippedPat) = { + val Strip(vset, pat) = opat + (vset.toList, pat) + } // @todo: rewrite UnApply(Apply(fn, _), _) case, using __UnApply instead of UnApply like so: // case ua @ __UnApply(_,argtpe,_) => // val ua = prepat @@ -968,7 +955,8 @@ trait ParallelMatching extends ast.TreeDSL { var bnd = subst for (((rpat, t), px) <- pats zip temp zipWithIndex) { - val (vs, p) = strip(rpat) + val Strip(vs, p) = rpat + if (isDefaultPattern(p)) bnd = bnd.add(vs, t) else { // Row( _ ... _ p_1i ... p_1n g_m b_m ) :: rows @@ -1020,19 +1008,17 @@ trait ParallelMatching extends ast.TreeDSL { rep.make(roots, rows.flatMap(x => x), targets, vss) } - final def newVar(pos: Position, name: Name, tpe: Type, flags: List[Long])(implicit theOwner: Symbol): Symbol = { - assert(tpe ne null, "newVar("+name+", null)") - val sym = theOwner.newVariable(pos, name) // careful: pos has special meaning - sym setInfo tpe - sym setFlag flags.foldLeft(Flags.SYNTHETIC.toLong)(_|_) + final def newVar( + pos: Position, + tpe: Type, + flags: List[Long] = Nil, + name: Name = null + )(implicit theOwner: Symbol): Symbol = { + val n: Name = if (name == null) newName(pos, "temp") else name + // careful: pos has special meaning + theOwner.newVariable(pos, n) setInfo tpe setFlag (0L /: flags)(_|_) } - final def newVar(pos: Position, tpe: Type, flags: List[Long])(implicit theOwner: Symbol): Symbol = - newVar(pos, newName(pos, "temp"), tpe, flags) - - final def newVar(pos: Position, tpe: Type)(implicit theOwner: Symbol): Symbol = - newVar(pos, tpe, Nil) - /** returns the condition in "if (cond) k1 else k2" */ final def condition(tpe: Type, scrut: Scrutinee)(implicit typer: Typer, theOwner: Symbol, rep: RepFactory): Tree = { @@ -1043,21 +1029,22 @@ trait ParallelMatching extends ast.TreeDSL { else addOuterCondition(cond, tpe, scrut.id, rep.handleOuter) } - final def condition(tpe: Type, scrutTree: Tree)(implicit typer : Typer): Tree = { + final def condition(tpe: Type, scrutTree: Tree)(implicit typer: Typer): Tree = { assert((tpe ne NoType) && (scrutTree.tpe ne NoType)) - def equalsRef = REF(tpe.termSymbol) ANY_== scrutTree - def isInst = scrutTree IS tpe + def equalsRef = REF(tpe.termSymbol) ANY_== scrutTree + def isInst = scrutTree IS tpe + def isAnyRef(t: Type) = t <:< definitions.AnyRefClass.tpe tpe match { - case ct: ConstantType => ct.value match { // constant - case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree ANY_EQ NULL - case v => scrutTree ANY_== Literal(v) + case ct: ConstantType => ct.value match { // constant + case v @ Constant(null) if isAnyRef(scrutTree.tpe) => scrutTree ANY_EQ NULL + case v => scrutTree ANY_== Literal(v) } case _: SingletonType => if (tpe.termSymbol.isModule) equalsRef // object - else typer typed (if (tpe.prefix ne NoPrefix) isInst else equalsRef) + else typer typed { if (tpe.prefix ne NoPrefix) isInst else equalsRef } case _ => - if (scrutTree.tpe <:< tpe && tpe.isAnyRef) typer typed (scrutTree OBJ_!= NULL) + if (scrutTree.tpe <:< tpe && isAnyRef(tpe)) typer typed (scrutTree OBJ_!= NULL) else isInst } } diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala index 7d83f9a5d3..69a9652ac8 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala @@ -32,9 +32,9 @@ trait PatternNodes extends ast.TreeDSL private def cmpSymbols(t1: Type, t2: Type) = t1.typeSymbol eq t2.typeSymbol // true if t2 is a parent of t1. Should this be rather: tpe.baseTypes.exists...? - private def parenthood(t1: Type, t2: Type) = t1.parents.exists(p => cmpSymbols(p, t2)) + private def parenthood(t1: Type, t2: Type) = t1.parents exists (p => cmpSymbols(p, t2)) // true if t1 is direct subtype of t2 (can't use just <:< cause have to take variance into account) - private def subtypehood(t1: Type, t2: Type) = t1.parents.exists(p => cmpSymbols(p, t2) && p <:< t2) + private def subtypehood(t1: Type, t2: Type) = t1.parents exists (p => cmpSymbols(p, t2) && p <:< t2) def yParentsX = parenthood(x, y) def xParentsY = parenthood(y, x) @@ -72,15 +72,14 @@ trait PatternNodes extends ast.TreeDSL } lazy val tpe = tpeWRTEquality(_tpe) - // The several different logics in these tests are intentionally grouped here to - // draw attention to them. To the extent that the differences are intentional, - // the thinking behind the distinctions needs to be documented. - def isInt = tpe =:= IntClass.tpe - def isChar = tpe =:= CharClass.tpe - def isAnyRef = tpe <:< AnyRefClass.tpe - def isBoolean = tpe.typeSymbol eq BooleanClass - def isArray = tpe.typeSymbol eq ArrayClass - def isNothing = tpe.typeSymbol eq NothingClass + // These tests for final classes can inspect the typeSymbol + private def is(s: Symbol) = tpe.typeSymbol eq s + def isInt = is(IntClass) + def isChar = is(CharClass) + def isBoolean = is(BooleanClass) + def isNothing = is(NothingClass) + def isArray = is(ArrayClass) + def isCaseClass = tpe.typeSymbol hasFlag Flags.CASE def cmp(other: Type): TypeComparison = TypeComparison(tpe, tpeWRTEquality(other)) @@ -95,7 +94,7 @@ trait PatternNodes extends ast.TreeDSL (tpe.typeSymbol == sym) || (symtpe <:< tpe) || (symtpe.parents exists (_.typeSymbol eq tpe.typeSymbol)) || // e.g. Some[Int] <: Option[&b] - (tpe.prefix.memberType(sym) <:< tpe) // outer, see combinator.lexical.Scanner + ((tpe.prefix memberType sym) <:< tpe) // outer, see combinator.lexical.Scanner } } @@ -133,7 +132,7 @@ trait PatternNodes extends ast.TreeDSL val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy") val res = mkTypeRef(sym) - (MethodType(dummyMethod.newSyntheticValueParams(List(tptArg, mkTypeRef(ListClass))), res), res) + (MethodType(dummyMethod newSyntheticValueParams List(tptArg, mkTypeRef(ListClass)), res), res) } Apply(TypeTree(consType), List(x, normalizedListPattern(xs, tptArg))) setType resType } @@ -164,22 +163,6 @@ trait PatternNodes extends ast.TreeDSL } } - // TODO - this doesn't work! For some reason this sometimes returns false when encapsulated - // in an object like this, when it returns true if the same logic is applied literally in - // the classifyPat match in ParallelMatching. I couldn't figure out why, and it concerns - // me - if this isn't working maybe other unapply objects aren't working right either. The big - // problem with using unapply and type matching is that if something's amiss, it will simply fail - // silently, with the bug most likely manifesting at some unknown later point. - // DRM: This problem is almost certainly an instance of bug 1697 - object Ident_Or_Empty { - def unapply(x: Any) = x match { - case Ident(nme.WILDCARD) | EmptyTree | _: Typed | _: Literal => true - // this returns false, and then a line identical the one above will match - // back in PM.scala. - case _ => false - } - } - object UnApply_TypeApply { def unapply(x: UnApply) = x match { case UnApply(Apply(TypeApply(sel @ Select(stor, nme.unapplySeq), List(tptArg)), _), ArrayValue(_, xs)::Nil) @@ -197,25 +180,24 @@ trait PatternNodes extends ast.TreeDSL } /** returns if pattern can be considered a no-op test ??for expected type?? */ - final def isDefaultPattern(pattern: Tree): Boolean = pattern match { - case Bind(_, p) => isDefaultPattern(p) - case EmptyTree => true // dummy - case Ident(nme.WILDCARD) => true - case _ => false -// -- what about the following? still have to test "ne null" :/ -// case Typed(nme.WILDCARD,_) => pattern.tpe <:< scrut.tpe - } + final def isDefaultPattern(pattern: Tree): Boolean = + cond(unbind(pattern)) { case EmptyTree | Ident(nme.WILDCARD) => true } + // -- what about the following? still have to test "ne null" :/ + // case Typed(nme.WILDCARD,_) => pattern.tpe <:< scrut.tpe /** returns all variables that are binding the given pattern * @param x a pattern * @return vs variables bound, p pattern proper */ - final def strip(x: Tree): (Set[Symbol], Tree) = x match { - case b @ Bind(_,pat) => val (vs, p) = strip(pat); (vs + b.symbol, p) - case _ => (emptySymbolSet, x) - } - object Strip { def unapply(x: Tree): Option[(Set[Symbol], Tree)] = Some(strip(x)) } + object Strip { + // all variables binding the given pattern + private def strip(syms: Set[Symbol], t: Tree): (Set[Symbol], Tree) = t match { + case b @ Bind(_, pat) => strip(syms + b.symbol, pat) + case _ => (syms, t) + } + def unapply(x: Tree): Option[(Set[Symbol], Tree)] = Some(strip(Set(), x)) + } object BoundVariables { def unapply(x: Tree): Option[List[Symbol]] = Some(Pattern(x).boundVariables) diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala index d7dd685b24..a348ea83a4 100644 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala @@ -30,15 +30,8 @@ trait TransMatcher extends ast.TreeDSL { final val settings_squeeze = settings.Xsqueeze.value == "on" // check special case Seq(p1,...,pk,_*) - protected def isRightIgnoring(p: ArrayValue): Boolean = { - def isDefaultStar(tree: Tree): Boolean = tree match { - case Bind(_, q) => isDefaultStar(q) - case Star(q) => isDefaultPattern(q) - case _ => false - } - - !p.elems.isEmpty && isDefaultStar(p.elems.last) - } + protected def isRightIgnoring(p: ArrayValue): Boolean = + !p.elems.isEmpty && cond(unbind(p.elems.last)) { case Star(q) => isDefaultPattern(q) } /** handles all translation of pattern matching */ @@ -54,11 +47,9 @@ trait TransMatcher extends ast.TreeDSL { implicit val rep = new RepFactory(handleOuter) val flags = if (doCheckExhaustive) Nil else List(Flags.TRANS_FLAG) - def matchError(obj: Tree) = atPos(selector.pos)(THROW(MatchErrorClass, obj)) - def caseIsOk(c: CaseDef) = c.pat match { - case _: Apply | Ident(nme.WILDCARD) => true - case _ => false - } + def matchError(obj: Tree) = atPos(selector.pos)(THROW(MatchErrorClass, obj)) + def caseIsOk(c: CaseDef) = cond(c.pat) { case _: Apply | Ident(nme.WILDCARD) => true } + def doApply(fn: Tree): Boolean = (fn.symbol eq (selector.tpe.decls lookup nme.CONSTRUCTOR)) && (cases forall caseIsOk) @@ -67,7 +58,7 @@ trait TransMatcher extends ast.TreeDSL { val Apply(fn, args) = app val (tmps, vds) = List.unzip( for ((arg, typeArg) <- args zip selector.tpe.typeArgs) yield { - val v = newVar(arg.pos, newName(arg.pos, "tp"), typeArg, flags) + val v = newVar(arg.pos, typeArg, flags, newName(arg.pos, "tp")) (v, typedValDef(v, arg)) } ) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 960a4e8a9a..a27f6989e1 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -317,7 +317,7 @@ abstract class ExplicitOuter extends InfoTransform * @pre mixinClass is an inner class */ def mixinOuterAccessorDef(mixinClass: Symbol): Tree = { - val outerAcc = outerAccessor(mixinClass).overridingSymbol(currentClass) + val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass assert(outerAcc != NoSymbol) val path = if (mixinClass.owner.isTerm) THIS(mixinClass.owner.enclClass) |