diff options
-rw-r--r-- | src/compiler/scala/reflect/internal/Types.scala | 15 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 | ||||
-rw-r--r-- | test/files/neg/t3015.check | 6 | ||||
-rw-r--r-- | test/files/neg/t5120.check | 12 | ||||
-rw-r--r-- | test/files/neg/t5120.scala | 29 |
5 files changed, 57 insertions, 7 deletions
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 { diff --git a/test/files/neg/t3015.check b/test/files/neg/t3015.check index 6095efc6a7..0b394e23d6 100644 --- a/test/files/neg/t3015.check +++ b/test/files/neg/t3015.check @@ -1,11 +1,11 @@ t3015.scala:7: error: scrutinee is incompatible with pattern type; - found : _$1 where type _$1 + found : _$1 where type +_$1 required: String val b(foo) = "foo" ^ t3015.scala:7: error: type mismatch; - found : _$1(in value foo) where type _$1(in value foo) <: String - required: (some other)_$1(in value foo) where type (some other)_$1(in value foo) + found : String with _$1(in object Test) where type +_$1(in object Test) + required: (some other)_$1(in object Test) where type +(some other)_$1(in object Test) val b(foo) = "foo" ^ two errors found diff --git a/test/files/neg/t5120.check b/test/files/neg/t5120.check new file mode 100644 index 0000000000..34d4ebde31 --- /dev/null +++ b/test/files/neg/t5120.check @@ -0,0 +1,12 @@ +t5120.scala:11: error: type mismatch; + found : Object + required: _1 + List(str, other) foreach (_.x1 = new AnyRef) + ^ +t5120.scala:25: error: type mismatch; + found : Thread + required: h.T + (which expands to) _2 + List(str, num).foreach(h => h.f1 = new Thread()) + ^ +two errors found diff --git a/test/files/neg/t5120.scala b/test/files/neg/t5120.scala new file mode 100644 index 0000000000..f28b2cfb4f --- /dev/null +++ b/test/files/neg/t5120.scala @@ -0,0 +1,29 @@ +class Cell[T](x0: T) { + type U = T + var x1: U = x0 +} + +object Test { + val str: Cell[String] = new Cell("a") + val other: Cell[Int] = new Cell(0) + + def main(args: Array[String]): Unit = { + List(str, other) foreach (_.x1 = new AnyRef) + str.x1.length + } +} +// another way demonstrating the same underlying problem, as reported by roman kalukiewicz + +class Holder[_T](_f1 : _T, _f2 : _T) { + type T = _T + var f1 : T = _f1 + var f2 : T = _f2 +} +object Test2 { + val str = new Holder("t1", "t2") + val num = new Holder(1, 2) + List(str, num).foreach(h => h.f1 = new Thread()) + def main(args: Array[String]) { + println(str.f1) + } +} |