From b7b81ca286b1f426cd19befd50fbc513bb82282f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 1 Nov 2011 17:16:51 +0000 Subject: Fixed type unsoundness problem in t5120 and als... Fixed type unsoundness problem in t5120 and also discovered by roman.kalukiewicz@gmail.com. Fix should be refined further, as I am not convinced we are quite done yet. Review by moors. --- src/compiler/scala/reflect/internal/Types.scala | 15 ++++++++++++--- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index bc739e58a9..c542c818c1 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -560,11 +560,19 @@ trait Types extends api.Types { self: SymbolTable => def asSeenFrom(pre: Type, clazz: Symbol): Type = if (isTrivial || phase.erasedTypes && pre.typeSymbol != ArrayClass) this else { +// scala.tools.nsc.util.trace.when(pre.isInstanceOf[ExistentialType])("X "+this+".asSeenfrom("+pre+","+clazz+" = ") { incCounter(asSeenFromCount) val start = startTimer(asSeenFromNanos) val m = new AsSeenFromMap(pre.normalize, clazz) val tp = m apply this - val result = existentialAbstraction(m.capturedParams, tp) + val tp1 = existentialAbstraction(m.capturedParams, tp) + val result: Type = + if (m.capturedSkolems.isEmpty) tp1 + else { + val captured = cloneSymbols(m.capturedSkolems) + captured foreach (_ setFlag CAPTURED) + tp1.substSym(m.capturedSkolems, captured) + } stopTimer(asSeenFromNanos, start) result } @@ -3606,6 +3614,7 @@ A type's typeSymbol should never be inspected directly. /** A map to compute the asSeenFrom method */ class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap with KeepOnlyTypeConstraints { + var capturedSkolems: List[Symbol] = List() var capturedParams: List[Symbol] = List() override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = { @@ -3679,7 +3688,7 @@ A type's typeSymbol should never be inspected directly. pre1 } } else { - toPrefix(base(pre, clazz).prefix, clazz.owner); + toPrefix(base(pre, clazz).prefix, clazz.owner) } toPrefix(pre, clazz) case SingleType(pre, sym) => @@ -3752,7 +3761,7 @@ A type's typeSymbol should never be inspected directly. " gets applied to arguments "+baseargs.mkString("[",",","]")+", phase = "+phase) } case ExistentialType(tparams, qtpe) => - capturedParams = capturedParams union tparams + capturedSkolems = capturedSkolems union tparams toInstance(qtpe, clazz) case t => throwError diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 976fcc8f7c..32ea3eb3b3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2841,7 +2841,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def isLocal(sym: Symbol): Boolean = if (sym == NoSymbol || sym.isRefinementClass || sym.isLocalDummy) false else if (owner == NoSymbol) tree exists (defines(_, sym)) - else containsDef(owner, sym) || isRawParameter(sym) + else containsDef(owner, sym) || isRawParameter(sym) || ((sym hasFlag EXISTENTIAL) && (sym hasFlag CAPTURED)) // todo refine this def containsLocal(tp: Type): Boolean = tp exists (t => isLocal(t.typeSymbol) || isLocal(t.termSymbol)) val normalizeLocals = new TypeMap { -- cgit v1.2.3