diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-02-27 15:22:50 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-02-27 15:22:50 -0800 |
commit | 65a5459b0c3ae7daa16a283733ff0070f3ef21ab (patch) | |
tree | c0f1e90291f282a46a4e898d725f6f8d9eb497af | |
parent | 4265ee8f3846262c778c0e1e6184b3a23f18ec2a (diff) | |
parent | 234d05d52b5a2985e53f9cb6877001b3c8fc780e (diff) | |
download | scala-65a5459b0c3ae7daa16a283733ff0070f3ef21ab.tar.gz scala-65a5459b0c3ae7daa16a283733ff0070f3ef21ab.tar.bz2 scala-65a5459b0c3ae7daa16a283733ff0070f3ef21ab.zip |
Merge branch 2.10.1 into master
Conflicts:
src/compiler/scala/tools/nsc/ast/Trees.scala
src/library/scala/concurrent/impl/ExecutionContextImpl.scala
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/Trees.scala | 53 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 8 | ||||
-rw-r--r-- | src/library/scala/collection/Iterator.scala | 2 | ||||
-rw-r--r-- | src/library/scala/concurrent/impl/ExecutionContextImpl.scala | 30 | ||||
-rwxr-xr-x | src/library/scala/xml/Utility.scala | 2 | ||||
-rw-r--r-- | test/files/jvm/t7146.check | 5 | ||||
-rw-r--r-- | test/files/jvm/t7146.scala | 23 | ||||
-rw-r--r-- | test/files/pos/t7180.scala | 13 | ||||
-rw-r--r-- | test/files/run/resetattrs-this.check | 1 | ||||
-rw-r--r-- | test/files/run/resetattrs-this.scala | 11 | ||||
-rw-r--r-- | test/files/run/t6827.scala | 3 | ||||
-rw-r--r-- | test/files/run/t7074.check | 9 | ||||
-rw-r--r-- | test/files/run/t7074.scala | 15 |
15 files changed, 154 insertions, 26 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index c8b878225e..ab6a400c63 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -342,18 +342,59 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => case tpt: TypeTree => if (tpt.original != null) transform(tpt.original) - else if (tpt.tpe != null && (tpt.wasEmpty || (tpt.tpe exists (tp => locals contains tp.typeSymbol)))) { - tpt.duplicate.clearType() + else { + val refersToLocalSymbols = tpt.tpe != null && (tpt.tpe exists (tp => locals contains tp.typeSymbol)) + val isInferred = tpt.wasEmpty + if (refersToLocalSymbols || isInferred) { + tpt.duplicate.clearType() + } else { + tpt + } } - else tree + // If one of the type arguments of a TypeApply gets reset to an empty TypeTree, then this means that: + // 1) It isn't empty now (tpt.tpe != null), but it was empty before (tpt.wasEmpty). + // 2) Thus, its argument got inferred during a preceding typecheck. + // 3) Thus, all its arguments were inferred (because scalac can only infer all or nothing). + // Therefore, we can safely erase the TypeApply altogether and have it inferred once again in a subsequent typecheck. + // UPD: Actually there's another reason for erasing a type behind the TypeTree + // is when this type refers to symbols defined in the tree being processed. + // These symbols will be erased, because we can't leave alive a type referring to them. + // Here we can only hope that everything will work fine afterwards. case TypeApply(fn, args) if args map transform exists (_.isEmpty) => transform(fn) - case This(_) if tree.symbol != null && tree.symbol.isPackageClass => + case EmptyTree => tree case _ => val dupl = tree.duplicate - if (tree.hasSymbolField && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel)) - dupl.symbol = NoSymbol + // Typically the resetAttrs transformer cleans both symbols and types. + // However there are exceptions when we cannot erase symbols due to idiosyncrasies of the typer. + // vetoXXX local variables declared below describe the conditions under which we cannot erase symbols. + // + // The first reason to not erase symbols is the threat of non-idempotency (SI-5464). + // Here we take care of labels (SI-5562) and references to package classes (SI-5705). + // There are other non-idempotencies, but they are not worked around yet. + // + // The second reason has to do with the fact that resetAttrs itself has limited usefulness. + // + // First of all, why do we need resetAttrs? Gor one, it's absolutely required to move trees around. + // One cannot just take a typed tree from one lexical context and transplant it somewhere else. + // Most likely symbols defined by those trees will become borked and the compiler will blow up (SI-5797). + // To work around we just erase all symbols and types and then hope that we'll be able to correctly retypecheck. + // For ones who're not affected by scalac Stockholm syndrome, this might seem to be an extremely naive fix, but well... + // + // Of course, sometimes erasing everything won't work, because if a given identifier got resolved to something + // in one lexical scope, it can get resolved to something else. + // + // What do we do in these cases? Enter the workaround for the workaround: resetLocalAttrs, which only destroys + // locally defined symbols, but doesn't touch references to stuff declared outside of a given tree. + // That's what localOnly and vetoScope are for. + if (dupl.hasSymbol) { + val sym = dupl.symbol + val vetoScope = localOnly && !(locals contains sym) + val vetoLabel = keepLabels && sym.isLabel + val vetoThis = dupl.isInstanceOf[This] && sym.isPackageClass + if (!(vetoScope || vetoLabel || vetoThis)) dupl.symbol = NoSymbol + } dupl.clearType() } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index a7e4006fbe..f0c2b05951 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1039,6 +1039,9 @@ abstract class ClassfileParser { for (n <- 0 until nClasses) { // FIXME: this performs an equivalent of getExceptionTypes instead of getGenericExceptionTypes (SI-7065) val cls = pool.getClassSymbol(in.nextChar.toInt) + // we call initialize due to the fact that we call Symbol.isMonomorphicType in addThrowsAnnotation + // and that method requires Symbol to be forced to give the right answers, see SI-7107 for details + cls.initialize sym.addThrowsAnnotation(cls) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index c7a4d44588..b4ec90c53e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1003,7 +1003,7 @@ trait Implicits { args foreach (getParts(_)) } } else if (sym.isAliasType) { - getParts(tp.dealias) + getParts(tp.normalize) // SI-7180 Normalize needed to expand HK type refs } else if (sym.isAbstractType) { getParts(tp.bounds.hi) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 77b0749c20..3c5e484105 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -929,6 +929,7 @@ trait Namers extends MethodSynthesis { // to use. clazz is the ModuleClass. sourceModule works also for classes defined in methods. val module = clazz.sourceModule for (cda <- module.attachments.get[ConstructorDefaultsAttachment]) { + debuglog(s"Storing the template namer in the ConstructorDefaultsAttachment of ${module.debugLocationString}.") cda.companionModuleClassNamer = templateNamer } val classTp = ClassInfoType(parents, decls, clazz) @@ -1250,8 +1251,11 @@ trait Namers extends MethodSynthesis { // module's templateNamer to classAndNamerOfModule module.attachments.get[ConstructorDefaultsAttachment] match { // by martin: the null case can happen in IDE; this is really an ugly hack on top of an ugly hack but it seems to work - // later by lukas: disabled when fixing SI-5975, i think it cannot happen anymore - case Some(cda) /*if cma.companionModuleClassNamer == null*/ => + case Some(cda) => + if (cda.companionModuleClassNamer == null) { + debugwarn(s"SI-6576 The companion module namer for $meth was unexpectedly null") + return + } val p = (cda.classWithDefault, cda.companionModuleClassNamer) moduleNamer = Some(p) p diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 77baad71d3..43db7c55e0 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -1109,7 +1109,7 @@ trait Iterator[+A] extends TraversableOnce[A] { * $willNotTerminateInf */ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = { - require(start >= 0 && start < xs.length, s"start $start out of range ${xs.length}") + require(start >= 0 && (start < xs.length || xs.length == 0), s"start $start out of range ${xs.length}") var i = start val end = start + math.min(len, xs.length - start) while (i < end && hasNext) { diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index 77625e381c..e4a0f464f9 100644 --- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala @@ -19,16 +19,16 @@ import scala.util.control.NonFatal private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: Throwable => Unit) extends ExecutionContextExecutor { + // Placed here since the creation of the executor needs to read this val + private[this] val uncaughtExceptionHandler: Thread.UncaughtExceptionHandler = new Thread.UncaughtExceptionHandler { + def uncaughtException(thread: Thread, cause: Throwable): Unit = reporter(cause) + } val executor: Executor = es match { case null => createExecutorService case some => some } - private val uncaughtExceptionHandler: Thread.UncaughtExceptionHandler = new Thread.UncaughtExceptionHandler { - def uncaughtException(thread: Thread, cause: Throwable): Unit = reporter(cause) - } - // Implement BlockContext on FJP threads class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory { def wire[T <: Thread](thread: T): T = { @@ -116,18 +116,18 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: private[concurrent] object ExecutionContextImpl { final class AdaptedForkJoinTask(runnable: Runnable) extends ForkJoinTask[Unit] { - final override def setRawResult(u: Unit): Unit = () - final override def getRawResult(): Unit = () - final override def exec(): Boolean = try { runnable.run(); true } catch { - case anything: Throwable ⇒ - val t = Thread.currentThread - t.getUncaughtExceptionHandler match { - case null ⇒ - case some ⇒ some.uncaughtException(t, anything) + final override def setRawResult(u: Unit): Unit = () + final override def getRawResult(): Unit = () + final override def exec(): Boolean = try { runnable.run(); true } catch { + case anything: Throwable ⇒ + val t = Thread.currentThread + t.getUncaughtExceptionHandler match { + case null ⇒ + case some ⇒ some.uncaughtException(t, anything) + } + throw anything + } } - throw anything - } - } def fromExecutor(e: Executor, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextImpl = new ExecutionContextImpl(e, reporter) def fromExecutorService(es: ExecutorService, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextImpl with ExecutionContextExecutorService = diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 06fd46701a..fff27c6e30 100755 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -64,7 +64,7 @@ object Utility extends AnyRef with parsing.TokenTests { val key = md.key val smaller = sort(md.filter { m => m.key < key }) val greater = sort(md.filter { m => m.key > key }) - smaller.copy(md.copy ( greater )) + smaller.foldRight (md copy greater) ((x, xs) => x copy xs) } /** Return the node with its attribute list sorted alphabetically diff --git a/test/files/jvm/t7146.check b/test/files/jvm/t7146.check new file mode 100644 index 0000000000..7c76040205 --- /dev/null +++ b/test/files/jvm/t7146.check @@ -0,0 +1,5 @@ +should be scala.concurrent.impl.ExecutionContextImpl == true +should be scala.concurrent.forkjoin.ForkJoinPool == true +should have non-null UncaughtExceptionHandler == true +should be a scala.concurrent.impl.ExecutionContextImpl UncaughtExceptionHandler == true +should just print out on uncaught == true diff --git a/test/files/jvm/t7146.scala b/test/files/jvm/t7146.scala new file mode 100644 index 0000000000..2bd03d6d02 --- /dev/null +++ b/test/files/jvm/t7146.scala @@ -0,0 +1,23 @@ +import java.util.concurrent.Executor +import scala.concurrent._ +import scala.util.control.NoStackTrace + +object Test { + def main(args: Array[String]) { + println("should be scala.concurrent.impl.ExecutionContextImpl == " + + ExecutionContext.global.toString.startsWith("scala.concurrent.impl.ExecutionContextImpl")) + val i = ExecutionContext.global.asInstanceOf[{ def executor: Executor }] + println("should be scala.concurrent.forkjoin.ForkJoinPool == " + + i.executor.toString.startsWith("scala.concurrent.forkjoin.ForkJoinPool")) + val u = i.executor. + asInstanceOf[{ def getUncaughtExceptionHandler: Thread.UncaughtExceptionHandler }]. + getUncaughtExceptionHandler + println("should have non-null UncaughtExceptionHandler == " + (u ne null)) + println("should be a scala.concurrent.impl.ExecutionContextImpl UncaughtExceptionHandler == " + + u.toString.startsWith("scala.concurrent.impl.ExecutionContextImpl")) + print("should just print out on uncaught == ") + u.uncaughtException(Thread.currentThread, new Throwable { + override def printStackTrace() { println("true") } + }) + } +} diff --git a/test/files/pos/t7180.scala b/test/files/pos/t7180.scala new file mode 100644 index 0000000000..15582f6df3 --- /dev/null +++ b/test/files/pos/t7180.scala @@ -0,0 +1,13 @@ +trait Higher[F[_]] + +trait Box[A] +object Box { + implicit def HigherBox = new Higher[Box] {} +} + +object Foo { + val box = implicitly[Higher[Box]] // compiles fine !!! + + type Bar[A] = Box[A] + val bar = implicitly[Higher[Bar]] // <-- this doesn't compile in 2.10.1-RC1, but does in 2.10.0 !!! +} diff --git a/test/files/run/resetattrs-this.check b/test/files/run/resetattrs-this.check new file mode 100644 index 0000000000..27ba77ddaf --- /dev/null +++ b/test/files/run/resetattrs-this.check @@ -0,0 +1 @@ +true diff --git a/test/files/run/resetattrs-this.scala b/test/files/run/resetattrs-this.scala new file mode 100644 index 0000000000..12afa3d712 --- /dev/null +++ b/test/files/run/resetattrs-this.scala @@ -0,0 +1,11 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.ToolBox + +object Test extends App { + val tb = cm.mkToolBox() + val tree = Select(This(cm.staticPackage("scala").moduleClass), newTermName("Predef")) + val ttree = tb.typeCheck(tree) + val rttree = tb.resetAllAttrs(ttree) + println(tb.eval(rttree) == Predef) +}
\ No newline at end of file diff --git a/test/files/run/t6827.scala b/test/files/run/t6827.scala index 7e8918e3dc..8e17af09e2 100644 --- a/test/files/run/t6827.scala +++ b/test/files/run/t6827.scala @@ -28,4 +28,7 @@ object Test extends App { tryit("read -1", 0, -1) tryit("invalid read 0", 30, 0) tryit("invalid read -1", 30, -1) + + // okay, see SI-7128 + "...".toIterator.copyToArray(new Array[Char](0), 0, 0) } diff --git a/test/files/run/t7074.check b/test/files/run/t7074.check new file mode 100644 index 0000000000..ab9cf11f16 --- /dev/null +++ b/test/files/run/t7074.check @@ -0,0 +1,9 @@ +<a/> +<a b="2" c="3" d="1"/> +<a b="2" c="4" d="1" e="3" f="5"/> +<a b="5" c="4" d="3" e="2" f="1"/> +<a b="1" c="2" d="3" e="4" f="5"/> +<a a:b="2" a:c="3" a:d="1"/> +<a a:b="2" a:c="4" a:d="1" a:e="3" a:f="5"/> +<a a:b="5" a:c="4" a:d="3" a:e="2" a:f="1"/> +<a a:b="1" a:c="2" a:d="3" a:e="4" a:f="5"/> diff --git a/test/files/run/t7074.scala b/test/files/run/t7074.scala new file mode 100644 index 0000000000..693a076a7a --- /dev/null +++ b/test/files/run/t7074.scala @@ -0,0 +1,15 @@ +import scala.xml.Utility.sort + +object Test extends App { + println(sort(<a/>)) + println(sort(<a d="1" b="2" c="3"/>)) + println(sort(<a d="1" b="2" e="3" c="4" f="5"/>)) + println(sort(<a f="1" e="2" d="3" c="4" b="5"/>)) + println(sort(<a b="1" c="2" d="3" e="4" f="5"/>)) + + println(sort(<a a:d="1" a:b="2" a:c="3"/>)) + println(sort(<a a:d="1" a:b="2" a:e="3" a:c="4" a:f="5"/>)) + println(sort(<a a:f="1" a:e="2" a:d="3" a:c="4" a:b="5"/>)) + println(sort(<a a:b="1" a:c="2" a:d="3" a:e="4" a:f="5"/>)) +} + |