summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-04-16 04:28:17 +0100
committerPaul Phillips <paulp@improving.org>2012-04-16 04:28:17 +0100
commit686adb12981b81290145b5fbf7462a710eb83ad3 (patch)
treea7eca218df9c3d8851c2ad80a272fdfeb4565406
parent121c72403633debf2f18984d4c81793446177a65 (diff)
parent23ae258c37bd5de050ae9d8b4287dc8c309af8de (diff)
downloadscala-686adb12981b81290145b5fbf7462a710eb83ad3.tar.gz
scala-686adb12981b81290145b5fbf7462a710eb83ad3.tar.bz2
scala-686adb12981b81290145b5fbf7462a710eb83ad3.zip
Merge commit 'refs/pull/408/head'
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala7
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala3
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala18
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala73
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala3
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala6
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala49
-rw-r--r--test/files/neg/t4515.check4
-rw-r--r--test/files/pos/annotDepMethType.flags1
-rw-r--r--test/files/run/inline-ex-handlers.check109
-rw-r--r--test/files/run/t5272_1.flags1
-rw-r--r--test/files/run/t5272_2.flags1
16 files changed, 168 insertions, 125 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 66b505c0d1..3150b674af 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -400,6 +400,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.tpe)
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe))
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe))
+
+ lazy val MarkerCPSTypes = getClassIfDefined("scala.util.continuations.cpsParam")
def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass
def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass
@@ -655,6 +657,11 @@ trait Definitions extends reflect.api.StandardDefinitions {
false
}
+ def isPartialFunctionType(tp: Type): Boolean = {
+ val sym = tp.typeSymbol
+ (sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass)
+ }
+
def isSeqType(tp: Type) = elementType(SeqClass, tp.normalize) != NoType
def elementType(container: Symbol, tp: Type): Type = tp match {
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index ce6a7ed6af..767df0791e 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -93,6 +93,9 @@ trait CompilationUnits { self: Global =>
def uncheckedWarning(pos: Position, msg: String) =
currentRun.uncheckedWarnings.warn(pos, msg)
+ def inlinerWarning(pos: Position, msg: String) =
+ currentRun.inlinerWarnings.warn(pos, msg)
+
def incompleteInputError(pos: Position, msg:String) =
reporter.incompleteInputError(pos, msg)
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 9169f80e1c..bbeee3220b 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -969,7 +969,8 @@ class Global(var currentSettings: Settings, var reporter: NscReporter) extends S
val deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation)
val uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked)
val featureWarnings = new ConditionalWarning("feature", settings.feature)
- val allConditionalWarnings = List(deprecationWarnings, uncheckedWarnings, featureWarnings)
+ val inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings)
+ val allConditionalWarnings = List(deprecationWarnings, uncheckedWarnings, featureWarnings, inlinerWarnings)
var reportedFeature = Set[Symbol]()
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index cf51a5b926..05d8c632c0 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -135,7 +135,7 @@ abstract class Inliners extends SubComponent {
/** The current iclass */
private var currentIClazz: IClass = _
- private def warn(pos: Position, msg: String) = currentIClazz.cunit.warning(pos, msg)
+ private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg)
val recentTFAs = mutable.Map.empty[Symbol, Tuple2[Boolean, analysis.MethodTFA]]
private def getRecentTFA(incm: IMethod): (Boolean, analysis.MethodTFA) = {
@@ -759,12 +759,16 @@ abstract class Inliners extends SubComponent {
private def helperIsSafeToInline(stackLength: Int): Boolean = {
def makePublic(f: Symbol): Boolean =
- (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && {
- debuglog("Making not-private symbol out of synthetic: " + f)
-
- f setNotFlag Flags.PRIVATE
- true
- }
+ /*
+ * Completely disabling member publifying. This shouldn't have been done in the first place. :|
+ */
+ false
+ // (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && {
+ // debuglog("Making not-private symbol out of synthetic: " + f)
+
+ // f setNotFlag Flags.PRIVATE
+ // true
+ // }
if (!inc.m.hasCode || inc.isRecursive) { return false }
if (inc.m.symbol.hasFlag(Flags.SYNCHRONIZED)) { return false }
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index d4c2ffa832..6a5c4c92bc 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -138,6 +138,7 @@ trait ScalaSettings extends AbsScalaSettings
val termConflict = ChoiceSetting ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
val inline = BooleanSetting ("-Yinline", "Perform inlining when possible.")
val inlineHandlers = BooleanSetting ("-Yinline-handlers", "Perform exception handler inlining when possible.")
+ val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
val Xlinearizer = ChoiceSetting ("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
val log = PhasesSetting ("-Ylog", "Log operations during")
val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.")
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 57cd51ad35..6b894a724f 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -446,8 +446,10 @@ abstract class UnCurry extends InfoTransform
}
val members =
- if (isPartial) List(applyOrElseMethodDef, isDefinedAtMethodDef)
- else List(applyMethodDef)
+ if (isPartial) {
+ assert(!opt.virtPatmat, "PartialFunction should have been synthesized during typer "+ fun);
+ List(applyOrElseMethodDef, isDefinedAtMethodDef)
+ } else List(applyMethodDef)
// println("MEMBERS "+ members)
val res = localTyper.typedPos(fun.pos) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
index 1fd9f6fc13..88cea2231f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
@@ -135,7 +135,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
// 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.uncurryPhase.id, phase)
+ if(phase.id >= currentRun.uncurryPhase.id) debugwarn("running translateMatch at "+ phase +" on "+ scrut +" match "+ cases)
val scrutSym = freshSym(scrut.pos, pureType(scrutType)) setFlag SYNTH_CASE
// pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental
@@ -1107,7 +1107,9 @@ class Foo(x: Other) { x._1 } // no error in this order
// 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)
+ 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 = 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)
@@ -1568,7 +1570,7 @@ class Foo(x: Other) { x._1 } // no error in this order
// TODO: if patterns allow switch but the type of the scrutinee doesn't, cast (type-test) the scrutinee to the corresponding switchable type and switch on the result
if (regularSwitchMaker.switchableTpe(scrutSym.tpe)) {
val caseDefsWithDefault = regularSwitchMaker(cases map {c => (scrutSym, c)}, pt)
- if (caseDefsWithDefault isEmpty) None
+ if (caseDefsWithDefault.length <= 2) None // not worth emitting a switch... also, the optimizer has trouble digesting tiny switches, apparently, so let's be nice and not generate them
else {
// match on scrutSym -- converted to an int if necessary -- not on scrut directly (to avoid duplicating scrut)
val scrutToInt: Tree =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 043e826d32..8f5b3fb519 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2212,6 +2212,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def adaptCase(cdef: CaseDef, mode: Int, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe))
+ // takes untyped sub-trees of a match and type checks them
def typedMatch(selector0: Tree, cases: List[CaseDef], mode: Int, resTp: Type) = {
val (selector, doTranslation) = selector0 match {
case Annotated(Ident(nme.synthSwitch), selector) => (selector, false)
@@ -2229,6 +2230,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(selector1, selectorTp, casesAdapted, ownType, doTranslation)
}
+ // match has been typed, now translate it
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)
@@ -2290,11 +2292,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// need to duplicate the cases before typing them to generate the apply method, or the symbols will be all messed up
val casesTrue = if (isPartial) cases map (c => deriveCaseDef(c)(x => TRUE_typed).duplicate) else Nil
+ def parentsPartial(targs: List[Type]) = List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
def applyMethod = {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass)
- val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL)
+ val methodSym = anonClass.newMethod(nme.apply, tree.pos, if(isPartial) (FINAL | OVERRIDE) else FINAL)
val (paramSyms, selector) = mkParams(methodSym)
if (selector eq EmptyTree) EmptyTree
@@ -2307,7 +2310,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
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)
+ val parents =
+ if (isPartial) parentsPartial(List(methFormals.head, resTp))
+ else List(abstractFunctionType(methFormals, resTp), SerializableClass.tpe)
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
methodSym setInfoAndEnter MethodType(paramSyms, resTp)
@@ -2320,9 +2325,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def applyOrElseMethodDef = {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
// targs were type arguments for PartialFunction, so we know they will work for AbstractPartialFunction as well
- def parents(targs: List[Type]) = List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
-
- anonClass setInfo ClassInfoType(parents(targs), newScope, anonClass)
+ anonClass setInfo ClassInfoType(parentsPartial(targs), newScope, anonClass)
val methodSym = anonClass.newMethod(nme.applyOrElse, tree.pos, FINAL | OVERRIDE)
// create the parameter that corresponds to the function's parameter
@@ -2344,7 +2347,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.typedMatch(selector, cases, mode, ptRes)
- anonClass setInfo ClassInfoType(parents(List(argTp, resTp)), newScope, anonClass)
+ anonClass setInfo ClassInfoType(parentsPartial(List(argTp, resTp)), newScope, anonClass)
B1 setInfo TypeBounds.lower(resTp)
anonClass.info.decls enter methodSym // methodSym's info need not change (B1's bound has been updated instead)
@@ -2373,7 +2376,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- val members = if (!isPartial) List(applyMethod) else List(applyOrElseMethodDef, isDefinedAtMethod)
+ val members = if (isPartial) {
+ if ((MarkerCPSTypes ne NoSymbol) && (targs exists (_ hasAnnotation MarkerCPSTypes))) List(applyMethod, isDefinedAtMethod)
+ else List(applyOrElseMethodDef, isDefinedAtMethod)
+ } else List(applyMethod)
+
if (members.head eq EmptyTree) setError(tree)
else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt)
}
@@ -2428,21 +2435,31 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- val vparamSyms = fun.vparams map { vparam =>
- enterSym(context, vparam)
- if (context.retyping) context.scope enter vparam.symbol
- vparam.symbol
+ fun.body match {
+ // later phase indicates scaladoc is calling (where shit is messed up, I tell you)
+ // -- so fall back to old patmat, which is more forgiving
+ case Match(sel, cases) if opt.virtPatmat && (phase.id < currentRun.uncurryPhase.id) =>
+ // 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 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)
}
}
@@ -3814,9 +3831,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- // translation only happens when (selector != EmptyTree) && !isPastTyper && opt.virtPatmat
def typedTranslatedMatch(tree: Tree, selector: Tree, cases: List[CaseDef]): Tree = {
- if (selector == EmptyTree) {
+ if (opt.virtPatmat && (phase.id < currentRun.uncurryPhase.id)) {
+ if (selector ne EmptyTree) {
+ val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = typedMatch(selector, cases, mode, pt)
+ typed(translatedMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt)
+ } else typedMatchAnonFun(tree, cases, mode, pt)
+ } else if (selector == EmptyTree) {
+ if (opt.virtPatmat) debugwarn("virtpatmat should not encounter empty-selector matches "+ tree)
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) {
@@ -3827,7 +3849,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 if (!((phase.id < currentRun.uncurryPhase.id) && opt.virtPatmat)) {
+ } else {
val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType))
var cases1 = typedCases(cases, packCaptured(selector1.tpe.widen), pt)
val (owntype, needAdapt) = ptOrLub(cases1 map (_.tpe))
@@ -3835,9 +3857,6 @@ 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)
}
}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index af0d768607..bed8e93d1b 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -94,8 +94,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
if (!cpsEnabled) return bounds
val anyAtCPS = newCpsParamsMarker(NothingClass.tpe, AnyClass.tpe)
-
- if (isFunctionType(tparams.head.owner.tpe) || tparams.head.owner == PartialFunctionClass) {
+ if (isFunctionType(tparams.head.owner.tpe) || isPartialFunctionType(tparams.head.owner.tpe)) {
vprintln("function bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs)
if (hasCpsParamTypes(targs.last))
bounds.reverse match {
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index 0975f16c6e..e1d699debc 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -457,11 +457,13 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
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)) {
+ // SUPER UGLY HACK: handle virtpatmat-style matches, whose labels have already been turned into DefDefs
+ if (anfStats.nonEmpty && (anfStats forall (t => !t.isDef || gen.hasSynthCaseSymbol(t)))) {
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
+ // the filter drops the ()'s emitted when transValue encountered a LabelDef
+ val stats = prologue ++ (rest filter (_.isInstanceOf[DefDef])).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)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 2db4054ef5..a78de8e6c8 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -190,32 +190,29 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val targettp = transformCPSType(tree.tpe)
-// val expr2 = if (catches.nonEmpty) {
- val pos = catches.head.pos
- val argSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
- val rhs = Match(Ident(argSym), catches1)
- val fun = Function(List(ValDef(argSym)), rhs)
- val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp)))
- val funDef = localTyper.typed(atPos(pos) { ValDef(funSym, fun) })
- val expr2 = localTyper.typed(atPos(pos) { Apply(Select(expr1, expr1.tpe.member(cpsNames.flatMapCatch)), List(Ident(funSym))) })
-
- argSym.owner = fun.symbol
- rhs.changeOwner(currentOwner -> fun.symbol)
-
- val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
-
- 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)))
+ val pos = catches.head.pos
+ val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp)))
+ val funDef = localTyper.typed(atPos(pos) {
+ ValDef(funSym, Match(EmptyTree, catches1))
+ })
+ val expr2 = localTyper.typed(atPos(pos) {
+ Apply(Select(expr1, expr1.tpe.member(cpsNames.flatMapCatch)), List(Ident(funSym)))
+ })
+
+ val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
+
+ 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/test/files/neg/t4515.check b/test/files/neg/t4515.check
index a60d16295f..856d252a0f 100644
--- a/test/files/neg/t4515.check
+++ b/test/files/neg/t4515.check
@@ -1,6 +1,6 @@
t4515.scala:37: error: type mismatch;
- found : _0(in value $anonfun) where type _0(in value $anonfun)
- required: (some other)_0(in value $anonfun)
+ found : _0(in method apply) where type _0(in method apply)
+ required: (some other)_0(in method apply)
handler.onEvent(target, ctx.getEvent, node, ctx)
^
one error found
diff --git a/test/files/pos/annotDepMethType.flags b/test/files/pos/annotDepMethType.flags
deleted file mode 100644
index e1b37447c9..0000000000
--- a/test/files/pos/annotDepMethType.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental \ No newline at end of file
diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check
index 708fcc6985..a5d7e93334 100644
--- a/test/files/run/inline-ex-handlers.check
+++ b/test/files/run/inline-ex-handlers.check
@@ -1,23 +1,27 @@
172c172
-< locals: value x$1, value x1
+< locals: value x$1, value x1, value x2, value x
---
-> locals: value x$1, value x1, variable boxed1
+> locals: value x$1, value x1, value x2, value x, variable boxed1
174c174
-< blocks: [1,2,3,4]
+< blocks: [1,2,3,5,6,7]
---
-> blocks: [1,3,4]
-186a187,188
-> 92 STORE_LOCAL(variable boxed1)
-> 92 LOAD_LOCAL(variable boxed1)
-195,197d196
+> blocks: [1,3,5,6]
+180,182d179
< 92 JUMP 2
<
< 2:
-385c384
+194,196d190
+< 92 JUMP 7
+<
+< 7:
+204a199,200
+> 92 STORE_LOCAL(variable boxed1)
+> 92 LOAD_LOCAL(variable boxed1)
+395c391
< blocks: [1,2,3,4,5,8,11,13,14,16]
---
> blocks: [1,2,3,5,8,11,13,14,16,17]
-409c408,417
+419c415,424
< 103 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
@@ -30,15 +34,15 @@
> 106 LOAD_LOCAL(value x3)
> 106 IS_INSTANCE REF(class MyException)
> 106 CZJUMP (BOOL)NE ? 5 : 11
-422,424d429
+432,434d436
< 101 JUMP 4
<
< 4:
-512c517
+522c524
< blocks: [1,2,3,4,6,7,8,9,10]
---
> blocks: [1,2,3,4,6,7,8,9,10,11,12,13]
-541c546,551
+551c553,558
< 306 THROW(MyException)
---
> ? JUMP 11
@@ -47,7 +51,7 @@
> ? LOAD_LOCAL(variable monitor4)
> 305 MONITOR_EXIT
> ? JUMP 12
-547c557,563
+557c564,570
< ? THROW(Throwable)
---
> ? JUMP 12
@@ -57,7 +61,7 @@
> 304 MONITOR_EXIT
> ? STORE_LOCAL(value t)
> ? JUMP 13
-553c569,582
+563c576,589
< ? THROW(Throwable)
---
> ? STORE_LOCAL(value t)
@@ -74,29 +78,30 @@
> 310 CALL_PRIMITIVE(EndConcat)
> 310 CALL_METHOD scala.Predef.println (dynamic)
> 310 JUMP 2
-577c606
+587c613
< catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6
---
> catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6
-580c609
+590c616
< 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
-612c641
+622c648
< blocks: [1,2,3,4,5,6,7,9,10]
---
> blocks: [1,2,3,4,5,6,7,9,10,11,12]
-636c665,671
+646c672,673
< 78 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
> ? JUMP 11
->
+647a675,679
> 11:
> 81 LOAD_LOCAL(value e)
> ? STORE_LOCAL(variable exc1)
> ? JUMP 12
-665c700,714
+>
+675c707,721
< 81 THROW(Exception)
---
> ? STORE_LOCAL(variable exc1)
@@ -114,15 +119,15 @@
> 84 STORE_LOCAL(variable result)
> 84 LOAD_LOCAL(variable exc1)
> 84 THROW(Throwable)
-687c736
+697c743
< catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3
---
> catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3
-713c762
+723c769
< 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,9,12,14,17,18,19,22,25,27,28,30,31,32,33,34]
-737c786,793
+747c793,800
< 172 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
@@ -133,12 +138,12 @@
> 170 STORE_LOCAL(value x3)
> 170 SCOPE_ENTER value x3
> 170 JUMP 18
-793c849,850
+803c856,857
< 177 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
> ? JUMP 33
-797c854,861
+807c861,868
< 170 THROW(Throwable)
---
> ? STORE_LOCAL(value ex5)
@@ -149,17 +154,17 @@
> 169 STORE_LOCAL(value x3)
> 169 SCOPE_ENTER value x3
> 169 JUMP 5
-830c894,895
+840c901,902
< 182 THROW(MyException)
---
> ? STORE_LOCAL(variable exc2)
> ? JUMP 34
-834c899,900
+844c906,907
< 169 THROW(Throwable)
---
> ? STORE_LOCAL(variable exc2)
> ? JUMP 34
-835a902,914
+845a909,921
> 34:
> 184 LOAD_MODULE object Predef
> 184 CONSTANT("finally")
@@ -173,19 +178,19 @@
> 185 LOAD_LOCAL(variable exc2)
> 185 THROW(Throwable)
>
-856c935
+866c942
< catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30) starting at: 4
---
> catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30, 32) starting at: 4
-859c938
+869c945
< 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, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3
-885c964
+895c971
< blocks: [1,2,3,6,7,8,11,14,16,17,19]
---
> blocks: [1,2,3,6,7,8,11,14,16,17,19,20]
-909c988,995
+919c995,1002
< 124 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
@@ -196,15 +201,15 @@
> 122 STORE_LOCAL(value x3)
> 122 SCOPE_ENTER value x3
> 122 JUMP 7
-969c1055
+979c1062
< 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
+1005c1088
< 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
+1029c1112,1121
< 148 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
@@ -217,15 +222,15 @@
> 154 LOAD_LOCAL(value x3)
> 154 IS_INSTANCE REF(class MyException)
> 154 CZJUMP (BOOL)NE ? 5 : 11
-1040,1042d1134
+1050,1052d1141
< 145 JUMP 4
<
< 4:
-1275c1367
+1285c1374
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1299c1391,1398
+1309c1398,1405
< 38 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -236,16 +241,16 @@
> 42 CONSTANT("IllegalArgumentException")
> 42 CALL_METHOD scala.Predef.println (dynamic)
> 42 JUMP 2
-1348c1447
+1358c1454
< blocks: [1,2,3,4,5,8,11,13,14,16,17,19]
---
> blocks: [1,2,3,5,8,11,13,14,16,17,19,20]
-1372c1471,1472
+1382c1478,1479
< 203 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
> ? JUMP 20
-1392c1492,1501
+1402c1499,1508
< 209 THROW(MyException)
---
> ? STORE_LOCAL(value ex5)
@@ -258,15 +263,15 @@
> 212 LOAD_LOCAL(value x3)
> 212 IS_INSTANCE REF(class MyException)
> 212 CZJUMP (BOOL)NE ? 5 : 11
-1405,1407d1513
+1415,1417d1520
< 200 JUMP 4
<
< 4:
-1467c1573
+1477c1580
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1491c1597,1604
+1501c1604,1611
< 58 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -277,11 +282,11 @@
> 62 CONSTANT("RuntimeException")
> 62 CALL_METHOD scala.Predef.println (dynamic)
> 62 JUMP 2
-1540c1653
+1550c1660
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1560c1673,1678
+1570c1680,1685
< 229 THROW(MyException)
---
> ? JUMP 5
@@ -290,19 +295,19 @@
> ? LOAD_LOCAL(variable monitor1)
> 228 MONITOR_EXIT
> 228 THROW(Throwable)
-1566c1684
+1576c1691
< ? THROW(Throwable)
---
> 228 THROW(Throwable)
-1594c1712
+1604c1719
< locals: value args, variable result, variable monitor2, variable monitorResult1
---
> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
-1596c1714
+1606c1721
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1619c1737,1745
+1629c1744,1752
< 245 THROW(MyException)
---
> ? STORE_LOCAL(value exception$1)
@@ -314,7 +319,7 @@
> ? LOAD_LOCAL(variable monitor2)
> 244 MONITOR_EXIT
> 244 THROW(Throwable)
-1625c1751
+1635c1758
< ? THROW(Throwable)
---
> 244 THROW(Throwable)
diff --git a/test/files/run/t5272_1.flags b/test/files/run/t5272_1.flags
new file mode 100644
index 0000000000..cb8324a345
--- /dev/null
+++ b/test/files/run/t5272_1.flags
@@ -0,0 +1 @@
+-Xoldpatmat \ No newline at end of file
diff --git a/test/files/run/t5272_2.flags b/test/files/run/t5272_2.flags
new file mode 100644
index 0000000000..cb8324a345
--- /dev/null
+++ b/test/files/run/t5272_2.flags
@@ -0,0 +1 @@
+-Xoldpatmat \ No newline at end of file