summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala16
2 files changed, 21 insertions, 23 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
index 9b50853c51..1fd9f6fc13 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
@@ -132,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
@@ -1105,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 = {
@@ -1658,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
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c4eb43c427..dd8631ba21 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2199,7 +2199,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
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)
@@ -2223,7 +2223,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// 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)
}
}
@@ -3772,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))
@@ -3802,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 if (!opt.virtPatmat || isPastTyper) {
+ } 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))
@@ -4688,7 +4694,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)
}