diff options
author | Paul Phillips <paulp@improving.org> | 2012-04-14 11:51:05 +0100 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-04-14 11:51:05 +0100 |
commit | 57c7debd62cd8c37723d80450141e3e3524a351c (patch) | |
tree | 23d22e428d200a3398b8310052e812b109cc141a | |
parent | 0b3b12fb29b8a4a624c4a0bb4520114f10599036 (diff) | |
parent | 631f60e4238552c614702d4594afaa01fe2ecd04 (diff) | |
download | scala-57c7debd62cd8c37723d80450141e3e3524a351c.tar.gz scala-57c7debd62cd8c37723d80450141e3e3524a351c.tar.bz2 scala-57c7debd62cd8c37723d80450141e3e3524a351c.zip |
Merge branch 'develop'
135 files changed, 962 insertions, 549 deletions
diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index 9b4c18ce86..486a3d3567 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -103,6 +103,16 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => } } + def printLabelParams(ps: List[Ident]) { + print("(") + printSeq(ps){printLabelParam}{print(", ")} + print(")") + } + + def printLabelParam(p: Ident) { + print(symName(p, p.name)); printOpt(": ", TypeTree() setType p.tpe) + } + def printValueParams(ts: List[ValDef]) { print("(") if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "") @@ -219,7 +229,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => } case LabelDef(name, params, rhs) => - print(symName(tree, name)); printRow(params, "(", ",", ")"); printBlock(rhs) + print(symName(tree, name)); printLabelParams(params); printBlock(rhs) case Import(expr, selectors) => // Is this selector remapping a name (i.e, {name1 => name2}) diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 0413fd9896..5f1a8f3fbe 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -144,11 +144,9 @@ trait Trees extends api.Trees { self: SymbolTable => * less than the whole tree. */ def summaryString: String = tree match { - case Select(qual, name) => qual.summaryString + "." + name.decode - case Ident(name) => name.longString case Literal(const) => "Literal(" + const + ")" - case t: DefTree => t.shortClass + " `" + t.name.decode + "`" - case t: RefTree => t.shortClass + " `" + t.name.longString + "`" + case Select(qual, name) => qual.summaryString + "." + name.decode + case t: NameTree => t.name.longString case t => t.shortClass + ( if (t.symbol != null && t.symbol != NoSymbol) " " + t.symbol diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 3efbe4b4df..17c9b955ca 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -97,7 +97,7 @@ trait Types extends api.Types { self: SymbolTable => */ private final val propagateParameterBoundsToTypeVars = sys.props contains "scalac.debug.prop-constraints" - protected val enableTypeVarExperimentals = settings.Xexperimental.value || settings.YvirtPatmat.value + protected val enableTypeVarExperimentals = settings.Xexperimental.value || !settings.XoldPatmat.value /** Empty immutable maps to avoid allocations. */ private val emptySymMap = immutable.Map[Symbol, Symbol]() diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala index b556c33aba..45ba4ed3e6 100644 --- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala @@ -43,5 +43,5 @@ abstract class MutableSettings extends AbsSettings { def Yrecursion: IntSetting def maxClassfileName: IntSetting def Xexperimental: BooleanSetting - def YvirtPatmat: BooleanSetting + def XoldPatmat: BooleanSetting }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala index 27e90c94bd..bbe4d60e9c 100644 --- a/src/compiler/scala/reflect/runtime/Settings.scala +++ b/src/compiler/scala/reflect/runtime/Settings.scala @@ -34,5 +34,5 @@ class Settings extends internal.settings.MutableSettings { val maxClassfileName = new IntSetting(255) val Xexperimental = new BooleanSetting(false) val deepCloning = new BooleanSetting (false) - val YvirtPatmat = new BooleanSetting(false) + val XoldPatmat = new BooleanSetting(false) } diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 0f9f7df548..403b5717b0 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -347,7 +347,7 @@ class Global(var currentSettings: Settings, var reporter: NscReporter) extends S override protected val etaExpandKeepsStar = settings.etaExpandKeepsStar.value // Here comes another one... override protected val enableTypeVarExperimentals = ( - settings.Xexperimental.value || settings.YvirtPatmat.value + settings.Xexperimental.value || !settings.XoldPatmat.value ) // True if -Xscript has been set, indicating a script run. diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index e566384713..d3e64811d3 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -72,14 +72,6 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { Annotated(Ident(nme.synthSwitch), expr) } - // must be kept in synch with the codegen in PatMatVirtualiser - object VirtualCaseDef { - def unapply(b: Block): Option[(Assign, Tree, Tree)] = b match { - case Block(List(assign@Assign(keepGoingLhs, falseLit), matchRes), zero) => Some((assign, matchRes, zero)) // TODO: check tree annotation - case _ => None - } - } - def hasSynthCaseSymbol(t: Tree) = (t.symbol ne null) && (t.symbol hasFlag (CASE | SYNTHETIC)) // TODO: would be so much nicer if we would know during match-translation (i.e., type checking) @@ -87,9 +79,11 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { class MatchMatcher { def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = unknownTree(orig) def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = unknownTree(orig) - def caseVirtualizedMatchOpt(orig: Tree, zero: ValDef, x: ValDef, matchRes: ValDef, keepGoing: ValDef, stats: List[Tree], epilogue: Tree, wrap: Tree => Tree): Tree = unknownTree(orig) + def caseVirtualizedMatchOpt(orig: Tree, prologue: List[Tree], cases: List[Tree], matchEndDef: Tree, wrap: Tree => Tree): Tree = unknownTree(orig) - def apply(matchExpr: Tree): Tree = (matchExpr: @unchecked) match { + def genVirtualizedMatch(prologue: List[Tree], cases: List[Tree], matchEndDef: Tree): Tree = Block(prologue ++ cases, matchEndDef) + + def apply(matchExpr: Tree): Tree = matchExpr match { // old-style match or virtpatmat switch case Match(selector, cases) => // println("simple match: "+ (selector, cases) + "for:\n"+ matchExpr ) caseMatch(matchExpr, selector, cases, identity) @@ -100,11 +94,15 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr ) caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher) // optimized version of virtpatmat - case Block((zero: ValDef) :: (x: ValDef) :: (matchRes: ValDef) :: (keepGoing: ValDef) :: stats, epilogue) if opt.virtPatmat => // TODO: check tree annotation // println("virtopt match: "+ (zero, x, matchRes, keepGoing, stats) + "for:\n"+ matchExpr ) - caseVirtualizedMatchOpt(matchExpr, zero, x, matchRes, keepGoing, stats, epilogue, identity) + case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) => + // the assumption is once we encounter a case, the remainder of the block will consist of cases + // the prologue may be empty, usually it is the valdef that stores the scrut + val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef]) + caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity) // optimized version of virtpatmat - case Block(outerStats, orig@Block((zero: ValDef) :: (x: ValDef) :: (matchRes: ValDef) :: (keepGoing: ValDef) :: stats, epilogue)) if opt.virtPatmat => // TODO: check tree annotation // println("virt opt block match: "+ (zero, x, matchRes, keepGoing, stats, outerStats) + "for:\n"+ matchExpr ) - caseVirtualizedMatchOpt(matchExpr, zero, x, matchRes, keepGoing, stats, epilogue, m => copyBlock(matchExpr, outerStats, m)) + case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) => + val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef]) + caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m)) case other => unknownTree(other) } @@ -120,35 +118,6 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { } } - def withDefaultCase(matchExpr: Tree, defaultAction: Tree/*scrutinee*/ => Tree): Tree = { - object withDefaultTransformer extends MatchMatcher { - override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = { - val casesNoSynthCatchAll = dropSyntheticCatchAll(cases) - if (casesNoSynthCatchAll exists treeInfo.isDefaultCase) orig - else { - val defaultCase = CaseDef(Ident(nme.WILDCARD), EmptyTree, defaultAction(selector.duplicate)) - wrap(Match(selector, casesNoSynthCatchAll :+ defaultCase)) - } - } - override def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = { import CODE._ - ((matcher APPLY (scrut)) DOT nme.getOrElse) APPLY (defaultAction(scrut.duplicate)) // TODO: pass targs - } - override def caseVirtualizedMatchOpt(orig: Tree, zero: ValDef, x: ValDef, matchRes: ValDef, keepGoing: ValDef, stats: List[Tree], epilogue: Tree, wrap: Tree => Tree): Tree = { import CODE._ - wrap(Block( - zero :: - x :: - matchRes :: - keepGoing :: - stats, - // replace `if (keepGoing) throw new MatchError(...) else matchRes` by `if (keepGoing) ${defaultAction(`x`)} else matchRes` - (IF (REF(keepGoing.symbol)) THEN defaultAction(x.rhs.duplicate) ELSE REF(matchRes.symbol)) - )) - } - } - withDefaultTransformer(matchExpr) - } - - def mkCached(cvar: Symbol, expr: Tree): Tree = { val cvarRef = mkUnattributedRef(cvar) Block( diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 59e36e86f6..04452c68e5 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -255,6 +255,7 @@ trait Trees extends reflect.internal.Trees { self: Global => def resetAllAttrs[A <: Tree](x: A, leaveAlone: Tree => Boolean = null): A = new ResetAttrs(false, leaveAlone).transform(x) def resetLocalAttrs[A <: Tree](x: A, leaveAlone: Tree => Boolean = null): A = new ResetAttrs(true, leaveAlone).transform(x) + def resetLocalAttrsKeepLabels[A<:Tree](x: A, leaveAlone: Tree => Boolean = null): A = new ResetAttrs(true, leaveAlone, true).transform(x) /** A transformer which resets symbol and tpe fields of all nodes in a given tree, * with special treatment of: @@ -265,7 +266,7 @@ trait Trees extends reflect.internal.Trees { self: Global => * * (bq:) This transformer has mutable state and should be discarded after use */ - private class ResetAttrs(localOnly: Boolean, leaveAlone: Tree => Boolean = null) { + private class ResetAttrs(localOnly: Boolean, leaveAlone: Tree => Boolean = null, keepLabels: Boolean = false) { val debug = settings.debug.value val trace = scala.tools.nsc.util.trace when debug @@ -328,18 +329,18 @@ trait Trees extends reflect.internal.Trees { self: Global => case EmptyTree => tree case _ => - if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol))) + if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel)) tree.symbol = NoSymbol tree.tpe = null tree } } - } + } } def transform[T <: Tree](x: T): T = { if (localOnly) - new MarkLocals().traverse(x) + new MarkLocals().traverse(x) if (localOnly && debug) { assert(locals.size == orderedLocals.size) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 65225b185b..eb4deeeee2 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -70,6 +70,9 @@ trait ParsersCommon extends ScannersCommon { @inline final def inBracesOrNil[T](body: => List[T]): List[T] = inBracesOrError(body, Nil) @inline final def inBracesOrUnit[T](body: => Tree): Tree = inBracesOrError(body, Literal(Constant())) + @inline final def dropAnyBraces[T](body: => T): T = + if (in.token == LBRACE) inBraces(body) + else body @inline final def inBrackets[T](body: => T): T = { accept(LBRACKET) @@ -1106,7 +1109,7 @@ self => * }}} * @note The returned tree does not yet have a position */ - def literal(isNegated: Boolean = false): Tree = { + def literal(isNegated: Boolean = false, inPattern: Boolean = false): Tree = { def finish(value: Any): Tree = { val t = Literal(Constant(value)) in.nextToken() @@ -1115,7 +1118,7 @@ self => if (in.token == SYMBOLLIT) Apply(scalaDot(nme.Symbol), List(finish(in.strVal))) else if (in.token == INTERPOLATIONID) - interpolatedString() + interpolatedString(inPattern) else finish(in.token match { case CHARLIT => in.charVal case INTLIT => in.intVal(isNegated).toInt @@ -1141,7 +1144,7 @@ self => } } - private def interpolatedString(): Tree = atPos(in.offset) { + private def interpolatedString(inPattern: Boolean = false): Tree = atPos(in.offset) { val start = in.offset val interpolator = in.name @@ -1151,8 +1154,11 @@ self => while (in.token == STRINGPART) { partsBuf += literal() exprBuf += { - if (in.token == IDENTIFIER) atPos(in.offset)(Ident(ident())) - else expr() + if (inPattern) dropAnyBraces(pattern()) + else { + if (in.token == IDENTIFIER) atPos(in.offset)(Ident(ident())) + else expr() + } } } if (in.token == STRINGLIT) partsBuf += literal() @@ -1837,7 +1843,7 @@ self => case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => t match { case Ident(nme.MINUS) => - return atPos(start) { literal(isNegated = true) } + return atPos(start) { literal(isNegated = true, inPattern = true) } case _ => } case _ => @@ -1855,7 +1861,7 @@ self => atPos(start, start) { Ident(nme.WILDCARD) } case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | INTERPOLATIONID | SYMBOLLIT | TRUE | FALSE | NULL => - atPos(start) { literal() } + atPos(start) { literal(inPattern = true) } case LPAREN => atPos(start)(makeParens(noSeq.patterns())) case XMLSTART => diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala index 40bbd3fa8e..99541ff4b4 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala @@ -81,7 +81,7 @@ private[tests] trait CoreTestDefs else { reporter.println("\naskHyperlinkPos for `" + tree.symbol.name + "` at " + format(pos) + " " + pos.source.file.name) val r = new Response[Position] - // `tree.symbol.sourceFile` was discovered to be null when testing -Yvirtpatmat on the akka presentation test, where a position had shifted to point to `Int` + // `tree.symbol.sourceFile` was discovered to be null when testing using virtpatmat on the akka presentation test, where a position had shifted to point to `Int` // askHyperlinkPos for `Int` at (73,19) pi.scala --> class Int in package scala has null sourceFile! val treePath = if (tree.symbol.sourceFile ne null) tree.symbol.sourceFile.path else null val treeName = if (tree.symbol.sourceFile ne null) tree.symbol.sourceFile.name else null diff --git a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala index 2fdc3004d6..63775ff1c5 100644 --- a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala @@ -31,7 +31,7 @@ trait AestheticSettings { def target = settings.target.value def unchecked = settings.unchecked.value def verbose = settings.verbose.value - def virtPatmat = settings.YvirtPatmat.value + def virtPatmat = !settings.XoldPatmat.value /** Derived values */ def jvm = target startsWith "jvm" diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index f7878cae71..d4c2ffa832 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -108,6 +108,8 @@ trait ScalaSettings extends AbsScalaSettings val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.") val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "") + val XoldPatmat = BooleanSetting ("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.") + /** Compatibility stubs for options whose value name did * not previously match the option name. */ @@ -175,7 +177,6 @@ trait ScalaSettings extends AbsScalaSettings val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.") val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.") val noSelfCheck = BooleanSetting ("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.") - val YvirtPatmat = BooleanSetting ("-Yvirtpatmat", "Translate pattern matches into flatMap/orElse calls. See scala.MatchingStrategy.") val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes") val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index bdf2f2883f..5e61359a25 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -480,11 +480,10 @@ abstract class Erasure extends AddInterfaces // TODO: should we do this for user-defined unapplies as well? // does the first argument list have exactly one argument -- for user-defined unapplies we can't be sure def maybeWrap(bridgingCall: Tree): Tree = { - val canReturnNone = afterErasure( - member.isSynthetic - && (member.name == nme.unapply || member.name == nme.unapplySeq) - && !(member.tpe <:< other.tpe) // no static guarantees (TODO: is the subtype test ever true?) - ) + val canReturnNone = ( // can't statically know which member is going to be selected, so don't let this depend on member.isSynthetic + (member.name == nme.unapply || member.name == nme.unapplySeq) + && !afterErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?) + if (canReturnNone) { import CODE._ val typeTest = gen.mkIsInstanceOf(REF(bridge.firstParam), member.tpe.params.head.tpe) diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 1d2206bc3d..57cd51ad35 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -241,7 +241,6 @@ abstract class UnCurry extends InfoTransform def owner = fun.symbol.owner def targs = fun.tpe.typeArgs def isPartial = fun.tpe.typeSymbol == PartialFunctionClass - assert(!(opt.virtPatmat && isPartial)) // empty-selector matches have already been translated into instantiations of anonymous (partial) functions def parents = if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe), SerializableClass.tpe) @@ -282,7 +281,44 @@ abstract class UnCurry extends InfoTransform val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), List(x)) val body = localTyper.typedPos(fun.pos) { import CODE._ - gen.mkUncheckedMatch(gen.withDefaultCase(substParam(fun.body), scrut => REF(default) APPLY (REF(x)))) + def defaultAction(scrut: Tree) = REF(default) APPLY (REF(x)) + + object withDefaultTransformer extends gen.MatchMatcher { + override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = { + val casesNoSynthCatchAll = dropSyntheticCatchAll(cases) + if (casesNoSynthCatchAll exists treeInfo.isDefaultCase) orig + else { + val defaultCase = CaseDef(Ident(nme.WILDCARD), EmptyTree, defaultAction(selector.duplicate)) + wrap(Match(/*gen.mkUnchecked*/(selector), casesNoSynthCatchAll :+ defaultCase)) + } + } + override def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = { import CODE._ + ((matcher APPLY (scrut)) DOT nme.getOrElse) APPLY (defaultAction(scrut.duplicate)) // TODO: pass targs + } + override def caseVirtualizedMatchOpt(orig: Tree, prologue: List[Tree], cases: List[Tree], matchEndDef: Tree, wrap: Tree => Tree): Tree = { import CODE._ + val scrutRef = REF(prologue.head.symbol) // scrut valdef is always emitted (except for nested matchers that handle alternatives) + + val casesNewSynthCatchAll = cases.init :+ (deriveLabelDef(cases.last){ + case Apply(matchEnd, List(Throw(Apply(Select(New(exTpt), nme.CONSTRUCTOR), _)))) if exTpt.tpe.typeSymbol eq MatchErrorClass => + assert(matchEnd.symbol == matchEndDef.symbol, "matchEnd discrepancy "+(matchEnd, matchEndDef)) + matchEnd APPLY (defaultAction(scrutRef)) + case x => x + } setSymbol cases.last.symbol setType null) + + val LabelDef(_, List(matchRes), rhs) = matchEndDef + val matchEnd = matchEndDef.symbol + matchRes setType B1.tpe + rhs setType B1.tpe + matchEndDef setType B1.tpe + matchRes.symbol setInfo B1.tpe + matchEnd setInfo MethodType(List(matchRes.symbol), B1.tpe) + cases foreach (c => c.symbol setInfo MethodType(List(), B1.tpe)) + + wrap(Block(prologue ++ casesNewSynthCatchAll, matchEndDef)) + } + } + + withDefaultTransformer(substParam(fun.body)) } body.changeOwner(fun.symbol -> methSym) @@ -294,30 +330,115 @@ abstract class UnCurry extends InfoTransform methDef } - // duplicate before applyOrElseMethodDef is run so we start with the same symbols as applyOrElseMethodDef + // duplicate before applyOrElseMethodDef is run so that it does not mess up our trees and label symbols (we have a fresh set) // otherwise `TreeSymSubstituter(fun.vparams map (_.symbol), params)` won't work as the subst has been run already - val bodyForIDA = fun.body.duplicate + val bodyForIDA = { + val duped = fun.body.duplicate + val oldParams = new mutable.ListBuffer[Symbol]() + val newParams = new mutable.ListBuffer[Symbol]() + + val oldSyms0 = + duped filter { + case l@LabelDef(_, params, _) => + params foreach {p => + val oldSym = p.symbol + p.symbol = oldSym.cloneSymbol + oldParams += oldSym + newParams += p.symbol + } + true + case _ => false + } map (_.symbol) + val oldSyms = oldParams.toList ++ oldSyms0 + val newSyms = newParams.toList ++ (oldSyms0 map (_.cloneSymbol)) + // println("duping "+ oldSyms +" --> "+ (newSyms map (_.ownerChain))) + + val substLabels = new TreeSymSubstituter(oldSyms, newSyms) + + substLabels(duped) + } + def isDefinedAtMethodDef = { val methSym = anonClass.newMethod(nme.isDefinedAt, fun.pos, FINAL) val params = methSym newSyntheticValueParams formals methSym setInfoAndEnter MethodType(params, BooleanClass.tpe) val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), params) - def doSubst(x: Tree) = substParam(resetLocalAttrs(x)) // see pos/t1761 for why `resetLocalAttrs` + def doSubst(x: Tree) = substParam(resetLocalAttrsKeepLabels(x)) // see pos/t1761 for why `resetLocalAttrs`, but must keep label symbols around + object isDefinedAtTransformer extends gen.MatchMatcher { // TODO: optimize duplication, but make sure ValDef's introduced by wrap are treated correctly override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = { import CODE._ - gen.mkUncheckedMatch( - if (cases exists treeInfo.isDefaultCase) TRUE_typed + val casesNoSynthCatchAll = dropSyntheticCatchAll(cases) + if (casesNoSynthCatchAll exists treeInfo.isDefaultCase) TRUE_typed else doSubst(wrap( - Match(selector, - (cases map (c => deriveCaseDef(c)(x => TRUE_typed))) :+ ( + Match(/*gen.mkUnchecked*/(selector), + (casesNoSynthCatchAll map (c => deriveCaseDef(c)(x => TRUE_typed))) :+ ( DEFAULT ==> FALSE_typed) ))) - ) + } + override def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = { + object noOne extends Transformer { + override val treeCopy = newStrictTreeCopier // must duplicate everything + val one = _match.tpe member newTermName("one") + override def transform(tree: Tree): Tree = tree match { + case Apply(fun, List(a)) if fun.symbol == one => + // blow one's argument away since all we want to know is whether the match succeeds or not + // (the alternative, making `one` CBN, would entail moving away from Option) + Apply(fun.duplicate, List(gen.mkZeroContravariantAfterTyper(a.tpe))) + case _ => + super.transform(tree) + } + } + doSubst(Apply(Apply(TypeApply(Select(_match.duplicate, _match.tpe.member(newTermName("isSuccess"))), targs map (_.duplicate)), List(scrut.duplicate)), List(noOne.transform(matcher)))) + } + + override def caseVirtualizedMatchOpt(orig: Tree, prologue: List[Tree], cases: List[Tree], matchEndDef: Tree, wrap: Tree => Tree) = { + val matchEnd = matchEndDef.symbol + val LabelDef(_, List(matchRes), rhs) = matchEndDef + matchRes setType BooleanClass.tpe + rhs setType BooleanClass.tpe + matchEndDef setType BooleanClass.tpe + matchRes.symbol setInfo BooleanClass.tpe + matchEnd setInfo MethodType(List(matchRes.symbol), BooleanClass.tpe) + cases foreach (c => c.symbol setInfo MethodType(List(), BooleanClass.tpe)) + // println("matchEnd: "+ matchEnd) + + // when the type of the selector contains a skolem owned by the applyOrElseMethod, should reskolemize everything, + // for now, just cast the RHS (since we're just trying to keep the typer happy, the cast is meaningless) + // ARGH -- this is why I would prefer the typedMatchAnonFun approach (but alas, CPS blocks that) + val newPrologue = prologue match { + case List(vd@ValDef(mods, name, tpt, rhs)) => List(treeCopy.ValDef(vd, mods, name, tpt, gen.mkAsInstanceOf(rhs, tpt.tpe, true, false))) + case _ => prologue + } + object casesReturnTrue extends Transformer { + // override val treeCopy = newStrictTreeCopier // will duplicate below + override def transform(tree: Tree): Tree = tree match { + // don't compute the result of the match, return true instead + case Apply(fun, List(res)) if fun.symbol eq matchEnd => + // println("matchend call "+ fun.symbol) + Apply(fun, List(TRUE_typed)) setType BooleanClass.tpe + case _ => super.transform(tree) + } + } + val newCatchAll = cases.last match { + case LabelDef(n, ps, Apply(matchEnd1, List(Throw(Apply(Select(New(exTpt), nme.CONSTRUCTOR), _))))) if exTpt.tpe.typeSymbol eq MatchErrorClass => + assert(matchEnd1.symbol == matchEnd, "matchEnd discrepancy "+(matchEnd, matchEndDef)) + List(treeCopy.LabelDef(cases.last, n, ps, matchEnd APPLY (FALSE_typed)) setSymbol cases.last.symbol) + case x => Nil + } + val casesWithoutCatchAll = if(newCatchAll.isEmpty) cases else cases.init + doSubst(wrap(Block(newPrologue ++ casesReturnTrue.transformTrees(casesWithoutCatchAll) ++ newCatchAll, matchEndDef))) + + // val duped = idaBlock //.duplicate // TODO: duplication of labeldefs is BROKEN + // duped foreach { + // case l@LabelDef(name, params, rhs) if gen.hasSynthCaseSymbol(l) => println("newInfo"+ l.symbol.info) + // case _ => + // } } } + val body = isDefinedAtTransformer(bodyForIDA) body.changeOwner(fun.symbol -> methSym) @@ -328,11 +449,14 @@ abstract class UnCurry extends InfoTransform if (isPartial) List(applyOrElseMethodDef, isDefinedAtMethodDef) else List(applyMethodDef) - localTyper.typedPos(fun.pos) { + // println("MEMBERS "+ members) + val res = localTyper.typedPos(fun.pos) { Block( List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, fun.pos)), Typed(New(anonClass.tpe), TypeTree(fun.tpe))) } + // println("MEMBERS TYPED "+ members) + res } def transformArgs(pos: Position, fun: Symbol, args: List[Tree], formals: List[Type]) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index fe1c90fe67..e2d4efab83 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -67,6 +67,7 @@ trait Contexts { self: Analyzer => val c = sc.make(unit, tree, sc.owner, sc.scope, sc.imports) if (erasedTypes) c.setThrowErrors() else c.setReportErrors() c.implicitsEnabled = !erasedTypes + c.enrichmentEnabled = c.implicitsEnabled c } @@ -106,7 +107,7 @@ trait Contexts { self: Analyzer => var depth: Int = 0 var imports: List[ImportInfo] = List() // currently visible imports var openImplicits: List[(Type,Tree)] = List() // types for which implicit arguments - // are currently searched + // are currently searched // for a named application block (Tree) the corresponding NamedApplyInfo var namedApplyBlockInfo: Option[(Tree, NamedApplyInfo)] = None var prefix: Type = NoPrefix @@ -120,6 +121,7 @@ trait Contexts { self: Analyzer => var diagnostic: List[String] = Nil // these messages are printed when issuing an error var implicitsEnabled = false var macrosEnabled = true + var enrichmentEnabled = false // to selectively allow enrichment in patterns, where other kinds of implicit conversions are not allowed var checking = false var retyping = false @@ -192,8 +194,25 @@ trait Contexts { self: Analyzer => def withImplicitsDisabled[T](op: => T): T = { val saved = implicitsEnabled implicitsEnabled = false + val savedP = enrichmentEnabled + enrichmentEnabled = false try op - finally implicitsEnabled = saved + finally { + implicitsEnabled = saved + enrichmentEnabled = savedP + } + } + + def withImplicitsDisabledAllowEnrichment[T](op: => T): T = { + val saved = implicitsEnabled + implicitsEnabled = false + val savedP = enrichmentEnabled + enrichmentEnabled = true + try op + finally { + implicitsEnabled = saved + enrichmentEnabled = savedP + } } def withMacrosEnabled[T](op: => T): T = { @@ -246,6 +265,7 @@ trait Contexts { self: Analyzer => c.typingIndentLevel = typingIndentLevel c.implicitsEnabled = this.implicitsEnabled c.macrosEnabled = this.macrosEnabled + c.enrichmentEnabled = this.enrichmentEnabled c.checking = this.checking c.retyping = this.retyping c.openImplicits = this.openImplicits @@ -298,6 +318,7 @@ trait Contexts { self: Analyzer => def makeImplicit(reportAmbiguousErrors: Boolean) = { val c = makeSilent(reportAmbiguousErrors) c.implicitsEnabled = false + c.enrichmentEnabled = false c } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index b4e0ad6edf..4fb9362ccc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -166,7 +166,7 @@ trait Implicits { } def isCyclicOrErroneous = - try containsError(tpe) + try sym.hasFlag(LOCKED) || containsError(tpe) catch { case _: CyclicReference => true } var useCountArg: Int = 0 diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index d78fd35d25..fb0616c890 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1189,6 +1189,50 @@ trait Infer { } } + /** Does `tp` contain any types that cannot be checked at run-time (i.e., after erasure, will isInstanceOf[erased(tp)] imply conceptualIsInstanceOf[tp]?) + * we should find a way to ask erasure: hey, is `tp` going to make it through you with all of its isInstanceOf resolving powers intact? + * TODO: at the very least, reduce duplication wrt checkCheckable + */ + def containsUnchecked(tp: Type): Boolean = { + def check(tp: Type, bound: List[Symbol]): Boolean = { + def isSurroundingTypeParam(sym: Symbol) = { + val e = context.scope.lookupEntry(sym.name) + ( (e ne null) + && (e.sym == sym ) + && !e.sym.isTypeParameterOrSkolem + && (e.owner == context.scope) + ) + } + def isLocalBinding(sym: Symbol) = ( + sym.isAbstractType && ( + (bound contains sym) + || (sym.name == tpnme.WILDCARD) + || isSurroundingTypeParam(sym) + ) + ) + tp.normalize match { + case SingleType(pre, _) => + check(pre, bound) + case TypeRef(_, ArrayClass, arg :: _) => + check(arg, bound) + case tp @ TypeRef(pre, sym, args) => + ( (sym.isAbstractType && !isLocalBinding(sym)) + || (args exists (x => !isLocalBinding(x.typeSymbol))) + || check(pre, bound) + ) + // case RefinedType(_, decls) if decls.nonEmpty => + // patternWarning(tp, "refinement ") + case RefinedType(parents, _) => + parents exists (p => check(p, bound)) + case ExistentialType(quantified, tp1) => + check(tp1, bound ::: quantified) + case _ => + false + } + } + check(tp, Nil) + } + def checkCheckable(tree: Tree, tp: Type, kind: String) { def patternWarning(tp0: Type, prefix: String) = { context.unit.uncheckedWarning(tree.pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure") diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 988b821d1a..b7e0eaef2b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -184,8 +184,21 @@ trait Macros { self: Analyzer => def typedMacroBody(typer: Typer, ddef: DefDef): Tree = { import typer.context if (macroDebug) println("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos)) + typer.checkFeature(ddef.pos, MacrosFeature) + // [Eugene to Martin] todo. copy/pasted this from checkFeature, because don't know a better way + // this is necessary to prevent macros from typechecking/expanding when they are not enabled + // `checkFeature` call alone is not enough, because it merely posts validation callback to unit.toCheck + def hasImport = inferImplicit(EmptyTree: Tree, MacrosFeature.tpe, true, false, typer.context) != SearchFailure + val nestedOwners = MacrosFeature.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse + val featureName = (nestedOwners map (_.name + ".")).mkString + MacrosFeature.name + def hasOption = settings.language.value contains featureName + if (!hasImport && !hasOption) { + ddef.symbol setFlag IS_ERROR + return EmptyTree + } + implicit class AugmentedString(s: String) { def abbreviateCoreAliases: String = { // hack! var result = s diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala index e8e65071af..1fd9f6fc13 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -22,7 +22,7 @@ import language.postfixOps * - Array patterns * - implement spec more closely (see TODO's) * - DCE - * - use manifests for type testing + * - use TypeTags for type testing * * (longer-term) TODO: * - user-defined unapplyProd @@ -119,6 +119,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => trait MatchTranslation extends MatchMonadInterface { self: TreeMakers with CodegenCore => import typer.{typed, context, silent, reallyExists} + // import typer.infer.containsUnchecked /** Implement a pattern match by turning its cases (including the implicit failure case) * into the corresponding (monadic) extractors, and combining them with the `orElse` combinator. @@ -131,10 +132,10 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => * this could probably optimized... (but note that the matchStrategy must be solved for each nested patternmatch) */ def translateMatch(scrut: Tree, cases: List[CaseDef], pt: Type, scrutType: Type, matchFailGenOverride: Option[Tree => Tree] = None): Tree = { - // we don't transform after typers - // (that would require much more sophistication when generating trees, + // we don't transform after uncurry + // (that would require more sophistication when generating trees, // and the only place that emits Matches after typers is for exception handling anyway) - assert(phase.id <= currentRun.typerPhase.id, phase) + assert(phase.id < currentRun.uncurryPhase.id, phase) val scrutSym = freshSym(scrut.pos, pureType(scrutType)) setFlag SYNTH_CASE // pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental @@ -820,13 +821,34 @@ class Foo(x: Other) { x._1 } // no error in this order cond } - // TODO: also need to test when erasing pt loses crucial information (and if we can recover it using a manifest) - def needsTypeTest(tp: Type, pt: Type) = !(tp <:< pt) - private def typeTest(binder: Symbol, pt: Type) = maybeWithOuterCheck(binder, pt)(codegen._isInstanceOf(binder, pt)) + // containsUnchecked: also need to test when erasing pt loses crucial information (maybe we can recover it using a TypeTag) + def needsTypeTest(tp: Type, pt: Type): Boolean = !(tp <:< pt) // || containsUnchecked(pt) + // TODO: try to find the TypeTag for the binder's type and the expected type, and if they exists, + // check that the TypeTag of the binder's type conforms to the TypeTag of the expected type + private def typeTest(binderToTest: Symbol, expectedTp: Type, disableOuterCheck: Boolean = false, dynamic: Boolean = false): Tree = { import CODE._ + // def coreTest = + if (disableOuterCheck) codegen._isInstanceOf(binderToTest, expectedTp) else maybeWithOuterCheck(binderToTest, expectedTp)(codegen._isInstanceOf(binderToTest, expectedTp)) + // if (opt.experimental && containsUnchecked(expectedTp)) { + // if (dynamic) { + // val expectedTpTagTree = findManifest(expectedTp, true) + // if (!expectedTpTagTree.isEmpty) + // ((expectedTpTagTree DOT "erasure".toTermName) DOT "isAssignableFrom".toTermName)(REF(binderToTest) DOT nme.getClass_) + // else + // coreTest + // } else { + // val expectedTpTagTree = findManifest(expectedTp, true) + // val binderTpTagTree = findManifest(binderToTest.info, true) + // if(!(expectedTpTagTree.isEmpty || binderTpTagTree.isEmpty)) + // coreTest AND (binderTpTagTree DOT nme.CONFORMS)(expectedTpTagTree) + // else + // coreTest + // } + // } else coreTest + } // need to substitute since binder may be used outside of the next extractor call (say, in the body of the case) case class TypeTestTreeMaker(prevBinder: Symbol, nextBinderTp: Type, pos: Position) extends CondTreeMaker { - val cond = typeTest(prevBinder, nextBinderTp) + val cond = typeTest(prevBinder, nextBinderTp, dynamic = true) val res = codegen._asInstanceOf(prevBinder, nextBinderTp) override def toString = "TT"+(prevBinder, nextBinderTp) } @@ -866,7 +888,7 @@ class Foo(x: Other) { x._1 } // no error in this order // TODO: `null match { x : T }` will yield a check that (indirectly) tests whether `null ne null` // don't bother (so that we don't end up with the warning "comparing values of types Null and Null using `ne' will always yield false") def genEqualsAndInstanceOf(sym: Symbol): Tree - = codegen._equals(REF(sym), patBinder) AND codegen._isInstanceOf(patBinder, pt.widen) + = codegen._equals(REF(sym), patBinder) AND typeTest(patBinder, pt.widen, disableOuterCheck = true) def isRefTp(tp: Type) = tp <:< AnyRefClass.tpe @@ -874,7 +896,7 @@ class Foo(x: Other) { x._1 } // no error in this order def isMatchUnlessNull = isRefTp(pt) && !needsTypeTest(patBinderTp, pt) // TODO: [SPEC] type test for Array - // TODO: use manifests to improve tests (for erased types we can do better when we have a manifest) + // TODO: use TypeTags to improve tests (for erased types we can do better when we have a TypeTag) pt match { case SingleType(_, sym) /*this implies sym.isStable*/ => genEqualsAndInstanceOf(sym) // TODO: [SPEC] the spec requires `eq` instead of `==` here case ThisType(sym) if sym.isModule => genEqualsAndInstanceOf(sym) // must use == to support e.g. List() == Nil @@ -1083,22 +1105,14 @@ class Foo(x: Other) { x._1 } // no error in this order def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya def and(a: Tree, b: Tree): Tree = a AND b + // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any + // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree + private def mkCast(t: Tree, tp: Type) = Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp) // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly) - def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = { val tpX = /*repackExistential*/(tp) - if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tpX)) t //{ println("warning: emitted redundant asInstanceOf: "+(t, t.tpe, tp)); t } //.setType(tpX) - else gen.mkAsInstanceOf(t, tpX, true, false) - } - - def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), /*repackExistential*/(tp), true, false) - // { val tpX = /*repackExistential*/(tp) + def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp) + def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp) + def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false) // if (typesConform(b.info, tpX)) { println("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE } - // else gen.mkIsInstanceOf(REF(b), tpX, true, false) - // } - - def _asInstanceOf(b: Symbol, tp: Type): Tree = { val tpX = /*repackExistential*/(tp) - if (typesConform(b.info, tpX)) REF(b) //{ println("warning: emitted redundant asInstanceOf: "+(b, b.info, tp)); REF(b) } //.setType(tpX) - else gen.mkAsInstanceOf(REF(b), tpX, true, false) - } // duplicated out of frustration with cast generation def mkZero(tp: Type): Tree = { @@ -1636,7 +1650,7 @@ class Foo(x: Other) { x._1 } // no error in this order */ def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = { val matchEnd = NoSymbol.newLabel(freshName("matchEnd"), NoPosition) setFlag SYNTH_CASE - val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe + val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations // matchEnd setInfo MethodType(List(matchRes), restpe) def newCaseSym = NoSymbol.newLabel(freshName("case"), NoPosition) setInfo MethodType(Nil, restpe) setFlag SYNTH_CASE @@ -1650,7 +1664,11 @@ class Foo(x: Other) { x._1 } // no error in this order def catchAll = matchFailGen map { matchFailGen => val scrutRef = if(scrutSym ne NoSymbol) REF(scrutSym) else EmptyTree // for alternatives - LabelDef(nextCase, Nil, matchEnd APPLY (_asInstanceOf(matchFailGen(scrutRef), restpe))) // need to jump to matchEnd with result generated by matchFailGen (could be `FALSE` for isDefinedAt) + // must jump to matchEnd, use result generated by matchFailGen (could be `FALSE` for isDefinedAt) + LabelDef(nextCase, Nil, matchEnd APPLY (matchFailGen(scrutRef))) + // don't cast the arg to matchEnd when using PartialFun synth in uncurry, since it won't detect the throw (see gen.withDefaultCase) + // the cast is necessary when using typedMatchAnonFun-style PartialFun synth: + // (_asInstanceOf(matchFailGen(scrutRef), restpe)) } toList // catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default) // if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index af75c75156..2d656e02b4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1655,9 +1655,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R inPattern = false treeCopy.CaseDef(tree, pat1, transform(guard), transform(body)) case LabelDef(_, _, _) if gen.hasSynthCaseSymbol(result) => + val old = inPattern inPattern = true val res = deriveLabelDef(result)(transform) - inPattern = false + inPattern = old res case _ => super.transform(result) diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 45d916c633..4319dd10c7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -14,8 +14,9 @@ import util.returning abstract class TreeCheckers extends Analyzer { import global._ - private val everything = ListBuffer[(Phase, Map[Tree, (Symbol, Type)])]() + private val everything = ListBuffer[(Phase, Map[Tree, (Symbol, Type)])]() private val currentTrees = mutable.Map[Tree, (Symbol, Type)]() + private val tpeOfTree = mutable.HashMap[Tree, Type]() if (settings.debug.value) { sys addShutdownHook { @@ -49,12 +50,13 @@ abstract class TreeCheckers extends Analyzer { object SymbolTracker extends Traverser { type PhaseMap = mutable.HashMap[Symbol, List[Tree]] + val defSyms = mutable.HashMap[Symbol, List[DefTree]]() withDefaultValue Nil + val newSyms = mutable.HashSet[Symbol]() val maps = ListBuffer[(Phase, PhaseMap)]() + val movedMsgs = ListBuffer[String]() + def prev = maps.init.last._2 def latest = maps.last._2 - val defSyms = mutable.HashMap[Symbol, List[DefTree]]() - val newSyms = mutable.HashSet[Symbol]() - val movedMsgs = new ListBuffer[String] def sortedNewSyms = newSyms.toList.distinct sortBy (_.name.toString) def inPrev(sym: Symbol) = { @@ -119,10 +121,8 @@ abstract class TreeCheckers extends Analyzer { if (sym != null && sym != NoSymbol) { record(sym, tree) tree match { - case x: DefTree => - if (defSyms contains sym) defSyms(sym) = defSyms(sym) :+ x - else defSyms(sym) = List(x) - case _ => () + case x: DefTree => defSyms(sym) :+= x + case _ => () } } @@ -130,8 +130,6 @@ abstract class TreeCheckers extends Analyzer { } } - lazy val tpeOfTree = mutable.HashMap[Tree, Type]() - def posstr(p: Position) = try p.source.path + ":" + p.line catch { case _: UnsupportedOperationException => p.toString } @@ -147,9 +145,7 @@ abstract class TreeCheckers extends Analyzer { if (!cond) errorFn(msg) def checkTrees() { - if (settings.verbose.value) - Console.println("[consistency check at the beginning of phase " + phase + "]") - + informFn("[consistency check at the beginning of phase " + phase + "]") currentRun.units foreach check } @@ -172,7 +168,7 @@ abstract class TreeCheckers extends Analyzer { informProgress("checking "+unit) val context = rootContext(unit) context.checking = true - tpeOfTree.clear + tpeOfTree.clear() SymbolTracker.check(phase, unit) val checker = new TreeChecker(context) runWithUnit(unit) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a6893ff4b2..0541f85f31 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1203,7 +1203,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { && !qtpe.typeSymbol.isBottomClass && qtpe != WildcardType && !qual.isInstanceOf[ApplyImplicitView] // don't chain views - && context.implicitsEnabled + && (context.implicitsEnabled || context.enrichmentEnabled) // Elaborating `context.implicitsEnabled`: // don't try to adapt a top-level type that's the subject of an implicit search // this happens because, if isView, typedImplicit tries to apply the "current" implicit value to @@ -2193,13 +2193,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def adaptCase(cdef: CaseDef, mode: Int, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe)) - def prepareTranslateMatch(selector0: Tree, cases: List[CaseDef], mode: Int, resTp: Type) = { + def typedMatch(selector0: Tree, cases: List[CaseDef], mode: Int, resTp: Type) = { val (selector, doTranslation) = selector0 match { case Annotated(Ident(nme.synthSwitch), selector) => (selector, false) case s => (s, true) } val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType)) - val selectorTp = packCaptured(selector1.tpe.widen) + val selectorTp = packCaptured(selector1.tpe.widen.withoutAnnotations) val casesTyped = typedCases(cases, selectorTp, resTp) val caseTypes = casesTyped map (c => packedType(c, context.owner).deconst) @@ -2210,7 +2210,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { (selector1, selectorTp, casesAdapted, ownType, doTranslation) } - def translateMatch(selector1: Tree, selectorTp: Type, casesAdapted: List[CaseDef], ownType: Type, doTranslation: Boolean, matchFailGen: Option[Tree => Tree] = None) = { + def translatedMatch(selector1: Tree, selectorTp: Type, casesAdapted: List[CaseDef], ownType: Type, doTranslation: Boolean, matchFailGen: Option[Tree => Tree] = None) = { def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match { case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg) case _ => tp @@ -2220,10 +2220,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { Match(selector1, casesAdapted) setType ownType // setType of the Match to avoid recursing endlessly } else { val scrutType = repeatedToSeq(elimAnonymousClass(selectorTp)) - // we've packed the type for each case in prepareTranslateMatch so that if all cases have the same existential case, we get a clean lub + // we've packed the type for each case in typedMatch so that if all cases have the same existential case, we get a clean lub // here, we should open up the existential again // relevant test cases: pos/existentials-harmful.scala, pos/gadt-gilles.scala, pos/t2683.scala, pos/virtpatmat_exist4.scala - MatchTranslator(this).translateMatch(selector1, casesAdapted, repeatedToSeq(ownType.skolemizeExistential(context.owner, context.tree)), scrutType, matchFailGen) + // TODO: fix skolemizeExistential (it should preserve annotations, right?) + val ownTypeSkolemized = ownType.skolemizeExistential(context.owner, context.tree) withAnnotations ownType.annotations + MatchTranslator(this).translateMatch(selector1, casesAdapted, repeatedToSeq(ownTypeSkolemized), scrutType, matchFailGen) } } @@ -2283,7 +2285,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it) paramSyms foreach (methodBodyTyper.context.scope enter _) - val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, cases, mode, ptRes) + val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.typedMatch(selector, cases, mode, ptRes) val methFormals = paramSyms map (_.tpe) val parents = List(abstractFunctionType(methFormals, resTp), SerializableClass.tpe) @@ -2291,7 +2293,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { anonClass setInfo ClassInfoType(parents, newScope, anonClass) methodSym setInfoAndEnter MethodType(paramSyms, resTp) - DefDef(methodSym, methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation)) + DefDef(methodSym, methodBodyTyper.translatedMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation)) } } @@ -2321,7 +2323,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it) paramSyms foreach (methodBodyTyper.context.scope enter _) - val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, cases, mode, ptRes) + val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.typedMatch(selector, cases, mode, ptRes) anonClass setInfo ClassInfoType(parents(List(argTp, resTp)), newScope, anonClass) B1 setInfo TypeBounds.lower(resTp) @@ -2330,7 +2332,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // use applyOrElse's first parameter since the scrut's type has been widened def doDefault(scrut_ignored: Tree) = REF(default) APPLY (REF(x)) - val body = methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, B1.tpe, doTranslation, Some(doDefault)) + val body = methodBodyTyper.translatedMatch(selector1, selectorTp, casesAdapted, B1.tpe, doTranslation, Some(doDefault)) DefDef(methodSym, body) } @@ -2345,8 +2347,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { paramSyms foreach (methodBodyTyper.context.scope enter _) methodSym setInfoAndEnter MethodType(paramSyms, BooleanClass.tpe) - val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, casesTrue, mode, BooleanClass.tpe) - val body = methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation, Some(scrutinee => FALSE_typed)) + val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.typedMatch(selector, casesTrue, mode, BooleanClass.tpe) + val body = methodBodyTyper.translatedMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation, Some(scrutinee => FALSE_typed)) DefDef(methodSym, body) } @@ -2407,29 +2409,21 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - fun.body match { - case Match(sel, cases) if opt.virtPatmat => - // go to outer context -- must discard the context that was created for the Function since we're discarding the function - // thus, its symbol, which serves as the current context.owner, is not the right owner - // you won't know you're using the wrong owner until lambda lift crashes (unless you know better than to use the wrong owner) - newTyper(context.outer).typedMatchAnonFun(fun, cases, mode, pt, Some((fun.vparams, sel))) - case _ => - val vparamSyms = fun.vparams map { vparam => - enterSym(context, vparam) - if (context.retyping) context.scope enter vparam.symbol - vparam.symbol - } - val vparams = fun.vparams mapConserve (typedValDef) - // for (vparam <- vparams) { - // checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); () - // } - val formals = vparamSyms map (_.tpe) - val body1 = typed(fun.body, respt) - val restpe = packedType(body1, fun.symbol).deconst.resultType - val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe) - // body = checkNoEscaping.locals(context.scope, restpe, body) - treeCopy.Function(fun, vparams, body1).setType(funtpe) + val vparamSyms = fun.vparams map { vparam => + enterSym(context, vparam) + if (context.retyping) context.scope enter vparam.symbol + vparam.symbol } + val vparams = fun.vparams mapConserve (typedValDef) +// for (vparam <- vparams) { +// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); () +// } + val formals = vparamSyms map (_.tpe) + val body1 = typed(fun.body, respt) + val restpe = packedType(body1, fun.symbol).deconst.resultType + val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe) +// body = checkNoEscaping.locals(context.scope, restpe, body) + treeCopy.Function(fun, vparams, body1).setType(funtpe) } } @@ -3780,12 +3774,16 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { lazy val thenTp = packedType(thenp1, context.owner) lazy val elseTp = packedType(elsep1, context.owner) + // println("typedIf: "+(thenp1.tpe, elsep1.tpe, ptOrLub(List(thenp1.tpe, elsep1.tpe)),"\n", thenTp, elseTp, thenTp =:= elseTp)) val (owntype, needAdapt) = // in principle we should pack the types of each branch before lubbing, but lub doesn't really work for existentials anyway // in the special (though common) case where the types are equal, it pays to pack before comparing // especially virtpatmat needs more aggressive unification of skolemized types // this breaks src/library/scala/collection/immutable/TrieIterator.scala - if (opt.virtPatmat && !isPastTyper && thenTp =:= elseTp) (thenp1.tpe, false) // use unpacked type + if ( opt.virtPatmat && !isPastTyper + && thenp1.tpe.annotations.isEmpty && elsep1.tpe.annotations.isEmpty // annotated types need to be lubbed regardless (at least, continations break if you by pass them like this) + && thenTp =:= elseTp + ) (thenp1.tpe, false) // use unpacked type // TODO: skolemize (lub of packed types) when that no longer crashes on files/pos/t4070b.scala else ptOrLub(List(thenp1.tpe, elsep1.tpe)) @@ -3797,13 +3795,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - def typedMatch(tree: Tree, selector: Tree, cases: List[CaseDef]): Tree = { - if (opt.virtPatmat && !isPastTyper) { - if (selector ne EmptyTree) { - val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = prepareTranslateMatch(selector, cases, mode, pt) - typed(translateMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt) - } else typedMatchAnonFun(tree, cases, mode, pt) - } else if (selector == EmptyTree) { + // translation only happens when (selector != EmptyTree) && !isPastTyper && opt.virtPatmat + def typedTranslatedMatch(tree: Tree, selector: Tree, cases: List[CaseDef]): Tree = { + if (selector == EmptyTree) { val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1 val params = for (i <- List.range(0, arity)) yield atPos(tree.pos.focusStart) { @@ -3814,7 +3808,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) } val body = treeCopy.Match(tree, selector1, cases) typed1(atPos(tree.pos) { Function(params, body) }, mode, pt) - } else { + } else if (!((phase.id < currentRun.uncurryPhase.id) && opt.virtPatmat)) { val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType)) var cases1 = typedCases(cases, packCaptured(selector1.tpe.widen), pt) val (owntype, needAdapt) = ptOrLub(cases1 map (_.tpe)) @@ -3822,6 +3816,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { cases1 = cases1 map (adaptCase(_, mode, owntype)) } treeCopy.Match(tree, selector1, cases1) setType owntype + } else { + val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = typedMatch(selector, cases, mode, pt) + typed(translatedMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt) } } @@ -4213,7 +4210,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } else { member(qual, name) } - if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) { + + // symbol not found? --> try to convert implicitly to a type that does have the required member + // added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an xml member to StringContext, which in turn has an unapply[Seq] method) + if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & (EXPRmode | PATTERNmode)) != 0) { val qual1 = if (member(qual, name) != NoSymbol) qual else adaptToMemberWithArgs(tree, qual, name, mode, true, true) @@ -4221,6 +4221,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt) } + if (!reallyExists(sym)) { if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) { val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) } @@ -4681,7 +4682,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { typedIf(cond, thenp, elsep) case tree @ Match(selector, cases) => - typedMatch(tree, selector, cases) + typedTranslatedMatch(tree, selector, cases) case Return(expr) => typedReturn(expr) @@ -4697,7 +4698,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { catches1 = catches1 map (adaptCase(_, mode, owntype)) } - if(!isPastTyper && opt.virtPatmat) { + if((phase.id < currentRun.uncurryPhase.id) && opt.virtPatmat) { catches1 = (MatchTranslator(this)).translateTry(catches1, owntype, tree.pos) } @@ -4957,6 +4958,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { ptLine("typing %s: pt = %s".format(ptTree(tree), pt), "undetparams" -> context.undetparams, "implicitsEnabled" -> context.implicitsEnabled, + "enrichmentEnabled" -> context.enrichmentEnabled, + "mode" -> modeString(mode), "silent" -> context.bufferErrors, "context.owner" -> context.owner ) @@ -5060,7 +5063,22 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // We disable implicits because otherwise some constructs will // type check which should not. The pattern matcher does not // perform implicit conversions in an attempt to consummate a match. - context.withImplicitsDisabled(typed(tree, PATTERNmode, pt)) + + // on the one hand, + // "abc" match { case Seq('a', 'b', 'c') => true } + // should be ruled out statically, otherwise this is a runtime + // error both because there is an implicit from String to Seq + // (even though such implicits are not used by the matcher) and + // because the typer is fine with concluding that "abc" might + // be of type "String with Seq[T]" and thus eligible for a call + // to unapplySeq. + + // on the other hand, we want to be able to use implicits to add members retro-actively (e.g., add xml to StringContext) + + // as a compromise, context.enrichmentEnabled tells adaptToMember to go ahead and enrich, + // but arbitrary conversions (in adapt) are disabled + // TODO: can we achieve the pattern matching bit of the string interpolation SIP without this? + context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt)) } /** Types a (fully parameterized) type tree */ diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index a6737573ea..0975f16c6e 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -71,24 +71,46 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with // { x => x match { case A => ... }} to // { x => shiftUnit(x match { case A => ... })} // which Uncurry cannot handle (see function6.scala) + // thus, we push down the shiftUnit to each of the case bodies val ext = getExternalAnswerTypeAnn(body.tpe) + val pureBody = getAnswerTypeAnn(body.tpe).isEmpty + + def transformPureMatch(tree: Tree, selector: Tree, cases: List[CaseDef]) = { + val caseVals = cases map { case cd @ CaseDef(pat, guard, body) => + // if (!hasPlusMarker(body.tpe)) body.tpe = body.tpe withAnnotation newPlusMarker() // TODO: to avoid warning + val bodyVal = transExpr(body, None, ext) // ??? triggers "cps-transformed unexpectedly" warning in transTailValue + treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal) + } + treeCopy.Match(tree, transform(selector), caseVals) + } + + def transformPureVirtMatch(body: Block, selDef: ValDef, cases: List[Tree], matchEnd: Tree) = { + val stats = transform(selDef) :: (cases map (transExpr(_, None, ext))) + treeCopy.Block(body, stats, transExpr(matchEnd, None, ext)) + } val body1 = body match { - case Match(selector, cases) if (ext.isDefined && getAnswerTypeAnn(body.tpe).isEmpty) => - val cases1 = for { - cd @ CaseDef(pat, guard, caseBody) <- cases - caseBody1 = transExpr(body, None, ext) - } yield { - treeCopy.CaseDef(cd, transform(pat), transform(guard), caseBody1) - } - treeCopy.Match(tree, transform(selector), cases1) + case Match(selector, cases) if ext.isDefined && pureBody => + transformPureMatch(body, selector, cases) + + // virtpatmat switch + case Block(List(selDef: ValDef), mat@Match(selector, cases)) if ext.isDefined && pureBody => + treeCopy.Block(body, List(transform(selDef)), transformPureMatch(mat, selector, cases)) + + // virtpatmat + case b@Block(matchStats@((selDef: ValDef) :: cases), matchEnd) if ext.isDefined && pureBody && (matchStats forall gen.hasSynthCaseSymbol) => + transformPureVirtMatch(b, selDef, cases, matchEnd) + + // virtpatmat that stores the scrut separately -- TODO: can we eliminate this case?? + case Block(List(selDef0: ValDef), mat@Block(matchStats@((selDef: ValDef) :: cases), matchEnd)) if ext.isDefined && pureBody && (matchStats forall gen.hasSynthCaseSymbol)=> + treeCopy.Block(body, List(transform(selDef0)), transformPureVirtMatch(mat, selDef, cases, matchEnd)) case _ => transExpr(body, None, ext) } - debuglog("result "+body1) + debuglog("anf result "+body1) debuglog("result is of type "+body1.tpe) treeCopy.Function(ff, transformValDefs(vparams), body1) @@ -170,63 +192,72 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with tree match { case Block(stms, expr) => val (cpsA2, cpsR2) = (cpsA, linearize(cpsA, getAnswerTypeAnn(tree.tpe))) // tbd -// val (cpsA2, cpsR2) = (None, getAnswerTypeAnn(tree.tpe)) - val (a, b) = transBlock(stms, expr, cpsA2, cpsR2) + // val (cpsA2, cpsR2) = (None, getAnswerTypeAnn(tree.tpe)) - val tree1 = (treeCopy.Block(tree, a, b)) // no updateSynthFlag here!!! + val (a, b) = transBlock(stms, expr, cpsA2, cpsR2) + val tree1 = (treeCopy.Block(tree, a, b)) // no updateSynthFlag here!!! (Nil, tree1, cpsA) - case If(cond, thenp, elsep) => - /* possible situations: - cps before (cpsA) - cps in condition (spc) <-- synth flag set if *only* here! - cps in (one or both) branches */ - val (condStats, condVal, spc) = transInlineValue(cond, cpsA) - val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe)) - (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else - (None, getAnswerTypeAnn(tree.tpe)) // if no cps in condition, branches must conform to tree.tpe directly - val thenVal = transExpr(thenp, cpsA2, cpsR2) - val elseVal = transExpr(elsep, cpsA2, cpsR2) - - // check that then and else parts agree (not necessary any more, but left as sanity check) - if (cpsR.isDefined) { - if (elsep == EmptyTree) - unit.error(tree.pos, "always need else part in cps code") - } - if (hasAnswerTypeAnn(thenVal.tpe) != hasAnswerTypeAnn(elseVal.tpe)) { - unit.error(tree.pos, "then and else parts must both be cps code or neither of them") - } - - (condStats, updateSynthFlag(treeCopy.If(tree, condVal, thenVal, elseVal)), spc) + case If(cond, thenp, elsep) => + /* possible situations: + cps before (cpsA) + cps in condition (spc) <-- synth flag set if *only* here! + cps in (one or both) branches */ + val (condStats, condVal, spc) = transInlineValue(cond, cpsA) + val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe)) + (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else + (None, getAnswerTypeAnn(tree.tpe)) // if no cps in condition, branches must conform to tree.tpe directly + val thenVal = transExpr(thenp, cpsA2, cpsR2) + val elseVal = transExpr(elsep, cpsA2, cpsR2) + + // check that then and else parts agree (not necessary any more, but left as sanity check) + if (cpsR.isDefined) { + if (elsep == EmptyTree) + unit.error(tree.pos, "always need else part in cps code") + } + if (hasAnswerTypeAnn(thenVal.tpe) != hasAnswerTypeAnn(elseVal.tpe)) { + unit.error(tree.pos, "then and else parts must both be cps code or neither of them") + } - case Match(selector, cases) => + (condStats, updateSynthFlag(treeCopy.If(tree, condVal, thenVal, elseVal)), spc) - val (selStats, selVal, spc) = transInlineValue(selector, cpsA) - val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe)) - (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else - (None, getAnswerTypeAnn(tree.tpe)) + case Match(selector, cases) => + val (selStats, selVal, spc) = transInlineValue(selector, cpsA) + val (cpsA2, cpsR2) = + if (hasSynthMarker(tree.tpe)) (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) + else (None, getAnswerTypeAnn(tree.tpe)) - val caseVals = for { - cd @ CaseDef(pat, guard, body) <- cases - bodyVal = transExpr(body, cpsA2, cpsR2) - } yield { - treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal) - } + val caseVals = cases map { case cd @ CaseDef(pat, guard, body) => + val bodyVal = transExpr(body, cpsA2, cpsR2) + treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal) + } - (selStats, updateSynthFlag(treeCopy.Match(tree, selVal, caseVals)), spc) + (selStats, updateSynthFlag(treeCopy.Match(tree, selVal, caseVals)), spc) + // this is utterly broken: LabelDefs need to be considered together when transforming them to DefDefs: + // suppose a Block {L1; ... ; LN} + // this should become {D1def ; ... ; DNdef ; D1()} + // where D$idef = def L$i(..) = {L$i.body; L${i+1}(..)} case ldef @ LabelDef(name, params, rhs) => if (hasAnswerTypeAnn(tree.tpe)) { - val sym = currentOwner.newMethod(name, tree.pos, Flags.SYNTHETIC) setInfo ldef.symbol.info - val rhs1 = new TreeSymSubstituter(List(ldef.symbol), List(sym)).transform(rhs) + // currentOwner.newMethod(name, tree.pos, Flags.SYNTHETIC) setInfo ldef.symbol.info + val sym = ldef.symbol resetFlag Flags.LABEL + val rhs1 = rhs //new TreeSymSubstituter(List(ldef.symbol), List(sym)).transform(rhs) val rhsVal = transExpr(rhs1, None, getAnswerTypeAnn(tree.tpe)) changeOwner (currentOwner -> sym) val stm1 = localTyper.typed(DefDef(sym, rhsVal)) - val expr = localTyper.typed(Apply(Ident(sym), List())) - - (List(stm1), expr, cpsA) + // since virtpatmat does not rely on fall-through, don't call the labels it emits + // transBlock will take care of calling the first label + // calling each labeldef is wrong, since some labels may be jumped over + // we can get away with this for now since the only other labels we emit are for tailcalls/while loops, + // which do not have consecutive labeldefs (and thus fall-through is irrelevant) + if (gen.hasSynthCaseSymbol(ldef)) (List(stm1), localTyper.typed{Literal(Constant(()))}, cpsA) + else { + assert(params.isEmpty, "problem in ANF transforming label with non-empty params "+ ldef) + (List(stm1), localTyper.typed{Apply(Ident(sym), List())}, cpsA) + } } else { val rhsVal = transExpr(rhs, None, None) (Nil, updateSynthFlag(treeCopy.LabelDef(tree, name, params, rhsVal)), cpsA) @@ -412,18 +443,29 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with } def transBlock(stms: List[Tree], expr: Tree, cpsA: CPSInfo, cpsR: CPSInfo): (List[Tree], Tree) = { - stms match { - case Nil => - transTailValue(expr, cpsA, cpsR) - - case stm::rest => - var (rest2, expr2) = (rest, expr) - val (headStms, headSpc) = transInlineStm(stm, cpsA) - val (restStms, restExpr) = transBlock(rest2, expr2, headSpc, cpsR) - (headStms:::restStms, restExpr) - } + def rec(currStats: List[Tree], currAns: CPSInfo, accum: List[Tree]): (List[Tree], Tree) = + currStats match { + case Nil => + val (anfStats, anfExpr) = transTailValue(expr, currAns, cpsR) + (accum ++ anfStats, anfExpr) + + case stat :: rest => + val (stats, nextAns) = transInlineStm(stat, currAns) + rec(rest, nextAns, accum ++ stats) + } + + val (anfStats, anfExpr) = rec(stms, cpsA, List()) + // println("\nanf-block:\n"+ ((stms :+ expr) mkString ("{", "\n", "}")) +"\nBECAME\n"+ ((anfStats :+ anfExpr) mkString ("{", "\n", "}"))) + + if (anfStats.nonEmpty && (anfStats forall gen.hasSynthCaseSymbol)) { + val (prologue, rest) = (anfStats :+ anfExpr) span (s => !s.isInstanceOf[DefDef]) // find first case + // val (defs, calls) = rest partition (_.isInstanceOf[DefDef]) + if (rest nonEmpty){ + val stats = prologue ++ rest.reverse // ++ calls + // println("REVERSED "+ (stats mkString ("{", "\n", "}"))) + (stats, localTyper.typed{Apply(Ident(rest.head.symbol), List())}) // call first label to kick-start the match + } else (anfStats, anfExpr) + } else (anfStats, anfExpr) } - - } } diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index 6453671eac..2db4054ef5 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -15,7 +15,7 @@ import scala.tools.nsc.ast._ * In methods marked @cps, CPS-transform assignments introduced by ANF-transform phase. */ abstract class SelectiveCPSTransform extends PluginComponent with - InfoTransform with TypingTransformers with CPSUtils { + InfoTransform with TypingTransformers with CPSUtils with TreeDSL { // inherits abstract value `global` and class `Phase` from Transform import global._ // the global environment @@ -203,12 +203,16 @@ abstract class SelectiveCPSTransform extends PluginComponent with rhs.changeOwner(currentOwner -> fun.symbol) val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe) - val catch2 = { localTyper.typedCases(List( - CaseDef(Bind(exSym, Typed(Ident("_"), TypeTree(ThrowableClass.tpe))), - Apply(Select(Ident(funSym), nme.isDefinedAt), List(Ident(exSym))), - Apply(Ident(funSym), List(Ident(exSym)))) - ), ThrowableClass.tpe, targettp) } + import CODE._ + // generate a case that is supported directly by the back-end + val catchIfDefined = CaseDef( + Bind(exSym, Ident(nme.WILDCARD)), + EmptyTree, + IF ((REF(funSym) DOT nme.isDefinedAt)(REF(exSym))) THEN (REF(funSym) APPLY (REF(exSym))) ELSE Throw(REF(exSym)) + ) + + val catch2 = localTyper.typedCases(List(catchIfDefined), ThrowableClass.tpe, targettp) //typedCases(tree, catches, ThrowableClass.tpe, pt) localTyper.typed(Block(List(funDef), treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catch2, finalizer1))) diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 6ddb2ea673..d659a9e9eb 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -294,18 +294,24 @@ trait Trees { self: Universe => override var symbol: Symbol = NoSymbol } + /** A tree with a name - effectively, a DefTree or RefTree. + */ + trait NameTree extends Tree { + def name: Name + } + /** A tree which references a symbol-carrying entity. * References one, as opposed to defining one; definitions * are in DefTrees. */ - trait RefTree extends SymTree { + trait RefTree extends SymTree with NameTree { def qualifier: Tree // empty for Idents def name: Name } /** A tree which defines a symbol-carrying entity. */ - abstract class DefTree extends SymTree { + abstract class DefTree extends SymTree with NameTree { def name: Name override def isDef = true } diff --git a/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.check b/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.check deleted file mode 100644 index 25df9a6a4a..0000000000 --- a/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.check +++ /dev/null @@ -1,10 +0,0 @@ -macro-deprecate-dont-touch-backquotedidents.scala:37: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
-package `macro` {
- ^
-macro-deprecate-dont-touch-backquotedidents.scala:38: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- package `macro`.bar {
- ^
-macro-deprecate-dont-touch-backquotedidents.scala:43: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- package `macro`.foo {
- ^
-three errors found
diff --git a/test/disabled/neg/macro-deprecate-idents.check b/test/disabled/neg/macro-deprecate-idents.check deleted file mode 100644 index bd685fc7b9..0000000000 --- a/test/disabled/neg/macro-deprecate-idents.check +++ /dev/null @@ -1,46 +0,0 @@ -macro-deprecate-idents.scala:2: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- val macro = ???
- ^
-macro-deprecate-idents.scala:6: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- var macro = ???
- ^
-macro-deprecate-idents.scala:10: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- type macro = Int
- ^
-macro-deprecate-idents.scala:14: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- class macro
- ^
-macro-deprecate-idents.scala:18: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- class macro
- ^
-macro-deprecate-idents.scala:22: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- object macro
- ^
-macro-deprecate-idents.scala:26: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- object macro
- ^
-macro-deprecate-idents.scala:30: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- trait macro
- ^
-macro-deprecate-idents.scala:34: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- trait macro
- ^
-macro-deprecate-idents.scala:37: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
-package macro {
- ^
-macro-deprecate-idents.scala:38: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- package macro.bar {
- ^
-macro-deprecate-idents.scala:43: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- package macro.foo {
- ^
-macro-deprecate-idents.scala:48: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- val Some(macro) = Some(42)
- ^
-macro-deprecate-idents.scala:50: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- case macro => println(macro)
- ^
-macro-deprecate-idents.scala:55: error: in future versions of Scala "macro" will be a keyword. consider using a different name.
- def macro = 2
- ^
-15 errors found
diff --git a/test/disabled/neg/macro-invalidshape-d.check b/test/disabled/neg/macro-invalidshape-d.check deleted file mode 100644 index 031aa653ab..0000000000 --- a/test/disabled/neg/macro-invalidshape-d.check +++ /dev/null @@ -1,4 +0,0 @@ -Macros_Test_2.scala:2: error: illegal start of statement
- def foo(x: Any) = {2; macro Impls.foo}
- ^
-one error found
diff --git a/test/disabled/neg/macro-keyword-bind.flags b/test/disabled/neg/macro-keyword-bind.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-bind.flags +++ b/test/disabled/neg/macro-keyword-bind.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-class1.flags b/test/disabled/neg/macro-keyword-class1.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-class1.flags +++ b/test/disabled/neg/macro-keyword-class1.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-class2.flags b/test/disabled/neg/macro-keyword-class2.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-class2.flags +++ b/test/disabled/neg/macro-keyword-class2.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-object1.flags b/test/disabled/neg/macro-keyword-object1.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-object1.flags +++ b/test/disabled/neg/macro-keyword-object1.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-object2.flags b/test/disabled/neg/macro-keyword-object2.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-object2.flags +++ b/test/disabled/neg/macro-keyword-object2.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-package1.flags b/test/disabled/neg/macro-keyword-package1.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-package1.flags +++ b/test/disabled/neg/macro-keyword-package1.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-package2.flags b/test/disabled/neg/macro-keyword-package2.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-package2.flags +++ b/test/disabled/neg/macro-keyword-package2.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-trait1.flags b/test/disabled/neg/macro-keyword-trait1.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-trait1.flags +++ b/test/disabled/neg/macro-keyword-trait1.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-trait2.flags b/test/disabled/neg/macro-keyword-trait2.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-trait2.flags +++ b/test/disabled/neg/macro-keyword-trait2.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-type.flags b/test/disabled/neg/macro-keyword-type.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-type.flags +++ b/test/disabled/neg/macro-keyword-type.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-keyword-val.flags b/test/disabled/neg/macro-keyword-val.flags index 7fea2ff901..cd66464f2f 100644 --- a/test/disabled/neg/macro-keyword-val.flags +++ b/test/disabled/neg/macro-keyword-val.flags @@ -1 +1 @@ --Xmacros
\ No newline at end of file +-language:experimental.macros
\ No newline at end of file diff --git a/test/disabled/neg/macro-without-xmacros-a.check b/test/disabled/neg/macro-without-xmacros-a.check deleted file mode 100644 index a3ca081f04..0000000000 --- a/test/disabled/neg/macro-without-xmacros-a.check +++ /dev/null @@ -1,10 +0,0 @@ -Macros_2.scala:5: error: not found: value macro
- def foo(x: Int): Int = macro foo_impl
- ^
-Macros_2.scala:7: error: not found: value macro
- def bar(x: Int): Int = macro bar_impl
- ^
-Macros_2.scala:11: error: not found: value macro
- def quux(x: Int): Int = macro quux_impl
- ^
-three errors found
diff --git a/test/disabled/neg/macro-without-xmacros-b.check b/test/disabled/neg/macro-without-xmacros-b.check deleted file mode 100644 index dce4a084c9..0000000000 --- a/test/disabled/neg/macro-without-xmacros-b.check +++ /dev/null @@ -1,10 +0,0 @@ -Macros_2.scala:3: error: ';' expected but '.' found.
- def foo(x: Int): Int = macro Impls.foo_impl
- ^
-Macros_2.scala:5: error: ';' expected but '.' found.
- def bar(x: Int): Int = macro Impls.bar_impl
- ^
-Macros_2.scala:9: error: ';' expected but '.' found.
- def quux(x: Int): Int = macro Impls.quux_impl
- ^
-three errors found
diff --git a/test/disabled/run/macro-reflective-mamd-normal-mi.check b/test/disabled/run/macro-reflective-mamd-normal-mi.check deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/disabled/run/macro-reflective-mamd-normal-mi.check +++ /dev/null diff --git a/test/disabled/run/macro-reflective-mamd-normal-mi.flags b/test/disabled/run/macro-reflective-mamd-normal-mi.flags deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/disabled/run/macro-reflective-mamd-normal-mi.flags +++ /dev/null diff --git a/test/files/buildmanager/t2559/D.scala b/test/files/buildmanager/t2559/D.scala index 906b69a3e7..62dc5427f9 100644 --- a/test/files/buildmanager/t2559/D.scala +++ b/test/files/buildmanager/t2559/D.scala @@ -1,8 +1,4 @@ object D { - def x(a: A) = - a match { - case _: B => () - case _: C => () - } + def x(a: A) = if (a.isInstanceOf[B] || a.isInstanceOf[C]) () } diff --git a/test/files/buildmanager/t2559/t2559.check b/test/files/buildmanager/t2559/t2559.check index 752278fbe8..4d43838cf5 100644 --- a/test/files/buildmanager/t2559/t2559.check +++ b/test/files/buildmanager/t2559/t2559.check @@ -6,9 +6,4 @@ compiling Set(A.scala) Changes: Map(class B -> List(), class C -> List(), class E -> List(Changed(Class(A))[class E extends a sealed trait A]), trait A -> List()) invalidate D.scala because it references changed class [Changed(Class(A))[class E extends a sealed trait A]] compiling Set(D.scala) -D.scala:3: warning: match is not exhaustive! -missing combination E - - a match { - ^ Changes: Map(object D -> List()) diff --git a/test/files/continuations-run/match2.scala b/test/files/continuations-run/match2.scala index 8b0fb946df..5092ce3abe 100644 --- a/test/files/continuations-run/match2.scala +++ b/test/files/continuations-run/match2.scala @@ -18,7 +18,7 @@ object Test { } - def main(args: Array[String]): Any = { + def main(args: Array[String]): Unit = { println(reset(test1())) println(reset(test2())) } diff --git a/test/files/jvm/interpreter.scala b/test/files/jvm/interpreter.scala index 1f289d9335..755b2ac9ae 100644 --- a/test/files/jvm/interpreter.scala +++ b/test/files/jvm/interpreter.scala @@ -2,7 +2,7 @@ import scala.tools.nsc._ import scala.tools.partest.ReplTest object Test extends ReplTest { - override def extraSettings = "-deprecation" + override def extraSettings = "-deprecation -Xoldpatmat" def code = <code> // basics 3+4 diff --git a/test/files/neg/array-not-seq.check b/test/files/neg/array-not-seq.check index c16ecdad72..a3a639e772 100644 --- a/test/files/neg/array-not-seq.check +++ b/test/files/neg/array-not-seq.check @@ -1,7 +1,13 @@ array-not-seq.scala:2: error: An Array will no longer match as Seq[_]. def f1(x: Any) = x.isInstanceOf[Seq[_]] ^ -error: An Array will no longer match as Seq[_]. -error: An Array will no longer match as Seq[_]. -error: An Array will no longer match as Seq[_]. +array-not-seq.scala:4: error: An Array will no longer match as Seq[_]. + case _: Seq[_] => true + ^ +array-not-seq.scala:16: error: An Array will no longer match as Seq[_]. + case (Some(_: Seq[_]), Nil, _) => 1 + ^ +array-not-seq.scala:17: error: An Array will no longer match as Seq[_]. + case (None, List(_: List[_], _), _) => 2 + ^ four errors found diff --git a/test/files/neg/exhausting.flags b/test/files/neg/exhausting.flags index e8fb65d50c..b7eb21d5f5 100644 --- a/test/files/neg/exhausting.flags +++ b/test/files/neg/exhausting.flags @@ -1 +1 @@ --Xfatal-warnings
\ No newline at end of file +-Xfatal-warnings -Xoldpatmat diff --git a/test/files/neg/gadts1.check b/test/files/neg/gadts1.check index 44d2b114d6..0441f604c9 100644 --- a/test/files/neg/gadts1.check +++ b/test/files/neg/gadts1.check @@ -11,4 +11,7 @@ gadts1.scala:20: error: type mismatch; required: a case Cell[a](x: Int) => c.x = 5 ^ -three errors found +gadts1.scala:20: error: Could not typecheck extractor call: case class <none> with arguments List((x @ (_: Int))) + case Cell[a](x: Int) => c.x = 5 + ^ +four errors found diff --git a/test/files/neg/macro-deprecate-idents.check b/test/files/neg/macro-deprecate-idents.check new file mode 100644 index 0000000000..f8a7e519df --- /dev/null +++ b/test/files/neg/macro-deprecate-idents.check @@ -0,0 +1,52 @@ +macro-deprecate-idents.scala:2: error: macro is now a reserved word; usage as an identifier is deprecated
+ val macro = ???
+ ^
+macro-deprecate-idents.scala:6: error: macro is now a reserved word; usage as an identifier is deprecated
+ var macro = ???
+ ^
+macro-deprecate-idents.scala:10: error: macro is now a reserved word; usage as an identifier is deprecated
+ type macro = Int
+ ^
+macro-deprecate-idents.scala:14: error: macro is now a reserved word; usage as an identifier is deprecated
+ class macro
+ ^
+macro-deprecate-idents.scala:18: error: macro is now a reserved word; usage as an identifier is deprecated
+ class macro
+ ^
+macro-deprecate-idents.scala:22: error: macro is now a reserved word; usage as an identifier is deprecated
+ object macro
+ ^
+macro-deprecate-idents.scala:26: error: macro is now a reserved word; usage as an identifier is deprecated
+ object macro
+ ^
+macro-deprecate-idents.scala:30: error: macro is now a reserved word; usage as an identifier is deprecated
+ trait macro
+ ^
+macro-deprecate-idents.scala:34: error: macro is now a reserved word; usage as an identifier is deprecated
+ trait macro
+ ^
+macro-deprecate-idents.scala:37: error: macro is now a reserved word; usage as an identifier is deprecated
+package macro {
+ ^
+macro-deprecate-idents.scala:38: error: macro is now a reserved word; usage as an identifier is deprecated
+ package macro.bar {
+ ^
+macro-deprecate-idents.scala:43: error: macro is now a reserved word; usage as an identifier is deprecated
+ package macro.foo {
+ ^
+macro-deprecate-idents.scala:48: error: macro is now a reserved word; usage as an identifier is deprecated
+ val Some(macro) = Some(42)
+ ^
+macro-deprecate-idents.scala:49: error: macro is now a reserved word; usage as an identifier is deprecated
+ macro match {
+ ^
+macro-deprecate-idents.scala:50: error: macro is now a reserved word; usage as an identifier is deprecated
+ case macro => println(macro)
+ ^
+macro-deprecate-idents.scala:50: error: macro is now a reserved word; usage as an identifier is deprecated
+ case macro => println(macro)
+ ^
+macro-deprecate-idents.scala:55: error: macro is now a reserved word; usage as an identifier is deprecated
+ def macro = 2
+ ^
+17 errors found
diff --git a/test/disabled/neg/macro-deprecate-idents.flags b/test/files/neg/macro-deprecate-idents.flags index e8fb65d50c..e8fb65d50c 100644 --- a/test/disabled/neg/macro-deprecate-idents.flags +++ b/test/files/neg/macro-deprecate-idents.flags diff --git a/test/disabled/neg/macro-deprecate-idents.scala b/test/files/neg/macro-deprecate-idents.scala index 23c398e341..23c398e341 100644 --- a/test/disabled/neg/macro-deprecate-idents.scala +++ b/test/files/neg/macro-deprecate-idents.scala diff --git a/test/files/neg/macro-invalidshape-d.check b/test/files/neg/macro-invalidshape-d.check new file mode 100644 index 0000000000..f0d77e2f2d --- /dev/null +++ b/test/files/neg/macro-invalidshape-d.check @@ -0,0 +1,8 @@ +Macros_Test_2.scala:2: warning: macro is now a reserved word; usage as an identifier is deprecated
+ def foo(x: Any) = {2; macro Impls.foo}
+ ^
+Macros_Test_2.scala:2: error: ';' expected but '.' found.
+ def foo(x: Any) = {2; macro Impls.foo}
+ ^
+one warning found
+one error found
diff --git a/test/disabled/neg/macro-invalidshape-d.flags b/test/files/neg/macro-invalidshape-d.flags index cd66464f2f..cd66464f2f 100644 --- a/test/disabled/neg/macro-invalidshape-d.flags +++ b/test/files/neg/macro-invalidshape-d.flags diff --git a/test/disabled/neg/macro-invalidshape-d/Impls_1.scala b/test/files/neg/macro-invalidshape-d/Impls_1.scala index 7b1620d117..7b1620d117 100644 --- a/test/disabled/neg/macro-invalidshape-d/Impls_1.scala +++ b/test/files/neg/macro-invalidshape-d/Impls_1.scala diff --git a/test/disabled/neg/macro-invalidshape-d/Macros_Test_2.scala b/test/files/neg/macro-invalidshape-d/Macros_Test_2.scala index bacd9a6e7c..bacd9a6e7c 100644 --- a/test/disabled/neg/macro-invalidshape-d/Macros_Test_2.scala +++ b/test/files/neg/macro-invalidshape-d/Macros_Test_2.scala diff --git a/test/files/neg/macro-without-xmacros-a.check b/test/files/neg/macro-without-xmacros-a.check new file mode 100644 index 0000000000..fd2667dbb8 --- /dev/null +++ b/test/files/neg/macro-without-xmacros-a.check @@ -0,0 +1,17 @@ +Macros_2.scala:5: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+This can be achieved by adding the import clause 'import language.experimental.macros'
+or by setting the compiler option -language:experimental.macros.
+See the Scala docs for value scala.language.experimental.macros for a discussion
+why the feature needs to be explicitly enabled.
+ def foo(x: Int): Int = macro foo_impl
+ ^
+Macros_2.scala:7: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def bar(x: Int): Int = macro bar_impl
+ ^
+Macros_2.scala:11: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def quux(x: Int): Int = macro quux_impl
+ ^
+three errors found
diff --git a/test/disabled/neg/macro-without-xmacros-a/Impls_1.scala b/test/files/neg/macro-without-xmacros-a/Impls_1.scala index 2493c81c95..01daf12b1a 100644 --- a/test/disabled/neg/macro-without-xmacros-a/Impls_1.scala +++ b/test/files/neg/macro-without-xmacros-a/Impls_1.scala @@ -1,17 +1,17 @@ import scala.reflect.makro.{Context => Ctx} object Impls { - def foo_impl(c: Ctx)(x: c.Expr[Int]): c.mirror.Tree = { + def foo_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = { import c.mirror._ Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1)))) } - def bar_impl(c: Ctx)(x: c.Expr[Int]): c.mirror.Tree = { + def bar_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = { import c.mirror._ Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2)))) } - def quux_impl(c: Ctx)(x: c.Expr[Int]): c.mirror.Tree = { + def quux_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = { import c.mirror._ Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3)))) } diff --git a/test/disabled/neg/macro-without-xmacros-a/Macros_2.scala b/test/files/neg/macro-without-xmacros-a/Macros_2.scala index 62f9dcf505..62f9dcf505 100644 --- a/test/disabled/neg/macro-without-xmacros-a/Macros_2.scala +++ b/test/files/neg/macro-without-xmacros-a/Macros_2.scala diff --git a/test/disabled/neg/macro-without-xmacros-a/Test_3.scala b/test/files/neg/macro-without-xmacros-a/Test_3.scala index e9a10e20c9..e9a10e20c9 100644 --- a/test/disabled/neg/macro-without-xmacros-a/Test_3.scala +++ b/test/files/neg/macro-without-xmacros-a/Test_3.scala diff --git a/test/files/neg/macro-without-xmacros-b.check b/test/files/neg/macro-without-xmacros-b.check new file mode 100644 index 0000000000..2d675b8319 --- /dev/null +++ b/test/files/neg/macro-without-xmacros-b.check @@ -0,0 +1,17 @@ +Macros_2.scala:3: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+This can be achieved by adding the import clause 'import language.experimental.macros'
+or by setting the compiler option -language:experimental.macros.
+See the Scala docs for value scala.language.experimental.macros for a discussion
+why the feature needs to be explicitly enabled.
+ def foo(x: Int): Int = macro Impls.foo_impl
+ ^
+Macros_2.scala:5: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def bar(x: Int): Int = macro Impls.bar_impl
+ ^
+Macros_2.scala:9: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def quux(x: Int): Int = macro Impls.quux_impl
+ ^
+three errors found
diff --git a/test/disabled/neg/macro-without-xmacros-b/Impls_1.scala b/test/files/neg/macro-without-xmacros-b/Impls_1.scala index 2493c81c95..01daf12b1a 100644 --- a/test/disabled/neg/macro-without-xmacros-b/Impls_1.scala +++ b/test/files/neg/macro-without-xmacros-b/Impls_1.scala @@ -1,17 +1,17 @@ import scala.reflect.makro.{Context => Ctx} object Impls { - def foo_impl(c: Ctx)(x: c.Expr[Int]): c.mirror.Tree = { + def foo_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = { import c.mirror._ Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1)))) } - def bar_impl(c: Ctx)(x: c.Expr[Int]): c.mirror.Tree = { + def bar_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = { import c.mirror._ Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2)))) } - def quux_impl(c: Ctx)(x: c.Expr[Int]): c.mirror.Tree = { + def quux_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = { import c.mirror._ Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3)))) } diff --git a/test/disabled/neg/macro-without-xmacros-b/Macros_2.scala b/test/files/neg/macro-without-xmacros-b/Macros_2.scala index de7080c7e8..de7080c7e8 100644 --- a/test/disabled/neg/macro-without-xmacros-b/Macros_2.scala +++ b/test/files/neg/macro-without-xmacros-b/Macros_2.scala diff --git a/test/disabled/neg/macro-without-xmacros-b/Test_3.scala b/test/files/neg/macro-without-xmacros-b/Test_3.scala index e9a10e20c9..e9a10e20c9 100644 --- a/test/disabled/neg/macro-without-xmacros-b/Test_3.scala +++ b/test/files/neg/macro-without-xmacros-b/Test_3.scala diff --git a/test/files/neg/pat_unreachable.flags b/test/files/neg/pat_unreachable.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/neg/pat_unreachable.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/neg/patmat-type-check.check b/test/files/neg/patmat-type-check.check index e045841ce1..ab4451f089 100644 --- a/test/files/neg/patmat-type-check.check +++ b/test/files/neg/patmat-type-check.check @@ -3,19 +3,31 @@ patmat-type-check.scala:22: error: scrutinee is incompatible with pattern type; required: String def f1 = "bob".reverse match { case Seq('b', 'o', 'b') => true } // fail ^ +patmat-type-check.scala:22: error: value _1 is not a member of object Seq + def f1 = "bob".reverse match { case Seq('b', 'o', 'b') => true } // fail + ^ patmat-type-check.scala:23: error: scrutinee is incompatible with pattern type; found : Seq[A] required: Array[Char] def f2 = "bob".toArray match { case Seq('b', 'o', 'b') => true } // fail ^ +patmat-type-check.scala:23: error: value _1 is not a member of object Seq + def f2 = "bob".toArray match { case Seq('b', 'o', 'b') => true } // fail + ^ patmat-type-check.scala:27: error: scrutinee is incompatible with pattern type; found : Seq[A] required: Test.Bop2 def f3(x: Bop2) = x match { case Seq('b', 'o', 'b') => true } // fail ^ +patmat-type-check.scala:27: error: value _1 is not a member of object Seq + def f3(x: Bop2) = x match { case Seq('b', 'o', 'b') => true } // fail + ^ patmat-type-check.scala:30: error: scrutinee is incompatible with pattern type; found : Seq[A] required: Test.Bop3[Char] def f4[T](x: Bop3[Char]) = x match { case Seq('b', 'o', 'b') => true } // fail ^ -four errors found +patmat-type-check.scala:30: error: value _1 is not a member of object Seq + def f4[T](x: Bop3[Char]) = x match { case Seq('b', 'o', 'b') => true } // fail + ^ +8 errors found diff --git a/test/files/neg/patmatexhaust.flags b/test/files/neg/patmatexhaust.flags index e8fb65d50c..b7eb21d5f5 100644 --- a/test/files/neg/patmatexhaust.flags +++ b/test/files/neg/patmatexhaust.flags @@ -1 +1 @@ --Xfatal-warnings
\ No newline at end of file +-Xfatal-warnings -Xoldpatmat diff --git a/test/files/neg/sealed-java-enums.flags b/test/files/neg/sealed-java-enums.flags index e709c65918..312f3a87ec 100644 --- a/test/files/neg/sealed-java-enums.flags +++ b/test/files/neg/sealed-java-enums.flags @@ -1 +1 @@ --Xexperimental -Xfatal-warnings +-Xexperimental -Xfatal-warnings -Xoldpatmat diff --git a/test/files/neg/switch.flags b/test/files/neg/switch.flags new file mode 100644 index 0000000000..809e9ff2f2 --- /dev/null +++ b/test/files/neg/switch.flags @@ -0,0 +1 @@ + -Xoldpatmat diff --git a/test/files/neg/t0418.check b/test/files/neg/t0418.check index 4e9ad2f9ae..50931a1bca 100644 --- a/test/files/neg/t0418.check +++ b/test/files/neg/t0418.check @@ -4,4 +4,7 @@ t0418.scala:2: error: not found: value Foo12340771 t0418.scala:2: error: not found: value x null match { case Foo12340771.Bar(x) => x } ^ -two errors found +t0418.scala:2: error: Could not typecheck extractor call: case class <none> with arguments List((x @ _)) + null match { case Foo12340771.Bar(x) => x } + ^ +three errors found diff --git a/test/files/neg/t112706A.check b/test/files/neg/t112706A.check index 30d0c3ec91..fb18b31be1 100644 --- a/test/files/neg/t112706A.check +++ b/test/files/neg/t112706A.check @@ -3,4 +3,7 @@ t112706A.scala:5: error: constructor cannot be instantiated to expected type; required: String case Tuple2(node,_) => ^ -one error found +t112706A.scala:5: error: Could not typecheck extractor call: case class Tuple2 with arguments List((node @ _), _) + case Tuple2(node,_) => + ^ +two errors found diff --git a/test/files/neg/t1878.check b/test/files/neg/t1878.check index 128741a022..b47367e12c 100644 --- a/test/files/neg/t1878.check +++ b/test/files/neg/t1878.check @@ -9,10 +9,13 @@ t1878.scala:3: error: scrutinee is incompatible with pattern type; t1878.scala:3: error: not found: value f val err1 = "" match { case Seq(f @ _*, ',') => f } ^ +t1878.scala:3: error: value _2 is not a member of object Seq + val err1 = "" match { case Seq(f @ _*, ',') => f } + ^ t1878.scala:9: error: _* may only come last val List(List(_*, arg2), _) = List(List(1,2,3), List(4,5,6)) ^ t1878.scala:13: error: _* may only come last case <p> { _* } </p> => ^ -5 errors found +6 errors found diff --git a/test/files/neg/t3098.flags b/test/files/neg/t3098.flags index e8fb65d50c..b7eb21d5f5 100644 --- a/test/files/neg/t3098.flags +++ b/test/files/neg/t3098.flags @@ -1 +1 @@ --Xfatal-warnings
\ No newline at end of file +-Xfatal-warnings -Xoldpatmat diff --git a/test/files/neg/t3392.check b/test/files/neg/t3392.check index 842d63eec9..3a39098c4e 100644 --- a/test/files/neg/t3392.check +++ b/test/files/neg/t3392.check @@ -1,4 +1,7 @@ t3392.scala:9: error: not found: value x case x@A(x/*<-- refers to the pattern that includes this comment*/.Ex(42)) => ^ -one error found +t3392.scala:9: error: Could not typecheck extractor call: case class <none> with arguments List(42) + case x@A(x/*<-- refers to the pattern that includes this comment*/.Ex(42)) => + ^ +two errors found diff --git a/test/files/neg/t3683a.flags b/test/files/neg/t3683a.flags index 85d8eb2ba2..b7eb21d5f5 100644 --- a/test/files/neg/t3683a.flags +++ b/test/files/neg/t3683a.flags @@ -1 +1 @@ --Xfatal-warnings +-Xfatal-warnings -Xoldpatmat diff --git a/test/files/neg/t3692.flags b/test/files/neg/t3692.flags new file mode 100644 index 0000000000..82becdfbfd --- /dev/null +++ b/test/files/neg/t3692.flags @@ -0,0 +1 @@ + -Xoldpatmat
\ No newline at end of file diff --git a/test/files/neg/t418.check b/test/files/neg/t418.check index 1489547823..c06088ba9d 100644 --- a/test/files/neg/t418.check +++ b/test/files/neg/t418.check @@ -4,4 +4,7 @@ t418.scala:2: error: not found: value Foo12340771 t418.scala:2: error: not found: value x null match { case Foo12340771.Bar(x) => x } ^ -two errors found +t418.scala:2: error: Could not typecheck extractor call: case class <none> with arguments List((x @ _)) + null match { case Foo12340771.Bar(x) => x } + ^ +three errors found diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check index 4ff4b1eec0..0f2fe6f2d1 100644 --- a/test/files/neg/t4425.check +++ b/test/files/neg/t4425.check @@ -1,4 +1,4 @@ -t4425.scala:3: error: erroneous or inaccessible type +t4425.scala:3: error: isInstanceOf cannot test if value types are references. 42 match { case _ X _ => () } ^ one error found diff --git a/test/files/neg/t5589neg.check b/test/files/neg/t5589neg.check index b3ff16d7e4..fb6858a397 100644 --- a/test/files/neg/t5589neg.check +++ b/test/files/neg/t5589neg.check @@ -22,6 +22,9 @@ t5589neg.scala:4: error: constructor cannot be instantiated to expected type; t5589neg.scala:4: error: not found: value y2 def f7(x: Either[Int, (String, Int)]) = for (y1 @ Tuple1(y2) <- x.right) yield ((y1, y2)) ^ +t5589neg.scala:4: error: Could not typecheck extractor call: case class Tuple1 with arguments List((y2 @ _)) + def f7(x: Either[Int, (String, Int)]) = for (y1 @ Tuple1(y2) <- x.right) yield ((y1, y2)) + ^ t5589neg.scala:5: error: constructor cannot be instantiated to expected type; found : (T1, T2, T3) required: (String, Int) @@ -34,4 +37,4 @@ t5589neg.scala:5: error: not found: value y2 def f8(x: Either[Int, (String, Int)]) = for ((y1, y2, y3) <- x.right) yield ((y1, y2)) ^ two warnings found -7 errors found +8 errors found diff --git a/test/files/neg/tailrec.check b/test/files/neg/tailrec.check index ad92731b2c..946d3421e6 100644 --- a/test/files/neg/tailrec.check +++ b/test/files/neg/tailrec.check @@ -4,9 +4,9 @@ tailrec.scala:45: error: could not optimize @tailrec annotated method facfail: i tailrec.scala:50: error: could not optimize @tailrec annotated method fail1: it is neither private nor final so can be overridden @tailrec def fail1(x: Int): Int = fail1(x) ^ -tailrec.scala:55: error: could not optimize @tailrec annotated method fail2: it contains a recursive call not in tail position - case x :: xs => x :: fail2[T](xs) - ^ +tailrec.scala:53: error: could not optimize @tailrec annotated method fail2: it contains a recursive call not in tail position + @tailrec final def fail2[T](xs: List[T]): List[T] = xs match { + ^ tailrec.scala:59: error: could not optimize @tailrec annotated method fail3: it is called recursively with different type arguments @tailrec final def fail3[T](x: Int): Int = fail3(x - 1) ^ diff --git a/test/files/neg/unreachablechar.flags b/test/files/neg/unreachablechar.flags new file mode 100644 index 0000000000..809e9ff2f2 --- /dev/null +++ b/test/files/neg/unreachablechar.flags @@ -0,0 +1 @@ + -Xoldpatmat diff --git a/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.flags b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.flags index e8fb65d50c..e8fb65d50c 100644 --- a/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.flags +++ b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.flags diff --git a/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.scala b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.scala index dee2f1de3b..69a7333011 100644 --- a/test/disabled/neg/macro-deprecate-dont-touch-backquotedidents.scala +++ b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.scala @@ -44,12 +44,12 @@ package foo { } } -object Test12 { - val Some(`macro`) = Some(42) - `macro` match { - case `macro` => println(`macro`) - } -} +//object Test12 { +// val Some(`macro`) = Some(42) +// `macro` match { +// case `macro` => println(`macro`) +// } +//} object Test13 { def `macro` = 2 diff --git a/test/files/pos/t1439.flags b/test/files/pos/t1439.flags index d86a0144e8..1e70f5c5c7 100644 --- a/test/files/pos/t1439.flags +++ b/test/files/pos/t1439.flags @@ -1 +1 @@ --unchecked -Xfatal-warnings -language:higherKinds
\ No newline at end of file +-unchecked -Xfatal-warnings -Xoldpatmat -language:higherKinds diff --git a/test/files/pos/virtpatmat_alts_subst.flags b/test/files/pos/virtpatmat_alts_subst.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_alts_subst.flags +++ b/test/files/pos/virtpatmat_alts_subst.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_anonfun_for.flags b/test/files/pos/virtpatmat_anonfun_for.flags index 23e3dc7d26..e69de29bb2 100644 --- a/test/files/pos/virtpatmat_anonfun_for.flags +++ b/test/files/pos/virtpatmat_anonfun_for.flags @@ -1 +0,0 @@ --Yvirtpatmat
\ No newline at end of file diff --git a/test/files/pos/virtpatmat_binding_opt.flags b/test/files/pos/virtpatmat_binding_opt.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_binding_opt.flags +++ b/test/files/pos/virtpatmat_binding_opt.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_castbinder.flags b/test/files/pos/virtpatmat_castbinder.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_castbinder.flags +++ b/test/files/pos/virtpatmat_castbinder.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_exist1.flags b/test/files/pos/virtpatmat_exist1.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_exist1.flags +++ b/test/files/pos/virtpatmat_exist1.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_exist2.flags b/test/files/pos/virtpatmat_exist2.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_exist2.flags +++ b/test/files/pos/virtpatmat_exist2.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_exist3.flags b/test/files/pos/virtpatmat_exist3.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_exist3.flags +++ b/test/files/pos/virtpatmat_exist3.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_exist_uncurry.scala b/test/files/pos/virtpatmat_exist_uncurry.scala new file mode 100644 index 0000000000..e017da6343 --- /dev/null +++ b/test/files/pos/virtpatmat_exist_uncurry.scala @@ -0,0 +1,6 @@ +object Test { + trait Leaf[T] { + def collect[U](f: PartialFunction[Leaf[_], U]): List[U] + def leaves: List[Leaf[T]] = collect { case l: Leaf[T] => l } + } +}
\ No newline at end of file diff --git a/test/files/pos/virtpatmat_gadt_array.flags b/test/files/pos/virtpatmat_gadt_array.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_gadt_array.flags +++ b/test/files/pos/virtpatmat_gadt_array.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_infer_single_1.flags b/test/files/pos/virtpatmat_infer_single_1.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_infer_single_1.flags +++ b/test/files/pos/virtpatmat_infer_single_1.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_instof_valuetype.flags b/test/files/pos/virtpatmat_instof_valuetype.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_instof_valuetype.flags +++ b/test/files/pos/virtpatmat_instof_valuetype.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/pos/virtpatmat_obj_in_case.flags b/test/files/pos/virtpatmat_obj_in_case.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/pos/virtpatmat_obj_in_case.flags +++ b/test/files/pos/virtpatmat_obj_in_case.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/presentation/callcc-interpreter/Runner.scala b/test/files/presentation/callcc-interpreter/Runner.scala index 1ef3cf9025..61b6efd50d 100644 --- a/test/files/presentation/callcc-interpreter/Runner.scala +++ b/test/files/presentation/callcc-interpreter/Runner.scala @@ -1,3 +1,5 @@ import scala.tools.nsc.interactive.tests._ -object Test extends InteractiveTest
\ No newline at end of file +object Test extends InteractiveTest { + settings.XoldPatmat.value = true // TODO: could this be running into some kind of race condition? sometimes the match has been translated, sometimes it hasn't +}
\ No newline at end of file diff --git a/test/files/presentation/random.check b/test/files/presentation/random.check index fce4b69fb3..1b73720312 100644 --- a/test/files/presentation/random.check +++ b/test/files/presentation/random.check @@ -4,7 +4,8 @@ askType at Random.scala(18,14) ================================================================================ [response] askTypeAt at (18,14) val filter: Int => Boolean = try { - java.this.lang.Integer.parseInt(args.apply(0)) match { + case <synthetic> val x1: Int = java.this.lang.Integer.parseInt(args.apply(0)); + x1 match { case 1 => ((x: Int) => x.%(2).!=(0)) case 2 => ((x: Int) => x.%(2).==(0)) case _ => ((x: Int) => x.!=(0)) diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check index 7a8a744bfa..708fcc6985 100644 --- a/test/files/run/inline-ex-handlers.check +++ b/test/files/run/inline-ex-handlers.check @@ -1,40 +1,44 @@ 172c172 -< locals: value x$1, value temp1 +< locals: value x$1, value x1 --- -> locals: value x$1, value temp1, variable boxed1 +> locals: value x$1, value x1, variable boxed1 174c174 < blocks: [1,2,3,4] --- -> blocks: [1,2,3] -187,189d186 -< 92 JUMP 4 -< -< 4: -195a193,194 +> blocks: [1,3,4] +186a187,188 > 92 STORE_LOCAL(variable boxed1) > 92 LOAD_LOCAL(variable boxed1) -386c385 -< blocks: [1,2,3,4,5,7,8,10] +195,197d196 +< 92 JUMP 2 +< +< 2: +385c384 +< blocks: [1,2,3,4,5,8,11,13,14,16] --- -> blocks: [1,2,3,4,5,7,8,10,11] -410c409,418 +> blocks: [1,2,3,5,8,11,13,14,16,17] +409c408,417 < 103 THROW(MyException) --- -> ? STORE_LOCAL(value ex$1) -> ? JUMP 11 +> ? STORE_LOCAL(value ex5) +> ? JUMP 17 > -> 11: -> 101 LOAD_LOCAL(value ex$1) -> 101 STORE_LOCAL(value temp2) -> 101 SCOPE_ENTER value temp2 -> 101 LOAD_LOCAL(value temp2) -> 101 IS_INSTANCE REF(class MyException) -> 101 CZJUMP (BOOL)NE ? 4 : 5 -501c509 +> 17: +> 101 LOAD_LOCAL(value ex5) +> 101 STORE_LOCAL(value x3) +> 101 SCOPE_ENTER value x3 +> 106 LOAD_LOCAL(value x3) +> 106 IS_INSTANCE REF(class MyException) +> 106 CZJUMP (BOOL)NE ? 5 : 11 +422,424d429 +< 101 JUMP 4 +< +< 4: +512c517 < blocks: [1,2,3,4,6,7,8,9,10] --- > blocks: [1,2,3,4,6,7,8,9,10,11,12,13] -530c538,543 +541c546,551 < 306 THROW(MyException) --- > ? JUMP 11 @@ -43,7 +47,7 @@ > ? LOAD_LOCAL(variable monitor4) > 305 MONITOR_EXIT > ? JUMP 12 -536c549,555 +547c557,563 < ? THROW(Throwable) --- > ? JUMP 12 @@ -53,7 +57,7 @@ > 304 MONITOR_EXIT > ? STORE_LOCAL(value t) > ? JUMP 13 -542c561,574 +553c569,582 < ? THROW(Throwable) --- > ? STORE_LOCAL(value t) @@ -70,19 +74,19 @@ > 310 CALL_PRIMITIVE(EndConcat) > 310 CALL_METHOD scala.Predef.println (dynamic) > 310 JUMP 2 -566c598 +577c606 < catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6 --- > catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6 -569c601 +580c609 < catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3 --- > catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3 -601c633 +612c641 < blocks: [1,2,3,4,5,6,7,9,10] --- > blocks: [1,2,3,4,5,6,7,9,10,11,12] -625c657,663 +636c665,671 < 78 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -92,7 +96,7 @@ > 81 LOAD_LOCAL(value e) > ? STORE_LOCAL(variable exc1) > ? JUMP 12 -654c692,706 +665c700,714 < 81 THROW(Exception) --- > ? STORE_LOCAL(variable exc1) @@ -110,57 +114,53 @@ > 84 STORE_LOCAL(variable result) > 84 LOAD_LOCAL(variable exc1) > 84 THROW(Throwable) -676c728 +687c736 < catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3 --- > catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3 -702c754 -< blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,18,19] +713c762 +< blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31] --- -> blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,18,19,20,21,22] -726c778,787 +> blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31,32,33,34] +737c786,793 < 172 THROW(MyException) --- -> ? STORE_LOCAL(value ex$4) -> ? JUMP 20 +> ? STORE_LOCAL(value ex5) +> ? JUMP 32 > -> 20: -> 170 LOAD_LOCAL(value ex$4) -> 170 STORE_LOCAL(value temp11) -> 170 SCOPE_ENTER value temp11 -> 170 LOAD_LOCAL(value temp11) -> 170 IS_INSTANCE REF(class MyException) -> 170 CZJUMP (BOOL)NE ? 12 : 13 -780c841,842 +> 32: +> 170 LOAD_LOCAL(value ex5) +> 170 STORE_LOCAL(value x3) +> 170 SCOPE_ENTER value x3 +> 170 JUMP 18 +793c849,850 < 177 THROW(MyException) --- -> ? STORE_LOCAL(value ex$5) -> ? JUMP 21 -784c846,855 +> ? STORE_LOCAL(value ex5) +> ? JUMP 33 +797c854,861 < 170 THROW(Throwable) --- -> ? STORE_LOCAL(value ex$5) -> ? JUMP 21 +> ? STORE_LOCAL(value ex5) +> ? JUMP 33 > -> 21: -> 169 LOAD_LOCAL(value ex$5) -> 169 STORE_LOCAL(value temp14) -> 169 SCOPE_ENTER value temp14 -> 169 LOAD_LOCAL(value temp14) -> 169 IS_INSTANCE REF(class MyException) -> 169 CZJUMP (BOOL)NE ? 5 : 6 -815c886,887 +> 33: +> 169 LOAD_LOCAL(value ex5) +> 169 STORE_LOCAL(value x3) +> 169 SCOPE_ENTER value x3 +> 169 JUMP 5 +830c894,895 < 182 THROW(MyException) --- > ? STORE_LOCAL(variable exc2) -> ? JUMP 22 -819c891,905 +> ? JUMP 34 +834c899,900 < 169 THROW(Throwable) --- > ? STORE_LOCAL(variable exc2) -> ? JUMP 22 -> -> 22: +> ? JUMP 34 +835a902,914 +> 34: > 184 LOAD_MODULE object Predef > 184 CONSTANT("finally") > 184 CALL_METHOD scala.Predef.println (dynamic) @@ -172,57 +172,60 @@ > 185 STORE_LOCAL(variable result) > 185 LOAD_LOCAL(variable exc2) > 185 THROW(Throwable) -841c927 -< catch (Throwable) in ArrayBuffer(11, 12, 13, 14, 15, 16, 18) starting at: 4 +> +856c935 +< catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30) starting at: 4 --- -> catch (Throwable) in ArrayBuffer(11, 12, 13, 14, 15, 16, 18, 20) starting at: 4 -844c930 -< catch (<none>) in ArrayBuffer(4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 18) starting at: 3 +> catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30, 32) starting at: 4 +859c938 +< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30) starting at: 3 --- -> catch (<none>) in ArrayBuffer(4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 18, 20, 21) starting at: 3 -870c956 -< blocks: [1,2,3,6,7,8,10,11,13] +> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3 +885c964 +< blocks: [1,2,3,6,7,8,11,14,16,17,19] --- -> blocks: [1,2,3,6,7,8,10,11,13,14] -894c980,989 +> blocks: [1,2,3,6,7,8,11,14,16,17,19,20] +909c988,995 < 124 THROW(MyException) --- -> ? STORE_LOCAL(value ex$2) -> ? JUMP 14 +> ? STORE_LOCAL(value ex5) +> ? JUMP 20 > -> 14: -> 122 LOAD_LOCAL(value ex$2) -> 122 STORE_LOCAL(value temp5) -> 122 SCOPE_ENTER value temp5 -> 122 LOAD_LOCAL(value temp5) -> 122 IS_INSTANCE REF(class MyException) -> 122 CZJUMP (BOOL)NE ? 7 : 8 -942c1037 -< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 10, 11, 13) starting at: 3 ---- -> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 10, 11, 13, 14) starting at: 3 -968c1063 -< blocks: [1,2,3,4,5,9,10,11,13] ---- -> blocks: [1,2,3,4,5,9,10,11,13,14] -992c1087,1096 +> 20: +> 122 LOAD_LOCAL(value ex5) +> 122 STORE_LOCAL(value x3) +> 122 SCOPE_ENTER value x3 +> 122 JUMP 7 +969c1055 +< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3 +--- +> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19, 20) starting at: 3 +995c1081 +< blocks: [1,2,3,4,5,8,11,15,16,17,19] +--- +> blocks: [1,2,3,5,8,11,15,16,17,19,20] +1019c1105,1114 < 148 THROW(MyException) --- -> ? STORE_LOCAL(value ex$3) -> ? JUMP 14 +> ? STORE_LOCAL(value ex5) +> ? JUMP 20 > -> 14: -> 145 LOAD_LOCAL(value ex$3) -> 145 STORE_LOCAL(value temp8) -> 145 SCOPE_ENTER value temp8 -> 145 LOAD_LOCAL(value temp8) -> 145 IS_INSTANCE REF(class MyException) -> 145 CZJUMP (BOOL)NE ? 4 : 5 -1236c1340 +> 20: +> 145 LOAD_LOCAL(value ex5) +> 145 STORE_LOCAL(value x3) +> 145 SCOPE_ENTER value x3 +> 154 LOAD_LOCAL(value x3) +> 154 IS_INSTANCE REF(class MyException) +> 154 CZJUMP (BOOL)NE ? 5 : 11 +1040,1042d1134 +< 145 JUMP 4 +< +< 4: +1275c1367 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1260c1364,1371 +1299c1391,1398 < 38 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -233,33 +236,37 @@ > 42 CONSTANT("IllegalArgumentException") > 42 CALL_METHOD scala.Predef.println (dynamic) > 42 JUMP 2 -1309c1420 -< blocks: [1,2,3,4,5,7,8,10,11,13] +1348c1447 +< blocks: [1,2,3,4,5,8,11,13,14,16,17,19] --- -> blocks: [1,2,3,4,5,7,8,10,11,13,14] -1333c1444,1445 +> blocks: [1,2,3,5,8,11,13,14,16,17,19,20] +1372c1471,1472 < 203 THROW(MyException) --- -> ? STORE_LOCAL(value ex$6) -> ? JUMP 14 -1353c1465,1474 +> ? STORE_LOCAL(value ex5) +> ? JUMP 20 +1392c1492,1501 < 209 THROW(MyException) --- -> ? STORE_LOCAL(value ex$6) -> ? JUMP 14 +> ? STORE_LOCAL(value ex5) +> ? JUMP 20 > -> 14: -> 200 LOAD_LOCAL(value ex$6) -> 200 STORE_LOCAL(value temp17) -> 200 SCOPE_ENTER value temp17 -> 200 LOAD_LOCAL(value temp17) -> 200 IS_INSTANCE REF(class MyException) -> 200 CZJUMP (BOOL)NE ? 4 : 5 -1416c1537 +> 20: +> 200 LOAD_LOCAL(value ex5) +> 200 STORE_LOCAL(value x3) +> 200 SCOPE_ENTER value x3 +> 212 LOAD_LOCAL(value x3) +> 212 IS_INSTANCE REF(class MyException) +> 212 CZJUMP (BOOL)NE ? 5 : 11 +1405,1407d1513 +< 200 JUMP 4 +< +< 4: +1467c1573 < blocks: [1,2,3,4,5,7] --- > blocks: [1,2,3,4,5,7,8] -1440c1561,1568 +1491c1597,1604 < 58 THROW(IllegalArgumentException) --- > ? STORE_LOCAL(value e) @@ -270,11 +277,11 @@ > 62 CONSTANT("RuntimeException") > 62 CALL_METHOD scala.Predef.println (dynamic) > 62 JUMP 2 -1489c1617 +1540c1653 < blocks: [1,2,3,4] --- > blocks: [1,2,3,4,5] -1509c1637,1642 +1560c1673,1678 < 229 THROW(MyException) --- > ? JUMP 5 @@ -283,19 +290,19 @@ > ? LOAD_LOCAL(variable monitor1) > 228 MONITOR_EXIT > 228 THROW(Throwable) -1515c1648 +1566c1684 < ? THROW(Throwable) --- > 228 THROW(Throwable) -1543c1676 +1594c1712 < locals: value args, variable result, variable monitor2, variable monitorResult1 --- > locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1 -1545c1678 +1596c1714 < blocks: [1,2,3,4] --- > blocks: [1,2,3,4,5] -1568c1701,1709 +1619c1737,1745 < 245 THROW(MyException) --- > ? STORE_LOCAL(value exception$1) @@ -307,7 +314,7 @@ > ? LOAD_LOCAL(variable monitor2) > 244 MONITOR_EXIT > 244 THROW(Throwable) -1574c1715 +1625c1751 < ? THROW(Throwable) --- > 244 THROW(Throwable) diff --git a/test/files/run/macro-reflective-mamd-normal-mi.check b/test/files/run/macro-reflective-mamd-normal-mi.check new file mode 100644 index 0000000000..ac4213d6e9 --- /dev/null +++ b/test/files/run/macro-reflective-mamd-normal-mi.check @@ -0,0 +1 @@ +43
\ No newline at end of file diff --git a/test/disabled/run/macro-reflective-mamd-normal-mi/Impls_1.scala b/test/files/run/macro-reflective-mamd-normal-mi/Impls_1.scala index dc7d42d23e..dc7d42d23e 100644 --- a/test/disabled/run/macro-reflective-mamd-normal-mi/Impls_1.scala +++ b/test/files/run/macro-reflective-mamd-normal-mi/Impls_1.scala diff --git a/test/disabled/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala index 7cbe425fc8..cf34f1685d 100644 --- a/test/disabled/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala +++ b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala @@ -12,5 +12,6 @@ object Test extends App { val module = ModuleDef(NoMods, newTermName("Macros"), Template(Nil, emptyValDef, List(modulector, macrodef))) val macroapp = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))) val tree = Block(macrodef, module, macroapp) - println(tree.eval) + val toolbox = mkToolBox(options = "-language:experimental.macros") + println(toolbox.runExpr(tree)) } diff --git a/test/files/run/patmat_unapp_abstype.check b/test/files/run/patmat_unapp_abstype.check index ac28ccdb95..72239d16cd 100644 --- a/test/files/run/patmat_unapp_abstype.check +++ b/test/files/run/patmat_unapp_abstype.check @@ -1,2 +1,4 @@ TypeRef none of the above +Bar +Foo diff --git a/test/files/run/patmat_unapp_abstype.flags b/test/files/run/patmat_unapp_abstype.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/run/patmat_unapp_abstype.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/run/patmat_unapp_abstype.scala b/test/files/run/patmat_unapp_abstype.scala index e5adec5c16..45496f08a2 100644 --- a/test/files/run/patmat_unapp_abstype.scala +++ b/test/files/run/patmat_unapp_abstype.scala @@ -19,6 +19,11 @@ trait TypesUser extends TypesAPI { def shouldNotCrash(tp: Type): Unit = { tp match { case TypeRef(x) => println("TypeRef") + // the above checks tp.isInstanceOf[TypeRef], which is erased to tp.isInstanceOf[Type] + // before calling TypeRef.unapply(tp), which will then crash unless tp.isInstanceOf[TypesImpl#TypeRef] (which is not implied by tp.isInstanceOf[Type]) + // tp.isInstanceOf[TypesImpl#TypeRef] is equivalent to classOf[TypesImpl#TypeRef].isAssignableFrom(tp.getClass) + // this is equivalent to manifest + // it is NOT equivalent to manifest[Type] <:< typeRefMani case MethodType(x) => println("MethodType") case _ => println("none of the above") } @@ -32,8 +37,47 @@ trait TypesImpl extends TypesAPI { //lazy val typeRefMani = manifest[TypeRef] } -object Test extends TypesImpl with TypesUser with App { - shouldNotCrash(TypeRef(10)) // should and does print "TypeRef" - // once #1697/#2337 are fixed, this should generate the correct output - shouldNotCrash(MethodType(10)) // should print "MethodType" but prints "none of the above" -- good one, pattern matcher! -}
\ No newline at end of file +trait Foos { + trait Bar + type Foo <: Bar + trait FooExtractor { + def unapply(foo: Foo): Option[Int] + } + val Foo: FooExtractor +} + +trait RealFoos extends Foos { + class Foo(val x: Int) extends Bar + object Foo extends FooExtractor { + def unapply(foo: Foo): Option[Int] = Some(foo.x) + } +} + +trait Intermed extends Foos { + def crash(bar: Bar): Unit = + bar match { + case Foo(x) => println("Foo") + case _ => println("Bar") + } +} + +object TestUnappStaticallyKnownSynthetic extends TypesImpl with TypesUser { + def test() = { + shouldNotCrash(TypeRef(10)) // should and does print "TypeRef" + // once #1697/#2337 are fixed, this should generate the correct output + shouldNotCrash(MethodType(10)) // should print "MethodType" but prints "none of the above" -- good one, pattern matcher! + } +} + +object TestUnappDynamicSynth extends RealFoos with Intermed { + case class FooToo(n: Int) extends Bar + def test() = { + crash(FooToo(10)) + crash(new Foo(5)) + } +} + +object Test extends App { + TestUnappStaticallyKnownSynthetic.test() + TestUnappDynamicSynth.test() +} diff --git a/test/files/run/reify_fors.flags b/test/files/run/reify_fors.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/run/reify_fors.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/run/reify_maps.flags b/test/files/run/reify_maps.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/run/reify_maps.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/run/repl-suppressed-warnings.scala b/test/files/run/repl-suppressed-warnings.scala index a78b00f36e..9afbbaf1a5 100644 --- a/test/files/run/repl-suppressed-warnings.scala +++ b/test/files/run/repl-suppressed-warnings.scala @@ -1,6 +1,7 @@ import scala.tools.partest.ReplTest object Test extends ReplTest { + override def extraSettings = "-Xoldpatmat" def code = """ // "Is this thing on?" Not working on first couple diff --git a/test/files/run/t2886.check b/test/files/run/t2886.check index 5fe1e73a45..8d97a82799 100644 --- a/test/files/run/t2886.check +++ b/test/files/run/t2886.check @@ -1,5 +1,5 @@ -((x: scala.Predef.String) => { - val x$1 = x; - val x$2 = x; - Test.test(x$2, x$1) -}) +((x: String) => {
+ val x$1 = x;
+ val x$2 = x;
+ Test.this.test(x$2, x$1)
+})
diff --git a/test/files/run/t2886.scala b/test/files/run/t2886.scala new file mode 100644 index 0000000000..e0835a0a44 --- /dev/null +++ b/test/files/run/t2886.scala @@ -0,0 +1,9 @@ +import scala.reflect.mirror._ + +object Test { + def test(name: String, address: String) = null + def main(args: Array[String]) = { + val tree = reify((x:String) => test(address=x,name=x)).tree + println(tree) + } +} diff --git a/test/files/run/t5273_1.flags b/test/files/run/t5273_1.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/run/t5273_1.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/run/t5273_2a.flags b/test/files/run/t5273_2a.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/run/t5273_2a.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/run/t5273_2b.flags b/test/files/run/t5273_2b.flags new file mode 100644 index 0000000000..ba80cad69b --- /dev/null +++ b/test/files/run/t5273_2b.flags @@ -0,0 +1 @@ +-Xoldpatmat diff --git a/test/files/run/virtpatmat_alts.flags b/test/files/run/virtpatmat_alts.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_alts.flags +++ b/test/files/run/virtpatmat_alts.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_apply.flags b/test/files/run/virtpatmat_apply.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_apply.flags +++ b/test/files/run/virtpatmat_apply.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_casting.flags b/test/files/run/virtpatmat_casting.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_casting.flags +++ b/test/files/run/virtpatmat_casting.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_extends_product.flags b/test/files/run/virtpatmat_extends_product.flags index ac6b805bd0..8b13789179 100644 --- a/test/files/run/virtpatmat_extends_product.flags +++ b/test/files/run/virtpatmat_extends_product.flags @@ -1 +1 @@ --Yvirtpatmat + diff --git a/test/files/run/virtpatmat_literal.flags b/test/files/run/virtpatmat_literal.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_literal.flags +++ b/test/files/run/virtpatmat_literal.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_nested_lists.flags b/test/files/run/virtpatmat_nested_lists.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_nested_lists.flags +++ b/test/files/run/virtpatmat_nested_lists.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_npe.flags b/test/files/run/virtpatmat_npe.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_npe.flags +++ b/test/files/run/virtpatmat_npe.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_opt_sharing.flags b/test/files/run/virtpatmat_opt_sharing.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_opt_sharing.flags +++ b/test/files/run/virtpatmat_opt_sharing.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_partial.flags b/test/files/run/virtpatmat_partial.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_partial.flags +++ b/test/files/run/virtpatmat_partial.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_staging.flags b/test/files/run/virtpatmat_staging.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_staging.flags +++ b/test/files/run/virtpatmat_staging.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_stringinterp.check b/test/files/run/virtpatmat_stringinterp.check new file mode 100644 index 0000000000..7927f4f2d9 --- /dev/null +++ b/test/files/run/virtpatmat_stringinterp.check @@ -0,0 +1 @@ +Node(1) diff --git a/test/files/run/virtpatmat_stringinterp.flags b/test/files/run/virtpatmat_stringinterp.flags new file mode 100644 index 0000000000..e1b37447c9 --- /dev/null +++ b/test/files/run/virtpatmat_stringinterp.flags @@ -0,0 +1 @@ +-Xexperimental
\ No newline at end of file diff --git a/test/files/run/virtpatmat_stringinterp.scala b/test/files/run/virtpatmat_stringinterp.scala new file mode 100644 index 0000000000..213712f17a --- /dev/null +++ b/test/files/run/virtpatmat_stringinterp.scala @@ -0,0 +1,13 @@ +object Test extends App { + case class Node(x: Int) + + implicit def sc2xml(sc: StringContext): XMLContext = new XMLContext(sc) + class XMLContext(sc: StringContext) { + object xml { + def unapplySeq(xml: Node): Option[Seq[Node]] = Some(List(Node(1))) + } + } + + val x: Node = Node(0) + x match { case xml"""<foo arg=$a/>""" => println(a) } +}
\ No newline at end of file diff --git a/test/files/run/virtpatmat_switch.flags b/test/files/run/virtpatmat_switch.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_switch.flags +++ b/test/files/run/virtpatmat_switch.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_tailcalls_verifyerror.flags b/test/files/run/virtpatmat_tailcalls_verifyerror.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_tailcalls_verifyerror.flags +++ b/test/files/run/virtpatmat_tailcalls_verifyerror.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_try.flags b/test/files/run/virtpatmat_try.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_try.flags +++ b/test/files/run/virtpatmat_try.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_typed.flags b/test/files/run/virtpatmat_typed.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_typed.flags +++ b/test/files/run/virtpatmat_typed.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_unapply.flags b/test/files/run/virtpatmat_unapply.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_unapply.flags +++ b/test/files/run/virtpatmat_unapply.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_unapplyprod.flags b/test/files/run/virtpatmat_unapplyprod.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_unapplyprod.flags +++ b/test/files/run/virtpatmat_unapplyprod.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/run/virtpatmat_unapplyseq.flags b/test/files/run/virtpatmat_unapplyseq.flags index 9769db9257..3f5a3100e4 100644 --- a/test/files/run/virtpatmat_unapplyseq.flags +++ b/test/files/run/virtpatmat_unapplyseq.flags @@ -1 +1 @@ - -Yvirtpatmat -Xexperimental + -Xexperimental diff --git a/test/files/specialized/spec-patmatch.check b/test/files/specialized/spec-patmatch.check index 33306ab5d9..a2746c0f48 100644 --- a/test/files/specialized/spec-patmatch.check +++ b/test/files/specialized/spec-patmatch.check @@ -17,4 +17,4 @@ long double float default -2
\ No newline at end of file +10 |