From 348ff4b6176a379dba943a6b6e0dbc71410f454f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 14 Feb 2013 15:10:58 +0100 Subject: SI-7128 Fix regression in copyToArray for empty arrays --- src/library/scala/collection/Iterator.scala | 2 +- test/files/run/t6827.scala | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 696bc4ab5c..2bb5bd1df9 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -1111,7 +1111,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/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) } -- cgit v1.2.3 From e2a17d9c8234bf620ba0109f9ab4bae822c20bf0 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 16 Feb 2013 23:42:09 +0100 Subject: resetAttrs now always erases This.tpe The symbol of This, if it points to a package class, isn't touched, just as usual, so that our Select(Select(Select(...))) => This(...) optimization works fine with attr reset. However the tpe is now erased, so that subsequent reflective compilation doesn't spuriously fail when seeing that some subtrees of a tree being compiled are typed. Erasing the tpe doesn't pose even a tiniest problem, because, as it can be seen in typedThis, type is trivially reconstructed from the symbol. --- src/compiler/scala/tools/nsc/ast/Trees.scala | 11 +++++++---- test/files/run/resetattrs-this.check | 1 + test/files/run/resetattrs-this.scala | 11 +++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/files/run/resetattrs-this.check create mode 100644 test/files/run/resetattrs-this.scala diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 2ad762fd55..f83a9632f6 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -335,14 +335,17 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => else tree case TypeApply(fn, args) if args map transform exists (_.isEmpty) => transform(fn) - case This(_) if tree.symbol != null && tree.symbol.isPackageClass => - tree case EmptyTree => tree case _ => val dupl = tree.duplicate - if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel)) - dupl.symbol = NoSymbol + 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.tpe = null dupl } 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 -- cgit v1.2.3 From 19649d425a761f9d6b91641df92d604f60124d08 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 19 Feb 2013 15:19:03 +0100 Subject: SI-6576 Workaround / diagnostic for IDE NPE. Seems like this was too optimistic: > // later by lukas: disabled when fixing SI-5975 > // i think it cannot happen anymore - restored the null check - added logging when we set the namer in this attachment, in the hope of spotting a pattern in the wild. We don't have a test case yet; if we did we could most likely have a more principled fix. But this should suffice for 2.10.1. --- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 341dbfbe1f..7a3ab00578 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -908,6 +908,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) @@ -1229,8 +1230,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 -- cgit v1.2.3 From bb067d31e4f02cc605146c676031bbfccac639c2 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 19 Feb 2013 18:51:24 +0100 Subject: SI-7146 - Fixing checkinit bug in ExecutionContextImpl and adding test --- .../concurrent/impl/ExecutionContextImpl.scala | 8 ++++---- test/files/jvm/t7146.check | 5 +++++ test/files/jvm/t7146.scala | 23 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/files/jvm/t7146.check create mode 100644 test/files/jvm/t7146.scala diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index 43b437dbc6..0aa6b37ffc 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[this] 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 = { 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") } + }) + } +} -- cgit v1.2.3 From dafebd040e938208e26a27dbd1e14c0307021cf0 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 12 Feb 2013 12:32:20 +0100 Subject: Fix typing idempotency bug with Annotated trees typedAnnotated transforms an Annotated tree into a Typed tree. The original field of the result is set to the Annotated tree. The bug was that typedAnnotated was using the untyped Annotated tree as original, but also set its type. When re-typing later on the same Annotated tree, the typer would consider it as alreadyTyped. This is incorrect, the typer needs to convert Annotated trees to Typed. Also, the Annotated tree only had its type field set, but its children were still untyped. This crashed the compiler lateron, non-typed trees would get out of the typing phase. --- .../scala/tools/nsc/typechecker/Typers.scala | 14 ++--- test/files/run/annotatedRetyping.check | 6 +++ test/files/run/annotatedRetyping.scala | 62 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 test/files/run/annotatedRetyping.check create mode 100644 test/files/run/annotatedRetyping.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 478312116a..cff3f4f0fa 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4153,15 +4153,11 @@ trait Typers extends Modes with Adaptations with Tags { def resultingTypeTree(tpe: Type) = { // we need symbol-ful originals for reification // hence we go the extra mile to hand-craft tis guy - val original = - if (arg1.isType) - arg1 match { - case tt @ TypeTree() => Annotated(ann, tt.original) - // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)" - case _ => Annotated(ann, arg1) - } - else - tree + val original = arg1 match { + case tt @ TypeTree() => Annotated(ann, tt.original) + // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)" + case _ => Annotated(ann, arg1) + } original setType ann.tpe TypeTree(tpe) setOriginal original setPos tree.pos.focus } diff --git a/test/files/run/annotatedRetyping.check b/test/files/run/annotatedRetyping.check new file mode 100644 index 0000000000..b296a80526 --- /dev/null +++ b/test/files/run/annotatedRetyping.check @@ -0,0 +1,6 @@ +typing List(1, 2).map(((x) => { + val another = scala.Tuple2(t.nt, t.tr): @testAnn match { + case scala.Tuple2(_, _) => 1 + }; + x +})) diff --git a/test/files/run/annotatedRetyping.scala b/test/files/run/annotatedRetyping.scala new file mode 100644 index 0000000000..cf1b0f27b5 --- /dev/null +++ b/test/files/run/annotatedRetyping.scala @@ -0,0 +1,62 @@ +import scala.tools.partest._ +import scala.tools.nsc._ + +object Test extends DirectTest { + + override def extraSettings: String = "-usejavacp" + + def code = """ + class testAnn extends annotation.Annotation + + object t { + def nt = 1 + def tr = "a" + } + + class Test { + List(1,2).map(x => { + val another = ((t.nt, t.tr): @testAnn) match { case (_, _) => 1 } + x + }) + } + """.trim + + + // point of this test: type-check the "Annotated" tree twice. first time the analyzer plugin types it, + // second time the typer. + + // bug was that typedAnnotated assigned a type to the Annotated tree. The second type check would consider + // the tree as alreadyTyped, which is not cool, the Annotated needs to be transformed into a Typed tree. + + def show() { + val global = newCompiler() + import global._ + import analyzer._ + import collection.{mutable => m} + + object analyzerPlugin extends AnalyzerPlugin { + val templates: m.Map[Symbol, (Template, Typer)] = m.Map() + override def pluginsTypeSig(tpe: Type, typer: Typer, defTree: Tree, pt: Type): Type = { + defTree match { + case impl: Template => + templates += typer.context.owner -> (impl, typer) + + case dd: DefDef if dd.symbol.isPrimaryConstructor && templates.contains(dd.symbol.owner) => + val (impl, templTyper) = templates(dd.symbol.owner) + for (stat <- impl.body.filterNot(_.isDef)) { + println("typing "+ stat) + val statsOwner = impl.symbol orElse templTyper.context.owner.newLocalDummy(impl.pos) + val tpr = analyzer.newTyper(templTyper.context.make(stat, statsOwner)) + tpr.typed(stat) + } + + case _ => + } + tpe + } + } + + addAnalyzerPlugin(analyzerPlugin) + compileString(global)(code) + } +} -- cgit v1.2.3 From 26be2067a9dcc0aa44063aa94581d970427c8ad6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 18 Feb 2013 12:06:19 +0100 Subject: Additional test case for Lukas' fix to annotated originals. This was inspired by the regression that Mark encountered when upgrading SBT from 2.10.0 to 2.10.1-RC1. --- test/files/pos/annotated-original/C_2.scala | 7 +++++++ test/files/pos/annotated-original/M_1.scala | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 test/files/pos/annotated-original/C_2.scala create mode 100644 test/files/pos/annotated-original/M_1.scala diff --git a/test/files/pos/annotated-original/C_2.scala b/test/files/pos/annotated-original/C_2.scala new file mode 100644 index 0000000000..36a09ffe0c --- /dev/null +++ b/test/files/pos/annotated-original/C_2.scala @@ -0,0 +1,7 @@ +object Bug { + M.m { + def s = "" + M.m(s): @unchecked // error: macro has not been expanded. + ??? + } +} diff --git a/test/files/pos/annotated-original/M_1.scala b/test/files/pos/annotated-original/M_1.scala new file mode 100644 index 0000000000..01654e02cf --- /dev/null +++ b/test/files/pos/annotated-original/M_1.scala @@ -0,0 +1,7 @@ +import language.experimental.macros +import reflect.macros.Context + +object M { + def impl(c: Context)(a: c.Expr[Any]) = c.Expr[Any](c.resetLocalAttrs(a.tree)) + def m(a: Any) = macro impl +} -- cgit v1.2.3 From 89be6914af3908717ebd78cb57dcdc9ff1d8253e Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 23 Feb 2013 02:33:23 +0100 Subject: fixes the test for SI-7112 Freshly released Java 1.6.0_41 for OSX fails with "IllegalAccessError: tried to access class JavaSimpleEnumeration_1 from class sun.proxy.$Proxy6", and rightfully so, because that class isn't public. I think I will avoid the usual "how could this even work before" in this commit message. --- test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java b/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java index 39246141cc..5f4dcce8a7 100644 --- a/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java +++ b/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java @@ -1,4 +1,4 @@ -enum JavaSimpleEnumeration_1 { +public enum JavaSimpleEnumeration_1 { FOO, BAR } \ No newline at end of file -- cgit v1.2.3 From 1976d9fd780c2220178113503841504b39b419a7 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 23 Feb 2013 02:33:23 +0100 Subject: fixes the test for SI-7112 Freshly released Java 1.6.0_41 for OSX fails with "IllegalAccessError: tried to access class JavaSimpleEnumeration_1 from class sun.proxy.$Proxy6", and rightfully so, because that class isn't public. I think I will avoid the usual "how could this even work before" in this commit message. --- test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java b/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java index 39246141cc..5f4dcce8a7 100644 --- a/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java +++ b/test/files/run/reflection-java-annotations/JavaSimpleEnumeration_1.java @@ -1,4 +1,4 @@ -enum JavaSimpleEnumeration_1 { +public enum JavaSimpleEnumeration_1 { FOO, BAR } \ No newline at end of file -- cgit v1.2.3 From 8187debb7148483d991b7fa131e0c66cdee6e646 Mon Sep 17 00:00:00 2001 From: Szabolcs Berecz Date: Sun, 17 Feb 2013 13:56:13 +0100 Subject: SI-7074 Fix xml attribute sorting Sorting the attributes of an xml element could drop some of the attributes. It was caused by the incorrect use of MetaData#copy() to concatenate "smaller" with the rest of the attributes. The MetaData#copy() method is similar to the following hypothetical method on a List: def copy(other: List): List = head :: other The fix prepends all elements of "smaller" to the rest of the attributes in the proper order. --- src/library/scala/xml/Utility.scala | 2 +- test/files/run/t7074.check | 9 +++++++++ test/files/run/t7074.scala | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t7074.check create mode 100644 test/files/run/t7074.scala diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 9429e9caa7..030a89773e 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/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 @@ + + + + + + + + + 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()) + println(sort()) + println(sort()) + println(sort()) + println(sort()) + + println(sort()) + println(sort()) + println(sort()) + println(sort()) +} + -- cgit v1.2.3 From de1f74990aa5321a47dd1366a1e283f2ca8a4e6f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 25 Feb 2013 11:37:14 +0100 Subject: SI-7180 Fix regression in implicit scope of HK type alias. We actually need to call normalize here, otherwise we don't progress through #1 below. [infer implicit] scala.this.Predef.implicitly[Higher[Foo.Bar]] with pt=Higher[Foo.Bar] in object Foo 1. tp=Foo.Bar tp.normalize=[A <: ]Foo.Bar[A] tp.dealias=Foo.Bar 2. tp=Foo.Bar[A] tp.normalize=Box[A] tp.dealias=Box[A] --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 2 +- test/files/pos/t7180.scala | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t7180.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index d1cf9b1904..3bea049c59 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1015,7 +1015,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/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 !!! +} -- cgit v1.2.3 From 4f1bfece9bc429ea465991355353a1e2c38c2e1a Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Mon, 25 Feb 2013 16:33:07 -0800 Subject: Fix SI-7107: scala now thinks every exception is polymorphic We need to force info of the `cls` in `parseExceptions` because we pass `cls` to `addThrowsAnnotation` which in turn calls `Symbol.isMonomorphicType` that relies on a symbol being initialized to give right answers. In the future we should just clean up implementation of `isMonomorphicType` method to not rely on a symbol being initialized as there's no inherent reason for that in most cases. In cases where there's reason for that we should just force the initialization. This patch does not come with a test-case because it's hard to reproduce not initialized symbols in partest reliably. --- src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index a517a33279..1f42fa8aab 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1044,6 +1044,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) } } -- cgit v1.2.3 From 3e7db2d189ca37203b39d2c028581a0ae1281823 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 26 Feb 2013 19:42:52 +0100 Subject: adds some comments to resetAttrs --- src/compiler/scala/tools/nsc/ast/Trees.scala | 46 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index f83a9632f6..0a12737572 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -327,18 +327,54 @@ 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)))) { - val dupl = tpt.duplicate - dupl.tpe = null - dupl + else { + val refersToLocalSymbols = tpt.tpe != null && (tpt.tpe exists (tp => locals contains tp.typeSymbol)) + val isInferred = tpt.wasEmpty + if (refersToLocalSymbols || isInferred) { + val dupl = tpt.duplicate + dupl.tpe = null + dupl + } 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 EmptyTree => tree case _ => val dupl = tree.duplicate + // 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) -- cgit v1.2.3