summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2010-01-08 13:09:57 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2010-01-08 13:09:57 +0000
commita487bd514e44e60f55abf26a20536162f8a5741a (patch)
treea2b8c3bd3ae6d39004ae1d47dec6f28cbb5d68e7
parent12e885143ed38d67f9f94e7422852f01f4b85538 (diff)
downloadscala-a487bd514e44e60f55abf26a20536162f8a5741a.tar.gz
scala-a487bd514e44e60f55abf26a20536162f8a5741a.tar.bz2
scala-a487bd514e44e60f55abf26a20536162f8a5741a.zip
Merged revisions 20307,20309-20312,20329,20341,...
Merged revisions 20307,20309-20312,20329,20341,20344,20349-20351,20357-20359,20363-20366, 20376-20377,20385-20388,20390,20398-20399,20401,20404-20406 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r20307 | milessabin | 2009-12-23 12:55:30 +0100 (Wed, 23 Dec 2009) | 1 line In resident mode the reporter should be reset after each compiler Run. review by odersky. ........ r20309 | odersky | 2009-12-23 16:02:17 +0100 (Wed, 23 Dec 2009) | 1 line Weeds out stale symbols in typer. review by milessabin. ........ r20310 | odersky | 2009-12-23 16:02:38 +0100 (Wed, 23 Dec 2009) | 1 line new testcase no review necessary. ........ r20311 | extempore | 2009-12-23 18:57:36 +0100 (Wed, 23 Dec 2009) | 9 lines Created team of private[collection] abstract classes and traits in scala.collection.views. Factored boilerplate and base Transformed traits out of *ViewLike classes. Executive summary and motivation: 4812029 Dec 23 09:47 scala-library.jar // before 604150 Dec 23 09:24 4scala-library.jar // after Direct size savings of 4.5%. Review by odersky. ........ r20312 | odersky | 2009-12-23 21:09:54 +0100 (Wed, 23 Dec 2009) | 2 lines a more thorough treatment of the stale symbol problem. review by milessabin. ........ r20329 | extempore | 2009-12-31 22:37:32 +0100 (Thu, 31 Dec 2009) | 1 line Added an XML.load overload which takes an URL. ........ r20341 | phaller | 2010-01-04 13:06:07 +0100 (Mon, 04 Jan 2010) | 1 line Fixed #2852 and #2854. ........ r20344 | rytz | 2010-01-04 15:08:25 +0100 (Mon, 04 Jan 2010) | 1 line fix parsing of .net types with inner classes ........ r20349 | odersky | 2010-01-04 21:46:26 +0100 (Mon, 04 Jan 2010) | 2 lines Added extensive statistics, reduced time of implicit resolution by 2/3rds, of whole typer by 1/4 to 1/3rd. ........ r20350 | odersky | 2010-01-04 23:33:01 +0100 (Mon, 04 Jan 2010) | 3 lines refined changes to implicits to allow again implicits in non-static companion objects. ........ r20351 | odersky | 2010-01-05 00:55:51 +0100 (Tue, 05 Jan 2010) | 2 lines polished statistics generation. no review necessary. ........ r20357 | phaller | 2010-01-05 10:33:22 +0100 (Tue, 05 Jan 2010) | 1 line Adjusted timeout in test. No review. ........ r20358 | phaller | 2010-01-05 12:39:12 +0100 (Tue, 05 Jan 2010) | 1 line Also run neg tests in directories in ant task. No review. ........ r20359 | rytz | 2010-01-05 15:02:13 +0100 (Tue, 05 Jan 2010) | 1 line rebuilt plugin test jars. no review ........ r20363 | odersky | 2010-01-05 17:42:11 +0100 (Tue, 05 Jan 2010) | 1 line further optimizations to implicits. Added general purpose counters and timers to statistics. no review. ........ r20364 | odersky | 2010-01-05 17:43:41 +0100 (Tue, 05 Jan 2010) | 1 line Closes #2853. No review necessary. ........ r20365 | odersky | 2010-01-05 17:44:32 +0100 (Tue, 05 Jan 2010) | 1 line Closes #2848. No review. ........ r20366 | phaller | 2010-01-05 17:57:30 +0100 (Tue, 05 Jan 2010) | 1 line Moved plugin neg tests to pending. No review. ........ r20376 | plocinic | 2010-01-06 12:12:10 +0100 (Wed, 06 Jan 2010) | 1 line Closes #2793, #2651, #2650, #2653. Review by dragos. ........ r20377 | plocinic | 2010-01-06 13:33:28 +0100 (Wed, 06 Jan 2010) | 1 line Fixes #2857. No review. ........ r20385 | plocinic | 2010-01-06 16:26:36 +0100 (Wed, 06 Jan 2010) | 1 line Closes #2657, #2789. Review by dragos. ........ r20386 | moors | 2010-01-06 17:23:42 +0100 (Wed, 06 Jan 2010) | 2 lines reinstated accidentally deleted comment no review ........ r20387 | odersky | 2010-01-06 17:44:32 +0100 (Wed, 06 Jan 2010) | 1 line Fixed issue with operator symbols. '* is now a symbol. review by community. ........ r20388 | odersky | 2010-01-06 17:46:48 +0100 (Wed, 06 Jan 2010) | 1 line further speed improvements by eliminating most uses of paramTypes. Knocks off about 3% of typer time. Not overwhelming but still worth doing. Review by rytz. ........ r20390 | milessabin | 2010-01-06 19:48:13 +0100 (Wed, 06 Jan 2010) | 1 line scalac portion of fix for #2689. For the isStale test to work as intended the source file path has to be inferred from the orphaned classfile. Review by Odersky. ........ r20398 | dragos | 2010-01-07 12:00:20 +0100 (Thu, 07 Jan 2010) | 2 lines Fixed #2850 -- while inside finally causes VerifyError, review by rytz ........ r20399 | phaller | 2010-01-07 12:35:41 +0100 (Thu, 07 Jan 2010) | 1 line Fixed issue in Reactor/Actor that could lead to premature termination of actors. Added test that could reproduce it (occurred more often on larger inputs, but test should not take too much time). The issue also caused the reactor-exceptionOnSend test to timeout sometimes. Review by plocinic. ........ r20401 | odersky | 2010-01-07 13:03:44 +0100 (Thu, 07 Jan 2010) | 1 line Fixed #2844 with dpp's patch. review by xmlteam. ........ r20404 | plocinic | 2010-01-07 17:41:18 +0100 (Thu, 07 Jan 2010) | 1 line Improvements in checking for references during dependency analysis. For example more carefully analysis of abstract type members, typerefs etc. References #2793. review by dragos. ........ r20405 | dragos | 2010-01-07 18:01:01 +0100 (Thu, 07 Jan 2010) | 2 lines Added warning for failed inlining when the target is @inline annotated. No review necessary. ........ r20406 | dragos | 2010-01-07 18:24:21 +0100 (Thu, 07 Jan 2010) | 2 lines Added final modifiers to several classes used by Predef implicits. Review by community. ........
-rw-r--r--src/actors/scala/actors/Actor.scala8
-rw-r--r--src/actors/scala/actors/Debug.scala9
-rw-r--r--src/actors/scala/actors/Reactor.scala22
-rw-r--r--src/actors/scala/actors/ReactorTask.scala1
-rw-r--r--src/actors/scala/actors/ReplyReactor.scala8
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala16
-rw-r--r--src/compiler/scala/tools/nsc/Main.scala1
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala31
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala5
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala27
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/Changes.scala14
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala40
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala44
-rw-r--r--src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala13
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala16
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala212
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala342
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala141
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala156
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala4
-rw-r--r--src/compiler/scala/tools/nsc/util/Statistics.scala253
-rw-r--r--src/library/scala/Predef.scala6
-rw-r--r--src/library/scala/collection/IndexedSeqViewLike.scala70
-rw-r--r--src/library/scala/collection/IterableViewLike.scala28
-rw-r--r--src/library/scala/collection/SeqViewLike.scala26
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala23
-rw-r--r--src/library/scala/collection/immutable/StringOps.scala2
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala2
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqView.scala5
-rw-r--r--src/library/scala/collection/mutable/MultiMap.scala4
-rw-r--r--src/library/scala/collection/views/Transformed.scala128
-rw-r--r--src/library/scala/ref/PhantomReference.scala8
-rw-r--r--src/library/scala/ref/ReferenceQueue.scala23
-rw-r--r--src/library/scala/ref/ReferenceWrapper.scala7
-rw-r--r--src/library/scala/ref/SoftReference.scala11
-rw-r--r--src/library/scala/ref/WeakReference.scala11
-rw-r--r--src/library/scala/xml/factory/XMLLoader.scala4
-rw-r--r--src/library/scala/xml/parsing/MarkupParser.scala2
-rw-r--r--src/partest/scala/tools/partest/PartestTask.scala2
-rw-r--r--test/files/jvm/future-awaitall-zero.scala4
-rw-r--r--test/files/jvm/reactor-producer-consumer.check10
-rw-r--r--test/files/jvm/reactor-producer-consumer.scala75
-rw-r--r--test/files/neg/plugin-after-terminal/lib/plugins.jar.desired.sha11
-rw-r--r--test/files/neg/plugin-before-parser/lib/plugins.jar.desired.sha11
-rw-r--r--test/files/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha11
-rw-r--r--test/files/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha11
-rw-r--r--test/files/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha11
-rw-r--r--test/files/neg/t2641.check8
-rw-r--r--test/files/pos/implicits.scala16
-rw-r--r--test/files/run/exceptions-2.scala19
-rw-r--r--test/files/run/t2857.check1
-rw-r--r--test/files/run/t2857.scala9
-rw-r--r--test/pending/neg/plugin-after-terminal.check (renamed from test/files/neg/plugin-after-terminal.check)0
-rw-r--r--test/pending/neg/plugin-after-terminal.flags (renamed from test/files/neg/plugin-after-terminal.flags)0
-rw-r--r--test/pending/neg/plugin-after-terminal/lib/plugins.jar.desired.sha11
-rwxr-xr-xtest/pending/neg/plugin-after-terminal/misc/build.sh (renamed from test/files/neg/plugin-after-terminal/misc/build.sh)0
-rw-r--r--test/pending/neg/plugin-after-terminal/misc/scalac-plugin.xml (renamed from test/files/neg/plugin-after-terminal/misc/scalac-plugin.xml)0
-rw-r--r--test/pending/neg/plugin-after-terminal/src/ThePlugin.scala (renamed from test/files/neg/plugin-after-terminal/src/ThePlugin.scala)0
-rw-r--r--test/pending/neg/plugin-after-terminal/testsource.scala (renamed from test/files/neg/plugin-after-terminal/testsource.scala)0
-rw-r--r--test/pending/neg/plugin-before-parser.check (renamed from test/files/neg/plugin-before-parser.check)0
-rw-r--r--test/pending/neg/plugin-before-parser.flags (renamed from test/files/neg/plugin-before-parser.flags)0
-rw-r--r--test/pending/neg/plugin-before-parser/lib/plugins.jar.desired.sha11
-rwxr-xr-xtest/pending/neg/plugin-before-parser/misc/build.sh (renamed from test/files/neg/plugin-before-parser/misc/build.sh)0
-rw-r--r--test/pending/neg/plugin-before-parser/misc/scalac-plugin.xml (renamed from test/files/neg/plugin-before-parser/misc/scalac-plugin.xml)0
-rw-r--r--test/pending/neg/plugin-before-parser/src/ThePlugin.scala (renamed from test/files/neg/plugin-before-parser/src/ThePlugin.scala)0
-rw-r--r--test/pending/neg/plugin-before-parser/testsource.scala (renamed from test/files/neg/plugin-before-parser/testsource.scala)0
-rw-r--r--test/pending/neg/plugin-cyclic-dependency.check (renamed from test/files/neg/plugin-cyclic-dependency.check)0
-rw-r--r--test/pending/neg/plugin-cyclic-dependency.flags (renamed from test/files/neg/plugin-cyclic-dependency.flags)0
-rw-r--r--test/pending/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha11
-rwxr-xr-xtest/pending/neg/plugin-cyclic-dependency/misc/build.sh (renamed from test/files/neg/plugin-cyclic-dependency/misc/build.sh)0
-rw-r--r--test/pending/neg/plugin-cyclic-dependency/misc/scalac-plugin.xml (renamed from test/files/neg/plugin-cyclic-dependency/misc/scalac-plugin.xml)0
-rw-r--r--test/pending/neg/plugin-cyclic-dependency/src/ThePlugin.scala (renamed from test/files/neg/plugin-cyclic-dependency/src/ThePlugin.scala)0
-rw-r--r--test/pending/neg/plugin-cyclic-dependency/testsource.scala (renamed from test/files/neg/plugin-cyclic-dependency/testsource.scala)0
-rw-r--r--test/pending/neg/plugin-multiple-rafter.check (renamed from test/files/neg/plugin-multiple-rafter.check)0
-rw-r--r--test/pending/neg/plugin-multiple-rafter.flags (renamed from test/files/neg/plugin-multiple-rafter.flags)0
-rw-r--r--test/pending/neg/plugin-multiple-rafter/lib/plugins.jar.desired.sha1 (renamed from test/files/neg/plugin-multiple-rafter/lib/plugins.jar.desired.sha1)0
-rwxr-xr-xtest/pending/neg/plugin-multiple-rafter/misc/build.sh (renamed from test/files/neg/plugin-multiple-rafter/misc/build.sh)0
-rw-r--r--test/pending/neg/plugin-multiple-rafter/misc/scalac-plugin.xml (renamed from test/files/neg/plugin-multiple-rafter/misc/scalac-plugin.xml)0
-rw-r--r--test/pending/neg/plugin-multiple-rafter/src/ThePlugin.scala (renamed from test/files/neg/plugin-multiple-rafter/src/ThePlugin.scala)0
-rw-r--r--test/pending/neg/plugin-multiple-rafter/testsource.scala (renamed from test/files/neg/plugin-multiple-rafter/testsource.scala)0
-rw-r--r--test/pending/neg/plugin-rafter-before-1.check (renamed from test/files/neg/plugin-rafter-before-1.check)0
-rw-r--r--test/pending/neg/plugin-rafter-before-1.flags (renamed from test/files/neg/plugin-rafter-before-1.flags)0
-rw-r--r--test/pending/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha11
-rwxr-xr-xtest/pending/neg/plugin-rafter-before-1/misc/build.sh (renamed from test/files/neg/plugin-rafter-before-1/misc/build.sh)0
-rw-r--r--test/pending/neg/plugin-rafter-before-1/misc/scalac-plugin.xml (renamed from test/files/neg/plugin-rafter-before-1/misc/scalac-plugin.xml)0
-rw-r--r--test/pending/neg/plugin-rafter-before-1/src/ThePlugin.scala (renamed from test/files/neg/plugin-rafter-before-1/src/ThePlugin.scala)0
-rw-r--r--test/pending/neg/plugin-rafter-before-1/testsource.scala (renamed from test/files/neg/plugin-rafter-before-1/testsource.scala)0
-rw-r--r--test/pending/neg/plugin-rightafter-terminal.check (renamed from test/files/neg/plugin-rightafter-terminal.check)0
-rw-r--r--test/pending/neg/plugin-rightafter-terminal.flags (renamed from test/files/neg/plugin-rightafter-terminal.flags)0
-rw-r--r--test/pending/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha11
-rwxr-xr-xtest/pending/neg/plugin-rightafter-terminal/misc/build.sh (renamed from test/files/neg/plugin-rightafter-terminal/misc/build.sh)0
-rw-r--r--test/pending/neg/plugin-rightafter-terminal/misc/scalac-plugin.xml (renamed from test/files/neg/plugin-rightafter-terminal/misc/scalac-plugin.xml)0
-rw-r--r--test/pending/neg/plugin-rightafter-terminal/src/ThePlugin.scala (renamed from test/files/neg/plugin-rightafter-terminal/src/ThePlugin.scala)0
-rw-r--r--test/pending/neg/plugin-rightafter-terminal/testsource.scala (renamed from test/files/neg/plugin-rightafter-terminal/testsource.scala)0
106 files changed, 1337 insertions, 640 deletions
diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala
index fb90cb9c46..907389b9f0 100644
--- a/src/actors/scala/actors/Actor.scala
+++ b/src/actors/scala/actors/Actor.scala
@@ -646,6 +646,7 @@ trait Actor extends AbstractActor with ReplyReactor with ReplyableActor {
}
// guarded by lock of this
+ // never throws SuspendActorException
private[actors] override def scheduleActor(f: Any =>? Unit, msg: Any) =
if ((f eq null) && (continuation eq null)) {
// do nothing (timeout is handled instead)
@@ -825,6 +826,13 @@ trait Actor extends AbstractActor with ReplyReactor with ReplyableActor {
resumeActor()
else if (waitingFor ne waitingForNone) {
scheduleActor(continuation, null)
+ /* Here we should not throw a SuspendActorException,
+ since the current method is called from an actor that
+ is in the process of exiting.
+
+ Therefore, the contract for scheduleActor is that
+ it never throws a SuspendActorException.
+ */
}
}
}
diff --git a/src/actors/scala/actors/Debug.scala b/src/actors/scala/actors/Debug.scala
index 481b68d7f4..bad19b8aeb 100644
--- a/src/actors/scala/actors/Debug.scala
+++ b/src/actors/scala/actors/Debug.scala
@@ -27,6 +27,15 @@ object Debug {
def error(s: String) =
if (lev > 0) System.err.println("Error: " + s)
+
+ def doInfo(b: => Unit) =
+ if (lev > 2) b
+
+ def doWarning(b: => Unit) =
+ if (lev > 1) b
+
+ def doError(b: => Unit) =
+ if (lev > 0) b
}
class Debug(tag: String) {
diff --git a/src/actors/scala/actors/Reactor.scala b/src/actors/scala/actors/Reactor.scala
index d641f54eb6..8545b92d1e 100644
--- a/src/actors/scala/actors/Reactor.scala
+++ b/src/actors/scala/actors/Reactor.scala
@@ -108,8 +108,17 @@ trait Reactor extends OutputChannel[Any] {
// assert continuation != null
if (onSameThread)
continuation(item._1)
- else
+ else {
scheduleActor(continuation, item._1)
+ /* Here, we throw a SuspendActorException to avoid
+ terminating this actor when the current ReactorTask
+ is finished.
+
+ The SuspendActorException skips the termination code
+ in ReactorTask.
+ */
+ throw Actor.suspendException
+ }
}
def !(msg: Any) {
@@ -149,7 +158,14 @@ trait Reactor extends OutputChannel[Any] {
// keep going
} else {
waitingFor = handlesMessage
- done = true
+ /* Here, we throw a SuspendActorException to avoid
+ terminating this actor when the current ReactorTask
+ is finished.
+
+ The SuspendActorException skips the termination code
+ in ReactorTask.
+ */
+ throw Actor.suspendException
}
}
} else {
@@ -171,6 +187,8 @@ trait Reactor extends OutputChannel[Any] {
* an actors act method.
*
* assume handler != null
+ *
+ * never throws SuspendActorException
*/
private[actors] def scheduleActor(handler: Any =>? Unit, msg: Any) = {
val fun = () => handler(msg)
diff --git a/src/actors/scala/actors/ReactorTask.scala b/src/actors/scala/actors/ReactorTask.scala
index 28e93bbbff..f6ec67e94c 100644
--- a/src/actors/scala/actors/ReactorTask.scala
+++ b/src/actors/scala/actors/ReactorTask.scala
@@ -46,6 +46,7 @@ private[actors] class ReactorTask[T >: Null <: Reactor](var reactor: T, var fun:
case e: Exception =>
Debug.info(reactor+": caught "+e)
+ Debug.doInfo { e.printStackTrace() }
reactor.terminated()
afterExecuting(e)
} finally {
diff --git a/src/actors/scala/actors/ReplyReactor.scala b/src/actors/scala/actors/ReplyReactor.scala
index 4b31369db4..64860f4d38 100644
--- a/src/actors/scala/actors/ReplyReactor.scala
+++ b/src/actors/scala/actors/ReplyReactor.scala
@@ -57,8 +57,11 @@ trait ReplyReactor extends Reactor with ReplyableReactor {
// assert continuation != null
if (onSameThread)
continuation(item._1)
- else
+ else {
scheduleActor(continuation, item._1)
+ // see Reactor.resumeReceiver
+ throw Actor.suspendException
+ }
}
// assume continuation != null
@@ -83,7 +86,8 @@ trait ReplyReactor extends Reactor with ReplyableReactor {
// keep going
} else {
waitingFor = handlesMessage
- done = true
+ // see Reactor.searchMailbox
+ throw Actor.suspendException
}
}
} else {
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index dfa8dcbef4..1128150cb8 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -673,9 +673,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
refreshProgress
}
private def refreshProgress =
- if (fileset.size > 0)
- progress((phasec * fileset.size) + unitc,
- (phaseDescriptors.length-1) * fileset.size) // terminal phase not part of the progress display
+ if (compiledFiles.size > 0)
+ progress((phasec * compiledFiles.size) + unitc,
+ (phaseDescriptors.length-1) * compiledFiles.size) // terminal phase not part of the progress display
// ----- finding phases --------------------------------------------
@@ -704,12 +704,12 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
// ----------- Units and top-level classes and objects --------
private var unitbuf = new ListBuffer[CompilationUnit]
- private var fileset = new HashSet[AbstractFile]
+ var compiledFiles = new HashSet[AbstractFile]
/** add unit to be compiled in this run */
private def addUnit(unit: CompilationUnit) {
unitbuf += unit
- fileset += unit.source.file
+ compiledFiles += unit.source.file
}
/* An iterator returning all the units being compiled in this run */
@@ -847,12 +847,12 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
* to phase "namer".
*/
def compileLate(file: AbstractFile) {
- if (fileset eq null) {
+ if (compiledFiles eq null) {
val msg = "No class file for " + file +
" was found\n(This file cannot be loaded as a source file)"
inform(msg)
throw new FatalError(msg)
- } else if (!(fileset contains file)) {
+ } else if (!(compiledFiles contains file)) {
compileLate(new CompilationUnit(getSourceFile(file)))
}
}
@@ -863,7 +863,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def compileLate(unit: CompilationUnit) {
addUnit(unit)
var localPhase = firstPhase.asInstanceOf[GlobalPhase]
- while (localPhase != null && (localPhase.id < globalPhase.id || localPhase.id <= namerPhase.id)/* && !reporter.hasErrors*/) {
+ while (localPhase != null && (localPhase.id < globalPhase.id || localPhase.id < typerPhase.id)/* && !reporter.hasErrors*/) {
val oldSource = reporter.getSource
reporter.withSource(unit.source) {
atPhase(localPhase)(localPhase.applyPhase(unit))
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala
index 315d94d7d4..577439990d 100644
--- a/src/compiler/scala/tools/nsc/Main.scala
+++ b/src/compiler/scala/tools/nsc/Main.scala
@@ -40,6 +40,7 @@ object Main extends AnyRef with EvalLoop {
loop { line =>
val args = line.split(' ').toList
val command = new CompilerCommand(args, new Settings(error), error, true)
+ compiler.reporter.reset
new compiler.Run() compile command.files
}
}
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 23ceb37c95..b039a9e90d 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -372,6 +372,37 @@ object Settings {
}
}
}
+
+ /** Return the source file path(s) which correspond to the given
+ * classfile path and SourceFile attribute value, subject to the
+ * condition that source files are arranged in the filesystem
+ * according to Java package layout conventions.
+ *
+ * The given classfile path must be contained in at least one of
+ * the specified output directories. If it does not then this
+ * method returns Nil.
+ *
+ * Note that the source file is not required to exist, so assuming
+ * a valid classfile path this method will always return a list
+ * containing at least one element.
+ *
+ * Also that if two or more source path elements target the same
+ * output directory there will be two or more candidate source file
+ * paths.
+ */
+ def srcFilesFor(classFile : AbstractFile, srcPath : String) : List[AbstractFile] = {
+ def isBelow(srcDir: AbstractFile, outDir: AbstractFile) =
+ classFile.path.startsWith(outDir.path)
+
+ singleOutDir match {
+ case Some(d) => Nil
+ case None =>
+ (outputs filter (isBelow _).tuple) match {
+ case Nil => Nil
+ case matches => matches.map(_._1.lookupPath(srcPath, false))
+ }
+ }
+ }
}
// The Setting companion object holds all the factory methods
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 9adad689f1..c4c9af5294 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -102,9 +102,8 @@ trait Trees {
//def kindingIrrelevant(tp: Type) = (tp eq null) || phase.name == "erasure" || phase.erasedTypes
abstract class Tree extends Product {
- {
- import util.Statistics
- if (Statistics.enabled) nodeCount += 1
+ if (util.Statistics.enabled) {
+ util.Statistics.nodeByType(getClass) += 1
}
val id = nodeCount
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index a8118242df..a89f4f01c3 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2165,6 +2165,7 @@ self =>
atPos(accept(THIS)) {
newLineOptWhenFollowedBy(LBRACE)
var t = Apply(Ident(nme.CONSTRUCTOR), argumentExprs())
+ newLineOptWhenFollowedBy(LBRACE)
while (in.token == LPAREN || in.token == LBRACE) {
t = Apply(t, argumentExprs())
newLineOptWhenFollowedBy(LBRACE)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index a9a3ded6b4..be90a835f5 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -332,7 +332,7 @@ trait Scanners {
nextChar()
if (isIdentifierStart(ch))
charLitOr(getIdentRest)
- else if (isSpecial(ch))
+ else if (isOperatorPart(ch) && (ch != '\\'))
charLitOr(getOperatorRest)
else {
getLitChar()
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 4e6507f9e3..cd690097e8 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1621,8 +1621,9 @@ abstract class GenICode extends SubComponent {
override def equals(other: Any) = f == other;
}
- def duplicateFinalizer(ctx: Context, finalizer: Tree) =
- (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer)
+ def duplicateFinalizer(boundLabels: collection.Set[Symbol], targetCtx: Context, finalizer: Tree) = {
+ (new DuplicateLabels(boundLabels))(targetCtx, finalizer)
+ }
/**
* The Context class keeps information relative to the current state
@@ -1863,6 +1864,10 @@ abstract class GenICode extends SubComponent {
var tmp: Local = null
val kind = toTypeKind(tree.tpe)
val guardResult = kind != UNIT && mayCleanStack(finalizer)
+ // we need to save bound labels before any code generation is performed on
+ // the current context (otherwise, any new lables in the finalizer that need to
+ // be duplicated would be incorrectly considered bound -- see #2850).
+ val boundLabels: collection.Set[Symbol] = Set.empty ++ labels.keySet
if (guardResult) {
tmp = this.makeLocal(tree.pos, tree.tpe, "tmp")
@@ -1875,11 +1880,11 @@ abstract class GenICode extends SubComponent {
if (guardResult) {
ctx1.bb.emit(STORE_LOCAL(tmp))
- val ctx2 = genLoad(duplicateFinalizer(ctx1, finalizer), ctx1, UNIT)
+ val ctx2 = genLoad(duplicateFinalizer(boundLabels, ctx1, finalizer), ctx1, UNIT)
ctx2.bb.emit(LOAD_LOCAL(tmp))
ctx2
} else
- genLoad(duplicateFinalizer(ctx1, finalizer), ctx1, UNIT)
+ genLoad(duplicateFinalizer(boundLabels, ctx1, finalizer), ctx1, UNIT)
} else ctx
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 8e77c493dd..4c9a996cec 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -278,10 +278,13 @@ abstract class Inliners extends SubComponent {
assert(pending.isEmpty, "Pending NEW elements: " + pending)
}
+ /** The current iclass */
+ private var currentIClazz: IClass = _
+
def analyzeClass(cls: IClass): Unit = if (settings.inline.value) {
if (settings.debug.value)
log("Analyzing " + cls);
-
+ this.currentIClazz = cls
cls.methods filterNot (_.symbol.isConstructor) foreach analyzeMethod
}
@@ -311,6 +314,12 @@ abstract class Inliners extends SubComponent {
if (!retry) {
i match {
case CALL_METHOD(msym, Dynamic) =>
+ def warnNoInline(reason: String) = {
+ if (msym.hasAnnotation(ScalaInlineAttr))
+ currentIClazz.cunit.warning(i.pos,
+ "Could not inline required method %s because %s.".format(msym.originalName.decode, reason))
+ }
+
val receiver = info.stack.types.drop(msym.info.paramTypes.length).head match {
case REFERENCE(s) => s;
case _ => NoSymbol;
@@ -361,12 +370,18 @@ abstract class Inliners extends SubComponent {
+ "\n\tinc.code ne null: " + (inc.code ne null) + (if (inc.code ne null)
"\n\tisSafeToInline(m, inc, info.stack): " + isSafeToInline(m, inc, info.stack)
+ "\n\tshouldInline heuristics: " + shouldInline(m, inc) else ""));
+ warnNoInline(
+ if (inc.code eq null) "bytecode was unavailable"
+ else if (!isSafeToInline(m, inc, info.stack)) "it is unsafe (target may reference private fields)"
+ else "a bug (run with -Ylog:inline -Ydebug for more information)")
}
case None =>
+ warnNoInline("bytecode was not available")
if (settings.debug.value)
log("could not find icode\n\treceiver: " + receiver + "\n\tmethod: " + concreteMethod)
}
- }
+ } else
+ warnNoInline(if (icodes.available(receiver)) "it is not final" else "bytecode was not available")
case _ => ();
}
@@ -375,14 +390,6 @@ abstract class Inliners extends SubComponent {
if (tfa.stat) log(m.symbol.fullNameString + " iterations: " + tfa.iterations + " (size: " + m.code.blocks.length + ")")
}} while (retry && count < 15)
m.normalize
-// } catch {
-// case e =>
-// Console.println("############# Caught exception: " + e + " #################");
-// Console.println("\nMethod: " + m +
-// "\nMethod owner: " + m.symbol.owner);
-// e.printStackTrace();
-// m.dump
-// throw e
}
diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala
index a7953dfb9f..87e38d8909 100644
--- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala
@@ -21,7 +21,8 @@ abstract class Changes {
/** Are the new modifiers more restrictive than the old ones? */
private def moreRestrictive(from: Long, to: Long): Boolean =
((((to & PRIVATE) != 0L) && (from & PRIVATE) == 0L)
- || (((to & PROTECTED) != 0L) && (from & PROTECTED) == 0L))
+ || (((to & PROTECTED) != 0L) && (from & PROTECTED) == 0L)) ||
+ ((from & IMPLICIT) != (to & IMPLICIT))
/** An entity in source code, either a class or a member definition.
* Name is fully-qualified.
@@ -38,6 +39,8 @@ abstract class Changes {
private def sameSymbol(sym1: Symbol, sym2: Symbol): Boolean =
sym1.fullNameString == sym2.fullNameString
+ private def sameFlags(sym1: Symbol, sym2: Symbol): Boolean =
+ sym1.flags == sym2.flags
private def sameType(tp1: Type, tp2: Type) = {
def typeOf(tp: Type): String = tp.toString + "[" + tp.getClass + "]"
@@ -88,9 +91,10 @@ abstract class Changes {
case (MethodType(params1, res1), MethodType(params2, res2)) =>
// new dependent types: probably fix this, use substSym as done for PolyType
(sameTypes(tp1.paramTypes, tp2.paramTypes) &&
- ((tp1.params, tp2.params).zipped forall sameSymbol) &&
- sameType(res1, res2) &&
- tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType])
+ ((tp1.params, tp2.params).zipped forall ((t1, t2) =>
+ (sameSymbol(t1, t1) && sameFlags(t1, t2)))) &&
+ sameType(res1, res2) &&
+ tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType])
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
sameTypeParams(tparams1, tparams2) && sameType(res1, res2)
@@ -141,7 +145,7 @@ abstract class Changes {
// println("changeSet " + from + "(" + from.info + ")"
// + " vs " + to + "(" + to.info + ")")
- def omitSymbols(s: Symbol): Boolean = !s.hasFlag(Flags.LOCAL | Flags.LIFTED | Flags.PRIVATE)
+ def omitSymbols(s: Symbol): Boolean = !s.hasFlag(LOCAL | LIFTED | PRIVATE)
val cs = new mutable.ListBuffer[Change]
if ((from.info.parents zip to.info.parents) exists { case (t1, t2) => !sameType(t1, t2) })
diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
index 32d94d9ee9..5ce0cfdb1c 100644
--- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
@@ -149,18 +149,52 @@ trait DependencyAnalysis extends SubComponent with Files {
&& (!tree.symbol.isPackage)
&& (!tree.symbol.hasFlag(Flags.JAVA))
&& ((tree.symbol.sourceFile eq null)
- || (tree.symbol.sourceFile.path != file.path))) {
- references += file -> (references(file) + tree.symbol.fullNameString)
+ || (tree.symbol.sourceFile.path != file.path))
+ && (!tree.symbol.isClassConstructor)) {
+ updateReferences(tree.symbol.fullNameString)
}
+
tree match {
case cdef: ClassDef if !cdef.symbol.hasFlag(Flags.PACKAGE) =>
buf += cdef.symbol
+ atPhase(currentRun.erasurePhase.prev) {
+ for (s <- cdef.symbol.info.decls)
+ s match {
+ case ts: TypeSymbol if !ts.isClass =>
+ checkType(s.tpe)
+ case _ =>
+ }
+ }
super.traverse(tree)
- case _ =>
+ case ddef: DefDef =>
+ atPhase(currentRun.typerPhase.prev) {
+ checkType(ddef.symbol.tpe)
+ }
+ super.traverse(tree)
+
+ case _ =>
super.traverse(tree)
}
}
+
+ def checkType(tpe: Type): Unit =
+ tpe match {
+ case t: MethodType =>
+ checkType(t.resultType)
+ for (s <- t.params) checkType(s.tpe)
+
+ case t: TypeRef =>
+ updateReferences(t.typeSymbol.fullNameString)
+ for (tp <- t.args) checkType(tp)
+
+ case t =>
+ updateReferences(t.typeSymbol.fullNameString)
+ }
+
+ def updateReferences(s: String): Unit =
+ references += file -> (references(file) + s)
+
}).apply(unit.body)
definitions(unit.source.file) = buf.toList
diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
index b445ec245e..5414b53e0c 100644
--- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
@@ -40,13 +40,15 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
protected def newCompiler(settings: Settings) = new BuilderGlobal(settings)
val compiler = newCompiler(settings)
- import compiler.Symbol
+ import compiler.{Symbol, atPhase, currentRun}
+
+ private case class Symbols(sym: Symbol, symBefErasure: Symbol)
/** Managed source files. */
private val sources: mutable.Set[AbstractFile] = new mutable.HashSet[AbstractFile]
- private val definitions: mutable.Map[AbstractFile, List[Symbol]] =
- new mutable.HashMap[AbstractFile, List[Symbol]] {
+ private val definitions: mutable.Map[AbstractFile, List[Symbols]] =
+ new mutable.HashMap[AbstractFile, List[Symbols]] {
override def default(key: AbstractFile) = Nil
}
@@ -70,7 +72,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
*/
private def invalidatedByRemove(files: Set[AbstractFile]): Set[AbstractFile] = {
val changes = new mutable.HashMap[Symbol, List[Change]]
- for (f <- files; sym <- definitions(f))
+ for (f <- files; Symbols(sym, _) <- definitions(f))
changes += sym -> List(Removed(Class(sym.fullNameString)))
invalidated(files, changes)
}
@@ -121,10 +123,16 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
val syms = defs(src)
for (sym <- syms) {
definitions(src).find(
- s => (s.fullNameString == sym.fullNameString) &&
- isCorrespondingSym(s, sym)) match {
- case Some(oldSym) =>
- changesOf(oldSym) = changeSet(oldSym, sym)
+ s => (s.sym.fullNameString == sym.fullNameString) &&
+ isCorrespondingSym(s.sym, sym)) match {
+ case Some(Symbols(oldSym, oldSymEras)) =>
+ val changes = changeSet(oldSym, sym)
+ val changesErasure =
+ atPhase(currentRun.erasurePhase.prev) {
+ changeSet(oldSymEras, sym)
+ }
+
+ changesOf(oldSym) = (changes ++ changesErasure).removeDuplicates
case _ =>
// a new top level definition
changesOf(sym) =
@@ -134,10 +142,10 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
}
}
// Create a change for the top level classes that were removed
- val removed = definitions(src) filterNot ((s: Symbol) =>
- syms.find(_.fullNameString == s.fullNameString) != None)
- for (sym <- removed) {
- changesOf(sym) = List(removeChangeSet(sym))
+ val removed = definitions(src) filterNot ((s:Symbols) =>
+ syms.find(_.fullNameString == (s.sym.fullNameString)) != None)
+ for (s <- removed) {
+ changesOf(s.sym) = List(removeChangeSet(s.sym))
}
}
}
@@ -192,8 +200,8 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
println("invalidate " + file + " because " + reason + " [" + change + "]")
buf += file
directDeps -= file
- for (sym <- definitions(file)) // fixes #2557
- newChangesOf(sym) = List(change)
+ for (syms <- definitions(file)) // fixes #2557
+ newChangesOf(syms.sym) = List(change)
break
}
@@ -255,8 +263,8 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
for (file <- directDeps) {
breakable {
- for (cls <- definitions(file)) checkParents(cls, file)
- for (cls <- definitions(file)) checkInterface(cls, file)
+ for (cls <- definitions(file)) checkParents(cls.sym, file)
+ for (cls <- definitions(file)) checkInterface(cls.sym, file)
checkReferences(file)
}
}
@@ -270,7 +278,9 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
/** Update the map of definitions per source file */
private def updateDefinitions(files: Set[AbstractFile]) {
for (src <- files; val localDefs = compiler.dependencyAnalysis.definitions(src)) {
- definitions(src) = (localDefs map (_.cloneSymbol))
+ definitions(src) = (localDefs map (s => {
+ Symbols(s.cloneSymbol, atPhase(currentRun.erasurePhase.prev) {s.cloneSymbol})
+ }))
}
this.references = compiler.dependencyAnalysis.references
}
diff --git a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
index 8fc01a91fb..c83138e9bc 100644
--- a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
@@ -9,6 +9,7 @@ package symtab
import scala.collection.mutable.ListBuffer
import scala.collection.immutable.Map
import math.max
+import util.Statistics._
/** A base type sequence (BaseTypeSeq) is an ordered sequence spanning all the base types
* of a type. It characterized by the following two laws:
@@ -32,6 +33,9 @@ trait BaseTypeSeqs {
class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
self =>
+ incCounter(baseTypeSeqCount)
+ incCounter(baseTypeSeqLenTotal, elems.length)
+
/** The number of types in the sequence */
def length: Int = elems.length
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 7e4693c7a1..3daa4e8ac2 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -18,6 +18,8 @@ import scala.tools.nsc.util.{Position, NoPosition, ClassPath, ClassRep, JavaClas
import classfile.ClassfileParser
import Flags._
+import util.Statistics._
+
/** This class ...
*
* @author Martin Odersky
@@ -243,11 +245,18 @@ abstract class SymbolLoaders {
protected def description = "class file "+ classfile.toString
protected def doComplete(root: Symbol) {
+ val start = startTimer(classReadNanos)
classfileParser.parse(classfile, root)
+ stopTimer(classReadNanos, start)
}
+ override protected def sourcefile = classfileParser.srcfile
}
class MSILTypeLoader(typ: MSILType) extends SymbolLoader {
+ private object typeParser extends clr.TypeParser {
+ val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
+ }
+
protected def description = "MSILType "+ typ.FullName + ", assembly "+ typ.Assembly.FullName
protected def doComplete(root: Symbol) { typeParser.parse(typ, root) }
}
@@ -263,10 +272,6 @@ abstract class SymbolLoaders {
protected def doComplete(root: Symbol) { root.sourceModule.initialize }
}
- private object typeParser extends clr.TypeParser {
- val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
- }
-
object clrTypes extends clr.CLRTypes {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
if (global.forMSIL) init()
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 91f26b1810..9f22bc54f7 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -10,8 +10,9 @@ package symtab
import scala.collection.mutable.ListBuffer
import scala.collection.immutable.Map
-import scala.tools.nsc.io.AbstractFile
-import scala.tools.nsc.util.{Position, NoPosition, BatchSourceFile}
+import io.AbstractFile
+import util.{Position, NoPosition, BatchSourceFile}
+import util.Statistics._
import Flags._
//todo: get rid of MONOMORPHIC flag
@@ -21,11 +22,7 @@ trait Symbols {
import definitions._
private var ids = 0
-
- //for statistics:
- def symbolCount = ids
- var typeSymbolCount = 0
- var classSymbolCount = 0
+ def symbolCount = ids // statistics
val emptySymbolArray = new Array[Symbol](0)
val emptySymbolSet = Set.empty[Symbol]
@@ -1872,7 +1869,7 @@ trait Symbols {
def cloneSymbolImpl(owner: Symbol): Symbol =
new TypeSymbol(owner, pos, name)
- if (util.Statistics.enabled) typeSymbolCount = typeSymbolCount + 1
+ incCounter(typeSymbolCount)
}
/** A class for type parameters viewed from inside their scopes
@@ -2009,7 +2006,7 @@ trait Symbols {
override def children: Set[Symbol] = childSet
override def addChild(sym: Symbol) { childSet = childSet + sym }
- if (util.Statistics.enabled) classSymbolCount = classSymbolCount + 1
+ incCounter(classSymbolCount)
}
/** A class for module class symbols
@@ -2025,6 +2022,7 @@ trait Symbols {
setSourceModule(module)
}
override def sourceModule = module
+ lazy val implicitMembers = info.implicitMembers
def setSourceModule(module: Symbol) { this.module = module }
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index d87a30f847..be537010f6 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -9,10 +9,12 @@ package symtab
import scala.collection.immutable
import scala.collection.mutable.{ListBuffer, HashMap, WeakHashMap}
-import scala.tools.nsc.ast.TreeGen
-import scala.tools.nsc.util.{HashSet, Position, NoPosition}
+import ast.TreeGen
+import util.{HashSet, Position, NoPosition}
+import util.Statistics._
import Flags._
+
/* A standard type pattern match:
case ErrorType =>
// internal: error
@@ -64,16 +66,7 @@ trait Types {
//statistics
- var singletonBaseTypeSeqCount = 0
- var compoundBaseTypeSeqCount = 0
- var typerefBaseTypeSeqCount = 0
- var findMemberCount = 0
- var noMemberCount = 0
- var multMemberCount = 0
- var findMemberNanos = 0l
- var subtypeCount = 0
- var sametypeCount = 0
- var subtypeNanos = 0l
+ def uniqueTypeCount = if (uniques == null) 0 else uniques.size
private var explainSwitch = false
@@ -499,9 +492,13 @@ trait Types {
*/
def asSeenFrom(pre: Type, clazz: Symbol): Type =
if (!isTrivial && (!phase.erasedTypes || pre.typeSymbol == ArrayClass)) {
+ incCounter(asSeenFromCount)
+ val start = startTimer(asSeenFromNanos)
val m = new AsSeenFromMap(pre.normalize, clazz)
val tp = m apply this
- existentialAbstraction(m.capturedParams, tp)
+ val result = existentialAbstraction(m.capturedParams, tp)
+ stopTimer(asSeenFromNanos, start)
+ result
} else this
/** The info of `sym', seen as a member of this type.
@@ -597,31 +594,36 @@ trait Types {
/** Is this type a subtype of that type? */
def <:<(that: Type): Boolean = {
-// val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l
-// val result =
- ((this eq that) ||
- (if (explainSwitch) explain("<:", isSubType, this, that)
- else isSubType(this, that, AnyDepth)))
-// if (util.Statistics.enabled) {
-// subtypeNanos += System.nanoTime() - startTime
-// subtypeCount += 1
-// }
-// result
+ if (util.Statistics.enabled) stat_<:<(that)
+ else
+ (this eq that) ||
+ (if (explainSwitch) explain("<:", isSubType, this, that)
+ else isSubType(this, that, AnyDepth))
+ }
+
+ def stat_<:<(that: Type): Boolean = {
+ incCounter(subtypeCount)
+ val start = startTimer(subtypeNanos)
+ val result =
+ (this eq that) ||
+ (if (explainSwitch) explain("<:", isSubType, this, that)
+ else isSubType(this, that, AnyDepth))
+ stopTimer(subtypeNanos, start)
+ result
}
/** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
*/
- def weak_<:<(that: Type): Boolean =
-// val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l
-// val result =
+ def weak_<:<(that: Type): Boolean = {
+ incCounter(subtypeCount)
+ val start = startTimer(subtypeNanos)
+ val result =
((this eq that) ||
(if (explainSwitch) explain("weak_<:", isWeakSubType, this, that)
else isWeakSubType(this, that)))
-// if (util.Statistics.enabled) {
-// subtypeNanos += System.nanoTime() - startTime
-// subtypeCount += 1
-// }
-// result
+ stopTimer(subtypeNanos, start)
+ result
+ }
/** Is this type equivalent to that type? */
def =:=(that: Type): Boolean = (
@@ -785,15 +787,17 @@ trait Types {
// See (t0851) for a situation where this happens.
if (!this.isGround)
return typeVarToOriginMap(this).findMember(name, excludedFlags, requiredFlags, stableOnly)
- if (util.Statistics.enabled) findMemberCount += 1
-// val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l
+
+ incCounter(findMemberCount)
+ val start = startTimer(findMemberNanos)
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
var members: Scope = null
var member: Symbol = NoSymbol
var excluded = excludedFlags | DEFERRED
- var self: Type = null
var continue = true
+ lazy val self: Type = this.narrow
+ lazy val membertpe = self.memberType(member)
while (continue) {
continue = false
val bcs0 = baseClasses
@@ -812,29 +816,27 @@ trait Types {
sym.getFlag(PRIVATE | LOCAL) != (PRIVATE | LOCAL).toLong ||
(bcs0.head.hasTransOwner(bcs.head)))) {
if (name.isTypeName || stableOnly && sym.isStable) {
-// if (util.Statistics.enabled) findMemberNanos += System.nanoTime() - startTime
+ stopTimer(findMemberNanos, start)
return sym
} else if (member == NoSymbol) {
member = sym
} else if (members eq null) {
+// val start = startTimer(timer1)
if (member.name != sym.name ||
!(member == sym ||
member.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow;
- (self.memberType(member) matches self.memberType(sym))
- })) {
+ !sym.hasFlag(PRIVATE) &&
+ (membertpe matches self.memberType(sym)))) {
members = new Scope(List(member, sym))
}
+// stopTimer(timer1, start)
} else {
var prevEntry = members.lookupEntry(sym.name)
while ((prevEntry ne null) &&
!(prevEntry.sym == sym ||
prevEntry.sym.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow;
- (self.memberType(prevEntry.sym) matches self.memberType(sym))
- })) {
+ !sym.hasFlag(PRIVATE) &&
+ (self.memberType(prevEntry.sym) matches self.memberType(sym)))) {
prevEntry = members lookupNextEntry prevEntry
}
if (prevEntry eq null) {
@@ -852,14 +854,13 @@ trait Types {
} // while (!bcs.isEmpty)
excluded = excludedFlags
} // while (continue)
-// if (util.Statistics.enabled) findMemberNanos += System.nanoTime() - startTime
+ stopTimer(findMemberNanos, start)
if (members eq null) {
- if (util.Statistics.enabled) if (member == NoSymbol) noMemberCount += 1;
+ if (member == NoSymbol) incCounter(noMemberCount)
member
} else {
- if (util.Statistics.enabled) multMemberCount += 1;
- //val pre = if (this.typeSymbol.isClass) this.typeSymbol.thisType else this;
- (baseClasses.head.newOverloaded(this, members.toList))
+ incCounter(multMemberCount)
+ baseClasses.head.newOverloaded(this, members.toList)
}
}
@@ -970,7 +971,7 @@ trait Types {
override def isVolatile = underlying.isVolatile
override def widen: Type = underlying.widen
override def baseTypeSeq: BaseTypeSeq = {
- if (util.Statistics.enabled) singletonBaseTypeSeqCount += 1
+ incCounter(singletonBaseTypeSeqCount)
underlying.baseTypeSeq prepend this
}
override def safeToString: String = prefixString + "type"
@@ -1179,8 +1180,7 @@ trait Types {
val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq
baseTypeSeqCache = bts lateMap paramToVar
} else {
- if (util.Statistics.enabled)
- compoundBaseTypeSeqCount += 1
+ incCounter(compoundBaseTypeSeqCount)
baseTypeSeqCache = undetBaseTypeSeq
baseTypeSeqCache = memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe)
}
@@ -1711,13 +1711,11 @@ A type's typeSymbol should never be inspected directly.
if (period != currentPeriod) {
baseTypeSeqPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- if (util.Statistics.enabled)
- typerefBaseTypeSeqCount += 1
+ incCounter(typerefBaseTypeSeqCount)
baseTypeSeqCache = undetBaseTypeSeq
baseTypeSeqCache =
if (sym.isAbstractType) transform(bounds.hi).baseTypeSeq prepend this
else sym.info.baseTypeSeq map transform
-
}
}
if (baseTypeSeqCache == undetBaseTypeSeq)
@@ -1796,7 +1794,7 @@ A type's typeSymbol should never be inspected directly.
case class MethodType(override val params: List[Symbol],
override val resultType: Type) extends Type {
override val isTrivial: Boolean =
- paramTypes.forall(_.isTrivial) && resultType.isTrivial
+ params.forall(_.tpe.isTrivial) && resultType.isTrivial
//assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
override def paramSectionCount: Int = resultType.paramSectionCount + 1
@@ -1910,6 +1908,10 @@ A type's typeSymbol should never be inspected directly.
override def boundSyms: List[Symbol] = quantified
override def prefix = maybeRewrap(underlying.prefix)
override def typeArgs = underlying.typeArgs map maybeRewrap
+ override def params = underlying.params mapConserve { param =>
+ val tpe1 = rewrap(param.tpe)
+ if (tpe1 eq param.tpe) param else param.cloneSymbol.setInfo(tpe1)
+ }
override def paramTypes = underlying.paramTypes map maybeRewrap
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
// maybeRewrap(underlying.instantiateTypeParams(formals, actuals))
@@ -2642,9 +2644,8 @@ A type's typeSymbol should never be inspected directly.
private var uniques: HashSet[AnyRef] = _
private var uniqueRunId = NoRunId
- def uniqueTypeCount = if (uniques == null) 0 else uniques.size // for statistics
-
private def unique[T <: AnyRef](tp: T): T = {
+ incCounter(rawTypeCount)
if (uniqueRunId != currentRunId) {
uniques = new HashSet("uniques", initialUniquesCapacity)
uniqueRunId = currentRunId
@@ -3531,6 +3532,7 @@ A type's typeSymbol should never be inspected directly.
class MissingAliasException extends Exception
val missingAliasException = new MissingAliasException
+ class MissingTypeException extends Exception
object adaptToNewRunMap extends TypeMap {
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
@@ -3542,7 +3544,8 @@ A type's typeSymbol should never be inspected directly.
var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
if (rebind0 == NoSymbol) {
if (sym.isAliasType) throw missingAliasException
- assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
+ throw new MissingTypeException // For build manager purposes
+ //assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
}
/** The two symbols have the same fully qualified name */
def corresponds(sym1: Symbol, sym2: Symbol): Boolean =
@@ -3588,6 +3591,8 @@ A type's typeSymbol should never be inspected directly.
} catch {
case ex: MissingAliasException =>
apply(tp.dealias)
+ case _: MissingTypeException =>
+ NoType
}
}
case MethodType(params, restp) =>
@@ -3757,7 +3762,7 @@ A type's typeSymbol should never be inspected directly.
/** Do `tp1' and `tp2' denote equivalent types?
*/
def isSameType(tp1: Type, tp2: Type): Boolean = try {
- sametypeCount += 1
+ incCounter(sametypeCount)
subsametypeRecursions += 1
undoLog undoUnless {
isSameType0(tp1, tp2)
@@ -4149,7 +4154,7 @@ A type's typeSymbol should never be inspected directly.
tp1 match {
case MethodType(params1, res1) =>
(params1.length == params2.length &&
- matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
(res1 <:< res2) &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType])
case _ =>
@@ -4242,13 +4247,71 @@ A type's typeSymbol should never be inspected directly.
}
/** A function implementing `tp1' matches `tp2' */
- def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
+ final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
+ def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean =
+ tparams1.length == tparams2.length &&
+ matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
+ def lastTry =
+ tp2 match {
+ case ExistentialType(_, res2) if alwaysMatchSimple =>
+ matchesType(tp1, res2, true)
+ case MethodType(_, _) =>
+ false
+ case PolyType(tparams2, res2) =>
+ tparams2.isEmpty && matchesType(tp1, res2, alwaysMatchSimple)
+ case _ =>
+ alwaysMatchSimple || tp1 =:= tp2
+ }
+ tp1 match {
+ case MethodType(params1, res1) =>
+ tp2 match {
+ case MethodType(params2, res2) =>
+ params1.length == params2.length && // useful pre-secreening optimization
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ matchesType(res1, res2, alwaysMatchSimple) &&
+ tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
+ case PolyType(List(), res2) =>
+ if (params1.isEmpty) matchesType(res1, res2, alwaysMatchSimple)
+ else matchesType(tp1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ false
+ }
+ case PolyType(tparams1, res1) =>
+ tp2 match {
+ case PolyType(tparams2, res2) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case MethodType(List(), res2) if (tparams1.isEmpty) =>
+ matchesType(res1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ tparams1.isEmpty && matchesType(res1, tp2, alwaysMatchSimple)
+ }
+ case ExistentialType(tparams1, res1) =>
+ tp2 match {
+ case ExistentialType(tparams2, res2) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case _ =>
+ if (alwaysMatchSimple) matchesType(res1, tp2, true)
+ else lastTry
+ }
+ case _ =>
+ lastTry
+ }
+ }
+
+/** matchesType above is an optimized version of the following implementation:
+
+ def matchesType2(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean =
tparams1.length == tparams2.length &&
matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
(tp1, tp2) match {
case (MethodType(params1, res1), MethodType(params2, res2)) =>
- matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ params1.length == params2.length && // useful pre-secreening optimization
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
matchesType(res1, res2, alwaysMatchSimple) &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
@@ -4275,14 +4338,25 @@ A type's typeSymbol should never be inspected directly.
alwaysMatchSimple || tp1 =:= tp2
}
}
+*/
- /** Are `tps1' and `tps2' lists of pairwise equivalent types? */
- private def matchingParams(tps1: List[Type], tps2: List[Type], tps1isJava: Boolean, tps2isJava: Boolean): Boolean =
- (tps1.length == tps2.length) &&
- ((tps1, tps2).zipped forall ((tp1, tp2) =>
- (tp1 =:= tp2) ||
- tps1isJava && tp2.typeSymbol == ObjectClass && tp1.typeSymbol == AnyClass ||
- tps2isJava && tp1.typeSymbol == ObjectClass && tp2.typeSymbol == AnyClass))
+ /** Are `syms1' and `syms2' parameter lists with pairwise equivalent types? */
+ private def matchingParams(syms1: List[Symbol], syms2: List[Symbol], syms1isJava: Boolean, syms2isJava: Boolean): Boolean = syms1 match {
+ case Nil =>
+ syms2.isEmpty
+ case sym1 :: rest1 =>
+ syms2 match {
+ case Nil =>
+ false
+ case sym2 :: rest2 =>
+ val tp1 = sym1.tpe
+ val tp2 = sym2.tpe
+ (tp1 =:= tp2 ||
+ syms1isJava && tp2.typeSymbol == ObjectClass && tp1.typeSymbol == AnyClass ||
+ syms2isJava && tp1.typeSymbol == ObjectClass && tp2.typeSymbol == AnyClass) &&
+ matchingParams(rest1, rest2, syms1isJava, syms2isJava)
+ }
+ }
/** like map2, but returns list `xs' itself - instead of a copy - if function
* `f' maps all elements to themselves.
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index da4e0aaa49..5c4679625b 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc
package symtab
package classfile
-import java.io.IOException
+import java.io.{ File, IOException }
import java.lang.Integer.toHexString
import scala.collection.immutable.{Map, ListMap}
@@ -41,6 +41,9 @@ abstract class ClassfileParser {
protected var busy: Option[Symbol] = None // lock to detect recursive reads
private var externalName: Name = _ // JVM name of the current class
protected var classTParams = Map[Name,Symbol]()
+ protected var srcfile0 : Option[AbstractFile] = None
+
+ def srcfile = srcfile0
private object metaParser extends MetaParser {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
@@ -813,6 +816,13 @@ abstract class ClassfileParser {
case nme.ExceptionsATTR if (!isScala) =>
parseExceptions(attrLen)
+ case nme.SourceFileATTR =>
+ val srcfileLeaf = pool.getName(in.nextChar).toString.trim
+ val srcpath = sym.enclosingPackage match {
+ case NoSymbol => srcfileLeaf
+ case pkg => pkg.fullNameString(File.separatorChar)+File.separator+srcfileLeaf
+ }
+ srcfile0 = settings.outputDirs.srcFilesFor(in.file, srcpath).find(_.exists)
case _ =>
in.skip(attrLen)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 1fa81c8776..de9dadbd1f 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -497,7 +497,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
tree
else if (isValueClass(tree.tpe.typeSymbol) && !isValueClass(pt.typeSymbol))
adaptToType(box(tree), pt)
- else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.paramTypes.isEmpty) {
+ else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) {
if (!tree.symbol.isStable) assert(false, "adapt "+tree+":"+tree.tpe+" to "+pt)
adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt)
} else if (pt <:< tree.tpe)
@@ -597,7 +597,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
if (isValueClass(tree.symbol.owner) && !isValueClass(qual1.tpe.typeSymbol))
tree.symbol = NoSymbol
- else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.paramTypes.isEmpty) {
+ else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.params.isEmpty) {
assert(qual1.symbol.isStable, qual1.symbol);
qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
} else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) {
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index b2f9489480..03339163a1 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -94,7 +94,9 @@ abstract class LazyVals extends Transform with ast.TreeDSL {
}
val bmps = bitmaps(methSym) map (ValDef(_, ZERO))
- def isMatch(params: List[Ident]) = (params.tail, methSym.tpe.paramTypes).zipped forall (_.tpe == _)
+
+ // Martin to Iulian: Don't we need to compare lengths here?
+ def isMatch(params: List[Ident]) = (params.tail, methSym.tpe.params).zipped forall (_.tpe == _.tpe)
if (bmps.isEmpty) rhs else rhs match {
case Block(assign, l @ LabelDef(name, params, rhs1))
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 8ea0b69049..fd5dd0f9a3 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -61,7 +61,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
tp match {
case MethodType(params, MethodType(params1, restpe)) =>
apply(MethodType(params ::: params1, restpe))
- case MethodType(formals, ExistentialType(tparams, restpe @ MethodType(_, _))) =>
+ case MethodType(params, ExistentialType(tparams, restpe @ MethodType(_, _))) =>
assert(false, "unexpected curried method types with intervening exitential")
tp0
case mt: ImplicitMethodType =>
@@ -189,8 +189,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
* additional parameter sections of a case class are skipped.
*/
def uncurryTreeType(tp: Type): Type = tp match {
- case MethodType(formals, MethodType(formals1, restpe)) if (inPattern) =>
- uncurryTreeType(MethodType(formals, restpe))
+ case MethodType(params, MethodType(params1, restpe)) if (inPattern) =>
+ uncurryTreeType(MethodType(params, restpe))
case _ =>
uncurry(tp)
}
@@ -451,13 +451,15 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
if (isJava &&
suffix.tpe.typeSymbol == ArrayClass &&
isValueClass(suffix.tpe.typeArgs.head.typeSymbol) &&
- fun.tpe.paramTypes.last.typeSymbol == ArrayClass &&
- fun.tpe.paramTypes.last.typeArgs.head.typeSymbol == ObjectClass)
+ { val lastFormal2 = fun.tpe.params.last.tpe
+ lastFormal2.typeSymbol == ArrayClass &&
+ lastFormal2.typeArgs.head.typeSymbol == ObjectClass
+ })
suffix = localTyper.typedPos(pos) {
gen.mkRuntimeCall("toObjectArray", List(suffix))
}
}
- args.take(formals.length - 1) ::: List(suffix setType formals.last)
+ args.take(formals.length - 1) ::: List(suffix setType lastFormal)
case _ =>
args
}
@@ -591,7 +593,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
transform(treeCopy.Apply(tree, fn, List(liftTree(args.head))))
} else {
withNeedLift(true) {
- val formals = fn.tpe.paramTypes;
+ val formals = fn.tpe.paramTypes
treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals)))
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index ead20f1cb8..519ad1b0bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -7,6 +7,8 @@
package scala.tools.nsc
package typechecker
+import util.Statistics._
+
/** The main attribution phase.
*/
trait Analyzer extends AnyRef
@@ -63,8 +65,6 @@ trait Analyzer extends AnyRef
}
}
- var typerTime = 0L
-
object typerFactory extends SubComponent {
val global: Analyzer.this.global.type = Analyzer.this.global
val phaseName = "typer"
@@ -73,10 +73,9 @@ trait Analyzer extends AnyRef
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
resetTyper()
override def run {
- val start = if (util.Statistics.enabled) System.nanoTime() else 0L
+ val start = startTimer(typerNanos)
currentRun.units foreach applyPhase
- if (util.Statistics.enabled)
- typerTime += System.nanoTime() - start
+ stopTimer(typerNanos, start)
}
def apply(unit: CompilationUnit) {
try {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index eea5be32b7..9657cea101 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -14,6 +14,7 @@ package typechecker
import scala.collection.mutable.{LinkedHashMap, ListBuffer}
import scala.tools.nsc.util.{ HashSet, Position, Set, NoPosition, SourceFile }
import symtab.Flags._
+import util.Statistics._
/** This trait provides methods to find various kinds of implicits.
*
@@ -28,16 +29,6 @@ self: Analyzer =>
def traceImplicits = printTypings
- var implicitTime = 0L
- var inscopeSucceed = 0L
- var inscopeFail = 0L
- var oftypeSucceed = 0L
- var oftypeFail = 0L
- var manifSucceed = 0L
- var manifFail = 0L
- var hits = 0
- var misses = 0
-
/** Search for an implicit value. See the comment on `result` at the end of class `ImplicitSearch`
* for more info how the search is conducted.
* @param tree The tree for which the implicit needs to be inserted.
@@ -52,10 +43,18 @@ self: Analyzer =>
* @return A search result
*/
def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = {
+ val rawTypeStart = startCounter(rawTypeImpl)
+ val findMemberStart = startCounter(findMemberImpl)
+ val subtypeStart = startCounter(subtypeImpl)
+ val start = startTimer(implicitNanos)
if (traceImplicits && !tree.isEmpty && !context.undetparams.isEmpty)
println("typing implicit with undetermined type params: "+context.undetparams+"\n"+tree)
val result = new ImplicitSearch(tree, pt, isView, context.makeImplicit(reportAmbiguous)).bestImplicit
context.undetparams = context.undetparams filterNot (result.subst.from contains _)
+ stopTimer(implicitNanos, start)
+ stopCounter(rawTypeImpl, rawTypeStart)
+ stopCounter(findMemberImpl, findMemberStart)
+ stopCounter(subtypeImpl, subtypeStart)
result
}
@@ -103,9 +102,14 @@ self: Analyzer =>
/** Does type `tp` contain an Error type as parameter or result?
*/
private def containsError(tp: Type): Boolean = tp match {
- case PolyType(tparams, restpe) => containsError(restpe)
- case MethodType(params, restpe) => (params map (_.tpe) exists (_.isError)) || containsError(restpe)
- case _ => tp.isError
+ case PolyType(tparams, restpe) =>
+ containsError(restpe)
+ case MethodType(params, restpe) =>
+ for (p <- params)
+ if (p.tpe.isError) return true
+ containsError(restpe)
+ case _ =>
+ tp.isError
}
def isCyclicOrErroneous = try {
@@ -214,10 +218,12 @@ self: Analyzer =>
/** Is implicit info `info1` better than implicit info `info2`?
*/
- def improves(info1: ImplicitInfo, info2: ImplicitInfo) =
+ def improves(info1: ImplicitInfo, info2: ImplicitInfo) = {
+ incCounter(improvesCount)
(info2 == NoImplicitInfo) ||
(info1 != NoImplicitInfo) &&
isStrictlyMoreSpecific(info1.tpe, info2.tpe, info1.sym, info2.sym)
+ }
/** Map all type params in given list to WildcardType
* @param tp The type in which to do the mapping
@@ -282,7 +288,7 @@ self: Analyzer =>
overlaps(dtor1, dted1) && (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1))
}
- if (util.Statistics.enabled) implcnt += 1
+ incCounter(implicitSearchCount)
/** Issues an error signalling ambiguous implicits */
private def ambiguousImplicitError(info1: ImplicitInfo, info2: ImplicitInfo,
@@ -307,6 +313,12 @@ self: Analyzer =>
/** The type parameters to instantiate */
val undetParams = if (isView) List() else context.outer.undetparams
+ /** Replace undetParams in type `tp` by Any/Nothing, according to variance */
+ def approximate(tp: Type) =
+ tp.instantiateTypeParams(undetParams, undetParams map (_ => WildcardType))
+
+ val wildPt = approximate(pt)
+
/** Try to construct a typed tree from given implicit info with given
* expected type.
* Detect infinite search trees for implicits.
@@ -353,48 +365,56 @@ self: Analyzer =>
case _ => tp.isStable
}
- /** Replace undetParams in type `tp` by Any/Nothing, according to variance */
- def approximate(tp: Type) =
- tp.instantiateTypeParams(undetParams, undetParams map (_ => WildcardType))
-
- /** Instantiated `pt' so that undetermined type parameters are replaced by wildcards
- */
- val wildPt = approximate(pt)
-
/** Does type `tp' match expected type `pt'
* This is the case if either `pt' is a unary function type with a
* HasMethodMatching type as result, and `tp' is a unary function
* or method type whose result type has a method whose name and type
* correspond to the HasMethodMatching type,
* or otherwise if `tp' is compatible with `pt'.
+ * This methid is performance critical: 5-8% of typechecking time.
*/
def matchesPt(tp: Type, pt: Type, undet: List[Symbol]) = {
- isCompatible(tp, pt) ||
- isView && {
+ val start = startTimer(matchesPtNanos)
+ val result = normSubType(tp, pt) || isView && {
pt match {
case Function1(arg, res) =>
- normalize(tp) match {
- case Function1(arg1, res1) =>
- (arg.deconst weak_<:< arg1) && {
- res match {
- case HasMethodMatching(name, argtpes, restpe) =>
- (res1.member(name) filter (m =>
- isApplicableSafe(undet, m.tpe, argtpes, restpe))) != NoSymbol
- case _ =>
- res1 <:< res
- }
- }
- case _ => false
- }
- case _ => false
+ matchesPtView(tp, arg, res, undet)
+ case _ =>
+ false
}
}
+ stopTimer(matchesPtNanos, start)
+ result
}
- //if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesPt(depoly(info.tpe), wildPt, List()))
- if (isPlausiblyCompatible(info.tpe, wildPt) &&
- matchesPt(depoly(info.tpe), wildPt, List()) &&
- isStable(info.pre)) {
+ def matchesPtView(tp: Type, ptarg: Type, ptres: Type, undet: List[Symbol]): Boolean = tp match {
+ case MethodType(params, restpe) =>
+ if (tp.isInstanceOf[ImplicitMethodType]) matchesPtView(restpe, ptarg, ptres, undet)
+ else params.length == 1 && matchesArgRes(params.head.tpe, restpe, ptarg, ptres, undet)
+ case ExistentialType(tparams, qtpe) =>
+ matchesPtView(normalize(tp), ptarg, ptres, undet)
+ case Function1(arg1, res1) =>
+ matchesArgRes(arg1, res1, ptarg, ptres, undet)
+ case _ => false
+ }
+
+ def matchesArgRes(tparg: Type, tpres: Type, ptarg: Type, ptres: Type, undet: List[Symbol]): Boolean =
+ (ptarg weak_<:< tparg) && {
+ ptres match {
+ case HasMethodMatching(name, argtpes, restpe) =>
+ (tpres.member(name) filter (m =>
+ isApplicableSafe(undet, m.tpe, argtpes, restpe))) != NoSymbol
+ case _ =>
+ tpres <:< ptres
+ }
+ }
+
+ incCounter(plausiblyCompatibleImplicits)
+
+ //if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesPt(depoly(info.tpe), wildPt, List())+"/"+info.pre+"/"+isStable(info.pre))
+ if (matchesPt(depoly(info.tpe), wildPt, List()) && isStable(info.pre)) {
+
+ incCounter(matchingImplicits)
val itree = atPos(tree.pos.focus) {
if (info.pre == NoPrefix) Ident(info.name)
@@ -417,6 +437,8 @@ self: Analyzer =>
else
typed1(itree, EXPRmode, wildPt)
+ incCounter(typedImplicits)
+
if (traceImplicits) println("typed implicit "+itree1+":"+itree1.tpe+", pt = "+wildPt)
val itree2 = if (isView) (itree1: @unchecked) match { case Apply(fun, _) => fun }
else adapt(itree1, EXPRmode, wildPt)
@@ -451,6 +473,7 @@ self: Analyzer =>
subst traverse itree2
val result = new SearchResult(itree2, subst)
+ incCounter(foundImplicits)
if (traceImplicits) println("RESULT = "+result)
// println("RESULT = "+itree+"///"+itree1+"///"+itree2)//DEBUG
result
@@ -517,9 +540,19 @@ self: Analyzer =>
isLocal: Boolean,
invalidImplicits: ListBuffer[Symbol]): Map[ImplicitInfo, SearchResult] = {
+ val start = startCounter(subtypeAppInfos)
+
/** A set containing names that are shadowed by implicit infos */
lazy val shadowed = new HashSet[Name]("shadowed", 512)
+ /** Is `sym' the standard conforms method in Predef?
+ * Note: DON't replace this by sym == Predef_conforms, as Predef_conforms is a `def'
+ * which does a member lookup (it can't be a lazy val because we might reload Predef
+ * during resident compilations).
+ */
+ def isConformsMethod(sym: Symbol) =
+ sym.name == nme.conforms && sym.owner == PredefModule.moduleClass
+
/** Try implicit `info` to see whether it is applicable for expected type `pt`.
* This is the case if all of the following holds:
* - the info's type is not erroneous,
@@ -528,18 +561,23 @@ self: Analyzer =>
* - the result of typedImplicit is non-empty.
* @return A search result with an attributed tree containing the implicit if succeeded,
* SearchFailure if not.
+ * @note Extreme hotspot!
*/
- def tryImplicit(info: ImplicitInfo): SearchResult =
+ def tryImplicit(info: ImplicitInfo): SearchResult = {
+ incCounter(triedImplicits)
if (info.isCyclicOrErroneous ||
(isLocal && shadowed.contains(info.name)) ||
- (isView && (info.sym == Predef_identity || info.sym == Predef_conforms)) //@M this condition prevents no-op conversions, which are a problem (besides efficiency),
- // TODO: remove `info.sym == Predef_identity` once we have a new STARR that only has conforms as an implicit
+ (isView && isConformsMethod(info.sym)) ||
+ //@M this condition prevents no-op conversions, which are a problem (besides efficiency),
// one example is removeNames in NamesDefaults, which relies on the type checker failing in case of ambiguity between an assignment/named arg
- ) SearchFailure
- else typedImplicit(info)
+ !isPlausiblyCompatible(info.tpe, wildPt))
+ SearchFailure
+ else
+ typedImplicit(info)
+ }
- def appInfos(is: List[ImplicitInfo]): Map[ImplicitInfo, SearchResult] = {
- var applicable = Map[ImplicitInfo, SearchResult]()
+ def addAppInfos(is: List[ImplicitInfo], m: Map[ImplicitInfo, SearchResult]): Map[ImplicitInfo, SearchResult] = {
+ var applicable = m
for (i <- is)
if (!isValid(i.sym)) invalidImplicits += i.sym
else {
@@ -551,7 +589,11 @@ self: Analyzer =>
applicable
}
- (Map[ImplicitInfo, SearchResult]() /: (iss map appInfos))(_ ++ _)
+ var applicable = Map[ImplicitInfo, SearchResult]()
+ for (is <- iss) applicable = addAppInfos(is, applicable)
+
+ stopCounter(subtypeAppInfos, start)
+ applicable
}
/** Search list of implicit info lists for one matching prototype
@@ -580,6 +622,8 @@ self: Analyzer =>
"\n because it comes after the application point and it lacks an explicit result type")
}
+ val start = startCounter(subtypeImprovCount)
+
/** A candidate for best applicable info wrt `improves` */
val best = (NoImplicitInfo /: applicable.keysIterator) (
(best, alt) => if (improves(alt, best)) alt else best)
@@ -589,67 +633,49 @@ self: Analyzer =>
val competing = applicable.keySet dropWhile (alt => best == alt || improves(best, alt))
if (!competing.isEmpty) ambiguousImplicitError(best, competing.head, "both", "and", "")
- // Also check that applicable infos that did not get selected are not
- // in (a companion object of) a subclass of (a companion object of) the class
- // containing the winning info.
- // (no longer needed; rules have changed)
- /*
- for (alt <- applicable.keySet) {
- if (isProperSubClassOrObject(alt.sym.owner, best.sym.owner)) {
- ambiguousImplicitError(best, alt,
- "most specific definition is:",
- "yet alternative definition ",
- "is defined in a subclass.\n Both definitions ")
- }
- }
- */
+ stopCounter(subtypeImprovCount, start)
applicable(best)
}
} // end searchImplicit
- /** The implicits made available directly by class type `tp`.
- * If `tp` refers to class C, these are all implicit members of the companion object of C.
- */
- private def implicitsOfClass(tp: Type): List[ImplicitInfo] = tp match {
- case TypeRef(pre, clazz, _) =>
- clazz.initialize.linkedClassOfClass.info.members.toList.filter(_.hasFlag(IMPLICIT)) map
- (sym => new ImplicitInfo(sym.name, pre.memberType(clazz.linkedModuleOfClass), sym))
- case _ =>
- List()
- }
-
/** The parts of a type is the smallest set of types that contains
* - the type itself
* - the parts of its immediate components (prefix and argument)
* - the parts of its base types
+ * - for alias types and abstract types, we take instead the parts
+ * - of their upper bounds.
+ * @return For those parts that refer to classes with companion objects that
+ * can be accessed with unambiguous stable prefixes, the implicits infos
+ * which are members of these companion objects.
*/
- private def parts(tp: Type): List[Type] = {
- val partMap = new collection.mutable.LinkedHashMap[Symbol, List[Type]]
- /** Add a new type to partMap, unless a subtype of it with the same
- * type symbol exists already.
- */
- def addType(newtp: Type): Boolean = {
- val tsym = newtp.typeSymbol
- partMap.get(tsym) match {
- case Some(ts) =>
- if (ts exists (_ <:< newtp)) false
- else { partMap.put(tsym, newtp :: ts); true }
- case None =>
- partMap.put(tsym, List(newtp)); true
- }
- }
- /** Enter all parts of `tp` into `partMap`
+ private def companionImplicits(tp: Type): List[List[ImplicitInfo]] = {
+
+ val partMap = new LinkedHashMap[Symbol, Type]
+
+ /** Enter all parts of `tp` into `parts` set.
+ * This method is performance critical: about 2-4% of all type checking is spent here
*/
def getParts(tp: Type) {
tp match {
- case TypeRef(pre, sym, args) if (!sym.isPackageClass) =>
- if (sym.isClass && !sym.isRefinementClass && !sym.isAnonymousClass) {
- if (addType(tp)) {
- for (bc <- sym.ancestors)
- getParts(tp.baseType(bc))
- getParts(pre)
- args foreach getParts
- }
+ case TypeRef(pre, sym, args) =>
+ if (sym.isClass) {
+ if (!((sym.name == nme.REFINE_CLASS_NAME.toTypeName) ||
+ (sym.name startsWith nme.ANON_CLASS_NAME) ||
+ (sym.name == nme.ROOT.toTypeName)))
+ partMap get sym match {
+ case Some(pre1) =>
+ if (!(pre =:= pre1)) partMap(sym) = NoType // ambiguous prefix - ignore implicit members
+ case None =>
+ if (pre.isStable) partMap(sym) = pre
+ val bts = tp.baseTypeSeq
+ var i = 1
+ while (i < bts.length) {
+ getParts(bts(i))
+ i += 1
+ }
+ getParts(pre)
+ args foreach getParts
+ }
} else if (sym.isAliasType) {
getParts(tp.normalize)
} else if (sym.isAbstractType) {
@@ -663,23 +689,29 @@ self: Analyzer =>
for (p <- ps) getParts(p)
case AnnotatedType(_, t, _) =>
getParts(t)
- case ExistentialType(tparams, t) =>
+ case ExistentialType(_, t) =>
+ getParts(t)
+ case PolyType(_, t) =>
getParts(t)
case _ =>
}
}
- /** Gives a list of typerefs with the same type symbol,
- * remove all those that have a prefix which is a supertype
- * of some other elements's prefix.
- */
- def compactify(ts: List[Type]): List[Type] = ts match {
- case List() => ts
- case (t @ TypeRef(pre, _, _)) :: ts1 =>
- if (ts1 exists (_.prefix <:< pre)) compactify(ts1)
- else t :: compactify(ts1 filterNot (pre <:< _.prefix))
- }
+
getParts(tp)
- for ((k, ts) <- partMap.iterator.toList; t <- compactify(ts)) yield t
+ val buf = new ListBuffer[List[ImplicitInfo]]
+ for ((clazz, pre) <- partMap) {
+ if (pre != NoType) {
+ val companion = clazz.linkedModuleOfClass
+ companion.moduleClass match {
+ case mc: ModuleClassSymbol =>
+ buf += (mc.implicitMembers map (im =>
+ new ImplicitInfo(im.name, SingleType(pre, companion), im)))
+ case _ =>
+ }
+ }
+ }
+ //println("companion implicits of "+tp+" = "+buf.toList) // DEBUG
+ buf.toList
}
/** The implicits made available by type `pt`.
@@ -687,32 +719,18 @@ self: Analyzer =>
* such that some part of `tp` has C as one of its superclasses.
*/
private def implicitsOfExpectedType: List[List[ImplicitInfo]] = implicitsCache get pt match {
- case Some(implicitInfoss) => hits += 1; implicitInfoss
- case None => {
- misses += 1
- val implicitInfoss = parts(pt).iterator.map(implicitsOfClass).toList
+ case Some(implicitInfoss) =>
+ incCounter(implicitCacheHits)
+ implicitInfoss
+ case None =>
+ incCounter(implicitCacheMisses)
+ val start = startTimer(subtypeETNanos)
+ val implicitInfoss = companionImplicits(pt)
+ stopTimer(subtypeETNanos, start)
implicitsCache(pt) = implicitInfoss
if (implicitsCache.size >= sizeLimit)
implicitsCache -= implicitsCache.keysIterator.next
implicitInfoss
- }
- }
-
-
- /** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest.
- */
- private def implicitManifest(pt: Type): Tree = pt.dealias match {
- case TypeRef(_, FullManifestClass, List(arg)) =>
- manifestOfType(arg, true)
- case TypeRef(_, PartialManifestClass, List(arg)) =>
- manifestOfType(arg, false)
- case TypeRef(_, OptManifestClass, List(arg)) =>
- val itree = manifestOfType(arg, false)
- if (itree == EmptyTree) gen.mkAttributedRef(NoManifest) else itree
- case TypeRef(_, tsym, _) if (tsym.isAbstractType) =>
- implicitManifest(pt.bounds.lo)
- case _ =>
- EmptyTree
}
/** Creates a tree that calls the relevant factory method in object
@@ -804,6 +822,26 @@ self: Analyzer =>
mot(tp)
}
+ def wrapResult(tree: Tree): SearchResult =
+ if (tree == EmptyTree) SearchFailure else new SearchResult(tree, EmptyTreeTypeSubstituter)
+
+ /** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest.
+ */
+ private def implicitManifestOrOfExpectedType(pt: Type): SearchResult = pt.dealias match {
+ case TypeRef(_, FullManifestClass, List(arg)) =>
+ wrapResult(manifestOfType(arg, true))
+ case TypeRef(_, PartialManifestClass, List(arg)) =>
+ wrapResult(manifestOfType(arg, false))
+ case TypeRef(_, OptManifestClass, List(arg)) =>
+ val itree = manifestOfType(arg, false)
+ wrapResult(if (itree == EmptyTree) gen.mkAttributedRef(NoManifest)
+ else itree)
+ case TypeRef(_, tsym, _) if (tsym.isAbstractType) =>
+ implicitManifestOrOfExpectedType(pt.bounds.lo)
+ case _ =>
+ searchImplicit(implicitsOfExpectedType, false)
+ }
+
/** The result of the implicit search:
* First search implicits visible in current context.
* If that fails, search implicits in expected type `pt`.
@@ -811,24 +849,34 @@ self: Analyzer =>
* If all fails return SearchFailure
*/
def bestImplicit: SearchResult = {
- val start = System.nanoTime()
+ val failstart = startTimer(inscopeFailNanos)
+ val succstart = startTimer(inscopeSucceedNanos)
+
var result = searchImplicit(context.implicitss, true)
- val timer1 = System.nanoTime()
- if (result == SearchFailure) inscopeFail += timer1 - start else inscopeSucceed += timer1 - start
- if (result == SearchFailure)
- result = searchImplicit(implicitsOfExpectedType, false)
- val timer2 = System.nanoTime()
- if (result == SearchFailure) oftypeFail += timer2 - timer1 else oftypeSucceed += timer2 - timer1
if (result == SearchFailure) {
- val resultTree = implicitManifest(pt)
- if (resultTree != EmptyTree) result = new SearchResult(resultTree, EmptyTreeTypeSubstituter)
+ stopTimer(inscopeFailNanos, failstart)
+ } else {
+ stopTimer(inscopeSucceedNanos, succstart)
+ incCounter(inscopeImplicitHits)
}
- val timer3 = System.nanoTime()
- if (result == SearchFailure) manifFail += timer3 - timer2 else manifSucceed += timer3 - timer2
+ if (result == SearchFailure) {
+ val failstart = startTimer(oftypeFailNanos)
+ val succstart = startTimer(oftypeSucceedNanos)
+
+ result = implicitManifestOrOfExpectedType(pt)
+
+ if (result == SearchFailure) {
+ stopTimer(oftypeFailNanos, failstart)
+ } else {
+ stopTimer(oftypeSucceedNanos, succstart)
+ incCounter(oftypeImplicitHits)
+ }
+ }
+
if (result == SearchFailure && settings.debug.value)
- log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+parts(pt)+implicitsOfExpectedType)
- implicitTime += System.nanoTime() - start
+ log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType)
+
result
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 76ff6734d4..5c6788f0f6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -21,11 +21,6 @@ trait Infer {
import global._
import definitions._
- // statistics
- var normM = 0
- var normP = 0
- var normO = 0
-
private final val inferInfo = false //@MDEBUG
/* -- Type parameter inference utility functions --------------------------- */
@@ -33,7 +28,8 @@ trait Infer {
private def assertNonCyclic(tvar: TypeVar) =
assert(tvar.constr.inst != tvar, tvar.origin)
- def isVarArgs(formals: List[Type]) = !formals.isEmpty && isRepeatedParamType(formals.last)
+ def isVarArgs(params: List[Symbol]) = !params.isEmpty && isRepeatedParamType(params.last.tpe)
+ def isVarArgTpes(formals: List[Type]) = !formals.isEmpty && isRepeatedParamType(formals.last)
def isWildcard(tp: Type) = tp match {
case WildcardType | BoundedWildcardType(_) => true
@@ -53,11 +49,11 @@ trait Infer {
/** This variant allows keeping ByName parameters. Useed in NamesDefaults. */
def formalTypes(formals: List[Type], nargs: Int, removeByName: Boolean): List[Type] = {
- val formals1 = if (removeByName) formals map {
+ val formals1 = if (removeByName) formals mapConserve {
case TypeRef(_, sym, List(arg)) if (sym == ByNameParamClass) => arg
case formal => formal
} else formals
- if (isVarArgs(formals1)) {
+ if (isVarArgTpes(formals1)) {
val ft = formals1.last.normalize.typeArgs.head
formals1.init ::: (for (i <- List.range(formals1.length - 1, nargs)) yield ft)
} else formals1
@@ -82,9 +78,11 @@ trait Infer {
//todo: remove comments around following privates; right now they cause an IllegalAccess
// error when built with scalac
- /*private*/ class NoInstance(msg: String) extends RuntimeException(msg) with ControlException
+ /*private*/
+ class NoInstance(msg: String) extends RuntimeException(msg) with ControlException
- /*private*/ class DeferredNoInstance(getmsg: () => String) extends NoInstance("") {
+ /*private*/
+ class DeferredNoInstance(getmsg: () => String) extends NoInstance("") {
override def getMessage(): String = getmsg()
}
@@ -181,18 +179,17 @@ trait Infer {
* A method type becomes the corresponding function type.
* A nullary method type becomes its result type.
* Implicit parameters are skipped.
+ * This method seems to be performance critical.
*/
- def normalize(tp: Type): Type = skipImplicit(tp) match {
+ def normalize(tp: Type): Type = tp match {
case MethodType(params, restpe) if (!restpe.isDependent) =>
- if (util.Statistics.enabled) normM += 1
- functionType(params map (_.tpe), normalize(restpe))
+ if (tp.isInstanceOf[ImplicitMethodType]) normalize(restpe)
+ else functionType(params map (_.tpe), normalize(restpe))
case PolyType(List(), restpe) => // nullary method type
- if (util.Statistics.enabled) normP += 1
normalize(restpe)
case ExistentialType(tparams, qtpe) =>
ExistentialType(tparams, normalize(qtpe))
case tp1 =>
- if (util.Statistics.enabled) normO += 1
tp1 // @MAT aliases already handled by subtyping
}
@@ -401,32 +398,51 @@ trait Infer {
isPlausiblyCompatible(mt.resultType, pt)
case ExistentialType(tparams, qtpe) =>
isPlausiblyCompatible(qtpe, pt)
- case MethodType(params, _) =>
- val formals = tp.paramTypes
- pt.normalize match {
+ case MethodType(params, restpe) =>
+ if (tp.isInstanceOf[ImplicitMethodType]) isPlausiblyCompatible(restpe, pt)
+ else pt match {
case TypeRef(pre, sym, args) =>
- !sym.isClass || {
+ if (sym.isAliasType) {
+ isPlausiblyCompatible(tp, pt.dealias)
+ } else if (sym.isAbstractType) {
+ isPlausiblyCompatible(tp, pt.bounds.lo)
+ } else {
val l = args.length - 1
- l == formals.length &&
- sym == FunctionClass(l) &&
- ((args, formals).zipped forall isPlausiblySubType) &&
- isPlausiblySubType(tp.resultApprox, args.last)
+ l == params.length &&
+ sym == FunctionClass(l) && {
+ var curargs = args
+ var curparams = params
+ while (curparams.nonEmpty) {
+ if (!isPlausiblySubType(curargs.head, curparams.head.tpe))
+ return false
+ curargs = curargs.tail
+ curparams = curparams.tail
+ }
+ isPlausiblySubType(restpe, curargs.head)
+ }
}
case _ =>
- true
+ false
}
case _ =>
- true
+ isPlausiblySubType(tp, pt)
}
- private def isPlausiblySubType(tp1: Type, tp2: Type): Boolean = tp1.normalize match {
+ private def isPlausiblySubType(tp1: Type, tp2: Type): Boolean = tp1 match {
case TypeRef(_, sym1, _) =>
- !sym1.isClass || {
- tp2.normalize match {
- case TypeRef(_, sym2, _) =>
- !sym2.isClass || (sym1 isSubClass sym2) || isNumericSubType(tp1, tp2)
- case _ => true
- }
+ if (sym1.isAliasType) isPlausiblySubType(tp1.dealias, tp2)
+ else if (!sym1.isClass) true
+ else tp2 match {
+ case TypeRef(_, sym2, _) =>
+ if (sym2.isAliasType) isPlausiblySubType(tp1, tp2.dealias)
+ else if (!sym2.isClass) true
+ else if (sym1 isSubClass sym2) true
+ else
+ isNumericValueClass(sym1) &&
+ isNumericValueClass(sym2) &&
+ (sym1 == sym2 || numericWidth(sym1) < numericWidth(sym2))
+ case _ =>
+ true
}
case _ =>
true
@@ -437,6 +453,41 @@ trait Infer {
(tp1 <:< pt) || isCoercible(tp1, pt)
}
+ final def normSubType(tp: Type, pt: Type): Boolean = tp match {
+ case MethodType(params, restpe) =>
+ if (tp.isInstanceOf[ImplicitMethodType]) normSubType(restpe, pt)
+ else pt match {
+ case TypeRef(pre, sym, args) =>
+ if (sym.isAliasType) {
+ normSubType(tp, pt.dealias)
+ } else if (sym.isAbstractType) {
+ normSubType(tp, pt.bounds.lo)
+ } else {
+ val l = args.length - 1
+ l == params.length &&
+ sym == FunctionClass(l) && {
+ var curargs = args
+ var curparams = params
+ while (curparams.nonEmpty) {
+ if (!(curargs.head <:< curparams.head.tpe))
+ return false
+ curargs = curargs.tail
+ curparams = curparams.tail
+ }
+ normSubType(restpe, curargs.head)
+ }
+ }
+ case _ =>
+ tp <:< pt
+ }
+ case PolyType(List(), restpe) => // nullary method type
+ normSubType(restpe, pt)
+ case ExistentialType(tparams, qtpe) =>
+ normalize(tp) <:< pt
+ case _ =>
+ tp <:< pt
+ }
+
def isCompatibleArg(tp: Type, pt: Type): Boolean = {
val tp1 = normalize(tp)
(tp1 weak_<:< pt) || isCoercible(tp1, pt)
@@ -446,7 +497,7 @@ trait Infer {
pt.typeSymbol == UnitClass || // can perform unit coercion
isCompatible(tp, pt) ||
tp.isInstanceOf[MethodType] && // can perform implicit () instantiation
- tp.paramTypes.length == 0 && isCompatible(tp.resultType, pt)
+ tp.params.isEmpty && isCompatible(tp.resultType, pt)
/** Like weakly compatible but don't apply any implicit conversions yet.
* Used when comparing the result type of a method with its prototype.
@@ -700,8 +751,10 @@ trait Infer {
case OverloadedType(pre, alts) =>
alts exists (alt => hasExactlyNumParams(pre.memberType(alt), n))
case _ =>
- formalTypes(tp.paramTypes, n).length == n
+ val len = tp.params.length
+ len == n || isVarArgs(tp.params) && len <= n + 1
}
+
/**
* Verifies whether the named application is valid. The logic is very
* similar to the one in NamesDefaults.removeNames.
@@ -767,13 +820,13 @@ trait Infer {
case ExistentialType(tparams, qtpe) =>
isApplicable(undetparams, qtpe, argtpes0, pt)
case MethodType(params, _) =>
- def paramType(param: Symbol) = param.tpe match {
- case TypeRef(_, sym, List(tpe)) if sym isNonBottomSubClass CodeClass =>
- tpe
- case tpe =>
- tpe
+ val formals0 = params map { param =>
+ param.tpe match {
+ case TypeRef(_, sym, List(tpe)) if sym isNonBottomSubClass CodeClass => tpe
+ case tpe => tpe
+ }
}
- val formals = formalTypes(params map paramType, argtpes0.length)
+ val formals = formalTypes(formals0, argtpes0.length)
def tryTupleApply: Boolean = {
// if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
@@ -883,7 +936,7 @@ trait Infer {
isAsSpecific(ftpe1.resultType, ftpe2)
case MethodType(params @ (x :: xs), _) =>
var argtpes = params map (_.tpe)
- if (isVarArgs(argtpes) && isVarArgs(ftpe2.paramTypes))
+ if (isVarArgs(params) && isVarArgs(ftpe2.params))
argtpes = argtpes map (argtpe =>
if (isRepeatedParamType(argtpe)) argtpe.typeArgs.head else argtpe)
isApplicable(List(), ftpe2, argtpes, WildcardType)
@@ -994,7 +1047,7 @@ trait Infer {
def isStrictlyBetter(tpe1: Type, tpe2: Type) = {
def isNullary(tpe: Type): Boolean = tpe match {
case tp: RewrappingTypeProxy => isNullary(tp.underlying)
- case _ => tpe.paramSectionCount == 0 || tpe.paramTypes.isEmpty
+ case _ => tpe.paramSectionCount == 0 || tpe.params.isEmpty
}
def isMethod(tpe: Type): Boolean = tpe match {
case tp: RewrappingTypeProxy => isMethod(tp.underlying)
@@ -1640,7 +1693,7 @@ trait Infer {
isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt))
if (varArgsOnly)
- allApplicable = allApplicable filter (alt => isVarArgs(alt.tpe.paramTypes))
+ allApplicable = allApplicable filter (alt => isVarArgs(alt.tpe.params))
// if there are multiple, drop those that use a default
// (keep those that use vararg / tupling conversion)
@@ -1653,7 +1706,7 @@ trait Infer {
alts map (_.tpe)
case t => List(t)
}
- mtypes.exists(t => t.paramTypes.length < argtpes.length || // tupling (*)
+ mtypes.exists(t => t.params.length < argtpes.length || // tupling (*)
hasExactlyNumParams(t, argtpes.length)) // same nb or vararg
// (*) more arguments than parameters, but still applicable: tuplig conversion works.
// todo: should not return "false" when paramTypes = (Unit) no argument is given
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 40eb72aaeb..1955348f91 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -874,14 +874,15 @@ trait Namers { self: Analyzer =>
}
for (vparams <- vparamss) {
- var pfs = resultPt.paramTypes
+ var pps = resultPt.params
for (vparam <- vparams) {
if (vparam.tpt.isEmpty) {
- vparam.tpt defineType pfs.head
+ val paramtpe = pps.head.tpe
+ vparam.symbol setInfo paramtpe
+ vparam.tpt defineType paramtpe
vparam.tpt setPos vparam.pos.focus
- vparam.symbol setInfo pfs.head
}
- pfs = pfs.tail
+ pps = pps.tail
}
resultPt = resultPt.resultType
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 835b6f2024..7b41c7b249 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -740,7 +740,7 @@ abstract class RefChecks extends InfoTransform {
sym = sym.info.bounds.hi.widen.typeSymbol
sym
}
- val formal = underlyingClass(fn.tpe.paramTypes.head)
+ val formal = underlyingClass(fn.tpe.params.head.tpe)
val actual = underlyingClass(args.head.tpe)
val receiver = underlyingClass(qual.tpe)
def nonSensibleWarning(what: String, alwaysEqual: Boolean) =
@@ -948,7 +948,7 @@ abstract class RefChecks extends InfoTransform {
private def isRepeatedParamArg(tree: Tree) = currentApplication match {
case Apply(fn, args) =>
!args.isEmpty && (args.last eq tree) &&
- fn.tpe.paramTypes.length == args.length && isRepeatedParamType(fn.tpe.paramTypes.last)
+ fn.tpe.params.length == args.length && isRepeatedParamType(fn.tpe.params.last.tpe)
case _ =>
false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index d09cd85137..e59b469057 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -42,22 +42,14 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Some((_, buf)) => buf
case None => throw new AssertionError("no acc def buf for "+clazz)
}
-/*
- private def transformArgs(args: List[Tree], formals: List[Type]) = {
- if (!formals.isEmpty && formals.last.symbol == definitions.ByNameParamClass)
- ((args take (formals.length - 1) map transform) :::
- withInvalidOwner { args drop (formals.length - 1) map transform })
- else
- args map transform
- }
-*/
- private def transformArgs(args: List[Tree], formals: List[Type]) =
- ((args, formals).zipped map { (arg, formal) =>
- if (formal.typeSymbol == definitions.ByNameParamClass)
- withInvalidOwner { checkPackedConforms(transform(arg), formal.typeArgs.head) }
+
+ private def transformArgs(args: List[Tree], params: List[Symbol]) =
+ ((args, params).zipped map { (arg, param) =>
+ if (param.tpe.typeSymbol == definitions.ByNameParamClass)
+ withInvalidOwner { checkPackedConforms(transform(arg), param.tpe.typeArgs.head) }
else transform(arg)
}) :::
- (args drop formals.length map transform)
+ (args drop params.length map transform)
private def checkPackedConforms(tree: Tree, pt: Type): Tree = {
if (tree.tpe exists (_.typeSymbol.isExistentialSkolem)) {
@@ -223,7 +215,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Apply(fn, args) =>
assert(fn.tpe != null, tree)
- treeCopy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.paramTypes))
+ treeCopy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.params))
case Function(vparams, body) =>
withInvalidOwner {
treeCopy.Function(tree, vparams, transform(body))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c43d9c8788..f29f6fa7a3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -13,11 +13,12 @@ package typechecker
import scala.collection.mutable.{HashMap, ListBuffer}
import scala.util.control.ControlException
-import scala.compat.Platform.currentTime
import scala.tools.nsc.interactive.RangePositions
import scala.tools.nsc.util.{ Position, Set, NoPosition, SourceFile, BatchSourceFile }
import symtab.Flags._
+import util.Statistics._
+
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
/** This trait provides methods to assign types to trees.
@@ -29,16 +30,6 @@ trait Typers { self: Analyzer =>
import global._
import definitions._
- var appcnt = 0
- var idcnt = 0
- var selcnt = 0
- var implcnt = 0
- var impltime = 0l
-
- var failedApplies = 0L
- var failedOpEqs = 0L
- var failedSilent = 0L
-
// namer calls typer.computeType(rhs) on DefDef / ValDef when tpt is empty. the result
// is cached here and re-used in typedDefDef / typedValDef
private val transformed = new HashMap[Tree, Tree]
@@ -46,6 +37,8 @@ trait Typers { self: Analyzer =>
// currently not used at all (March 09)
private val superDefs = new HashMap[Symbol, ListBuffer[Tree]]
+ final val shortenImports = false
+
def resetTyper() {
resetContexts
resetNamer()
@@ -545,6 +538,24 @@ trait Typers { self: Analyzer =>
final val xtypes = false
+ /** Is symbol defined and not stale?
+ */
+ def reallyExists(sym: Symbol) = {
+ if (isStale(sym)) sym.setInfo(NoType)
+ sym.exists
+ }
+
+ /** A symbol is stale if it is toplevel, to be loaded from a classfile, and
+ * the classfile is produced from a sourcefile which is compiled in the current run.
+ */
+ def isStale(sym: Symbol): Boolean = {
+ sym.rawInfo.isInstanceOf[loaders.ClassfileLoader] && {
+ sym.rawInfo.load(sym)
+ (sym.sourceFile ne null) &&
+ (currentRun.compiledFiles contains sym.sourceFile)
+ }
+ }
+
/** Does the context of tree <code>tree</code> require a stable type?
*/
private def isStableContext(tree: Tree, mode: Int, pt: Type) =
@@ -674,7 +685,7 @@ trait Typers { self: Analyzer =>
case Select(qual, _) => qual.tpe
case _ => NoPrefix
}
- if (tree.tpe.isInstanceOf[MethodType] && pre.isStable && sym.tpe.paramTypes.isEmpty &&
+ if (tree.tpe.isInstanceOf[MethodType] && pre.isStable && sym.tpe.params.isEmpty &&
(isStableContext(tree, mode, pt) || sym.isModule))
tree.setType(MethodType(List(), singleType(pre, sym)))
else tree
@@ -690,28 +701,35 @@ trait Typers { self: Analyzer =>
}
def silent[T](op: Typer => T): Any /* in fact, TypeError or T */ = {
-// val start = System.nanoTime()
+ val rawTypeStart = startCounter(rawTypeFailed)
+ val findMemberStart = startCounter(findMemberFailed)
+ val subtypeStart = startCounter(subtypeFailed)
+ val failedSilentStart = startTimer(failedSilentNanos)
try {
- if (context.reportGeneralErrors) {
- val context1 = context.makeSilent(context.reportAmbiguousErrors)
- context1.undetparams = context.undetparams
- context1.savedTypeBounds = context.savedTypeBounds
- context1.namedApplyBlockInfo = context.namedApplyBlockInfo
- val typer1 = newTyper(context1)
- val result = op(typer1)
- context.undetparams = context1.undetparams
- context.savedTypeBounds = context1.savedTypeBounds
- context.namedApplyBlockInfo = context1.namedApplyBlockInfo
- result
- } else {
- op(this)
+ if (context.reportGeneralErrors) {
+ val context1 = context.makeSilent(context.reportAmbiguousErrors)
+ context1.undetparams = context.undetparams
+ context1.savedTypeBounds = context.savedTypeBounds
+ context1.namedApplyBlockInfo = context.namedApplyBlockInfo
+ val typer1 = newTyper(context1)
+ val result = op(typer1)
+ context.undetparams = context1.undetparams
+ context.savedTypeBounds = context1.savedTypeBounds
+ context.namedApplyBlockInfo = context1.namedApplyBlockInfo
+ result
+ } else {
+ op(this)
+ }
+ } catch {
+ case ex: CyclicReference => throw ex
+ case ex: TypeError =>
+ stopCounter(rawTypeFailed, rawTypeStart)
+ stopCounter(findMemberFailed, findMemberStart)
+ stopCounter(subtypeFailed, subtypeStart)
+ stopTimer(failedSilentNanos, failedSilentStart)
+ ex
}
- } catch {
- case ex: CyclicReference => throw ex
- case ex: TypeError =>
-// failedSilent += System.nanoTime() - start
- ex
- }}
+ }
/** Utility method: Try op1 on tree. If that gives an error try op2 instead.
*/
@@ -802,7 +820,7 @@ trait Typers { self: Analyzer =>
if (!context.undetparams.isEmpty/* && (mode & POLYmode) == 0 disabled to make implicits in new collection work; we should revisit this. */) { // (9)
// println("adapt IMT: "+(context.undetparams, pt)) //@MDEBUG
context.undetparams = inferExprInstance(
- tree, context.extractUndetparams(), pt, mt.paramTypes exists isManifest)
+ tree, context.extractUndetparams(), pt, mt.params exists (p => isManifest(p.tpe)))
// if we are looking for a manifest, instantiate type to Nothing anyway,
// as we would get amnbiguity errors otherwise. Example
// Looking for a manifest of Nil: This mas many potential types,
@@ -895,7 +913,7 @@ trait Typers { self: Analyzer =>
case _ => TypeTree(tree.tpe) setOriginal(tree)
}
} else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) { // (5)
- val extractor = tree.symbol.filter(sym => unapplyMember(sym.tpe).exists)
+ val extractor = tree.symbol.filter(sym => reallyExists(unapplyMember(sym.tpe)))
if (extractor != NoSymbol) {
tree setSymbol extractor
val unapply = unapplyMember(extractor.tpe)
@@ -1215,7 +1233,8 @@ trait Typers { self: Analyzer =>
if (!(selfType <:< parent.tpe.typeOfThis) &&
!phase.erasedTypes &&
!(context.owner hasFlag SYNTHETIC) && // don't do this check for synthetic concrete classes for virtuals (part of DEVIRTUALIZE)
- !(settings.suppressVTWarn.value))
+ !(settings.suppressVTWarn.value) &&
+ !selfType.isErroneous && !parent.tpe.isErroneous)
{
//Console.println(context.owner);//DEBUG
//Console.println(context.owner.unsafeTypeParams);//DEBUG
@@ -1558,11 +1577,11 @@ trait Typers { self: Analyzer =>
def decompose(call: Tree): (Tree, List[Tree]) = call match {
case Apply(fn, args) =>
val (superConstr, args1) = decompose(fn)
- val formals = fn.tpe.paramTypes
- val args2 = if (formals.isEmpty || !isRepeatedParamType(formals.last)) args
- else args.take(formals.length - 1) ::: List(EmptyTree)
- if (args2.length != formals.length)
- assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
+ val params = fn.tpe.params
+ val args2 = if (params.isEmpty || !isRepeatedParamType(params.last.tpe)) args
+ else args.take(params.length - 1) ::: List(EmptyTree)
+ if (args2.length != params.length)
+ assert(false, "mismatch " + clazz + " " + (params map (_.tpe)) + " " + args2);//debug
(superConstr, args1 ::: args2)
case Block(stats, expr) if !stats.isEmpty =>
decompose(stats.last)
@@ -1655,11 +1674,11 @@ trait Typers { self: Analyzer =>
while (cx != NoContext) {
val pre = cx.enclClass.prefix
val defEntry = cx.scope.lookupEntry(name)
- if ((defEntry ne null) && defEntry.sym.exists)
+ if ((defEntry ne null) && reallyExists(defEntry.sym))
return Some(defEntry.sym)
cx = cx.enclClass
- (pre member name filter (sym => sym.exists && context.isAccessible(sym, pre, false))) match {
+ (pre member name filter (sym => reallyExists(sym) && context.isAccessible(sym, pre, false))) match {
case NoSymbol => cx = cx.outer
case other => return Some(other)
}
@@ -1807,8 +1826,6 @@ trait Typers { self: Analyzer =>
transformedOrTyped(ddef.rhs, tpt1.tpe)
}
- checkMethodStructuralCompatible(meth)
-
if (meth.isPrimaryConstructor && meth.isClassConstructor &&
phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
computeParamAliases(meth.owner, vparamss1, rhs1)
@@ -2158,7 +2175,7 @@ trait Typers { self: Analyzer =>
def typedArgs(args: List[Tree], mode: Int, originalFormals: List[Type], adaptedFormals: List[Type]) = {
def newmode(i: Int) =
- if (isVarArgs(originalFormals) && i >= originalFormals.length - 1) STARmode else 0
+ if (isVarArgTpes(originalFormals) && i >= originalFormals.length - 1) STARmode else 0
for (((arg, formal), i) <- (args zip adaptedFormals).zipWithIndex) yield
typedArg(arg, mode, newmode(i), formal)
@@ -2194,14 +2211,6 @@ trait Typers { self: Analyzer =>
def isNamedApplyBlock(tree: Tree) =
context.namedApplyBlockInfo exists (_._1 == tree)
- /**
- * @param tree ...
- * @param fun0 ...
- * @param args ...
- * @param mode ...
- * @param pt ...
- * @return ...
- */
def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Int, pt: Type): Tree = {
var fun = fun0
if (fun.hasSymbol && (fun.symbol hasFlag OVERLOADED)) {
@@ -2262,8 +2271,9 @@ trait Typers { self: Analyzer =>
doTypedApply(tree, adapt(fun, funMode(mode), WildcardType), args1, mode, pt)
case mt @ MethodType(params, _) =>
+ val paramTypes = mt.paramTypes
// repeat vararg as often as needed, remove by-name
- val formals = formalTypes(mt.paramTypes, args.length)
+ val formals = formalTypes(paramTypes, args.length)
/** Try packing all arguments into a Tuple and apply `fun'
* to that. This is the last thing which is tried (after
@@ -2364,7 +2374,7 @@ trait Typers { self: Analyzer =>
} else {
val tparams = context.extractUndetparams()
if (tparams.isEmpty) { // all type params are defined
- val args1 = typedArgs(args, argMode(fun, mode), mt.paramTypes, formals)
+ val args1 = typedArgs(args, argMode(fun, mode), paramTypes, formals)
val restpe = mt.resultType(args1 map (_.tpe)) // instantiate dependent method types
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp
@@ -3243,12 +3253,12 @@ trait Typers { self: Analyzer =>
* insert an implicit conversion.
*/
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
- val start = System.nanoTime()
+ val start = startTimer(failedApplyNanos)
silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
case t: Tree =>
t
case ex: TypeError =>
- failedApplies += System.nanoTime() - start
+ stopTimer(failedApplyNanos, start)
def errorInResult(tree: Tree): Boolean = tree.pos == ex.pos || {
tree match {
case Block(_, r) => errorInResult(r)
@@ -3287,11 +3297,12 @@ trait Typers { self: Analyzer =>
typed1(tree, mode & ~PATTERNmode | EXPRmode, pt)
} else {
val funpt = if ((mode & PATTERNmode) != 0) pt else WildcardType
- val start = System.nanoTime()
+ val appStart = startTimer(failedApplyNanos)
+ val opeqStart = startTimer(failedOpEqNanos)
silent(_.typed(fun, funMode(mode), funpt)) match {
case fun1: Tree =>
val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
- if (util.Statistics.enabled) appcnt += 1
+ incCounter(typedApplyCount)
val res =
if (phase.id <= currentRun.typerPhase.id &&
fun2.isInstanceOf[Select] &&
@@ -3320,14 +3331,15 @@ trait Typers { self: Analyzer =>
else res
*/
case ex: TypeError =>
- failedOpEqs += System.nanoTime() - start
fun match {
case Select(qual, name)
if (mode & PATTERNmode) == 0 && nme.isOpAssignmentName(name.decode) =>
val qual1 = typedQualifier(qual)
if (treeInfo.isVariableOrGetter(qual1)) {
+ stopTimer(failedOpEqNanos, opeqStart)
convertToAssignment(fun, qual1, name, args, ex)
} else {
+ stopTimer(failedApplyNanos, appStart)
if ((qual1.symbol ne null) && qual1.symbol.isValue)
error(tree.pos, "reassignment to val")
else
@@ -3335,6 +3347,7 @@ trait Typers { self: Analyzer =>
setError(tree)
}
case _ =>
+ stopTimer(failedApplyNanos, appStart)
reportTypeError(fun.pos, ex)
setError(tree)
}
@@ -3467,7 +3480,7 @@ trait Typers { self: Analyzer =>
val qual1 = adaptToName(qual, name)
if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
- if (!sym.exists) {
+ if (!reallyExists(sym)) {
if (settings.debug.value) Console.err.println("qual = "+qual+":"+qual.tpe+"\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+"\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+"\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner)
if (!qual.tpe.widen.isErroneous) {
error(tree.pos,
@@ -3534,12 +3547,15 @@ trait Typers { self: Analyzer =>
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
var qual: Tree = EmptyTree // the qualififier tree if transformed tree is a select
- // if we are in a constructor of a pattern, ignore all definitions
+ // A symbol qualifies if it exists and is not stale. Stale symbols
+ // are made to disappear here. In addition,
+ // if we are in a constructor of a pattern, we ignore all definitions
// which are methods (note: if we don't do that
// case x :: xs in class List would return the :: method).
- def qualifies(sym: Symbol): Boolean =
- sym.exists &&
+ def qualifies(sym: Symbol): Boolean = {
+ reallyExists(sym) &&
((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod)
+ }
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
@@ -3569,7 +3585,7 @@ trait Typers { self: Analyzer =>
else cx.depth - (cx.scope.nestingLevel - defEntry.owner.nestingLevel)
var impSym: Symbol = NoSymbol; // the imported symbol
var imports = context.imports; // impSym != NoSymbol => it is imported from imports.head
- while (!impSym.exists && !imports.isEmpty && imports.head.depth > symDepth) {
+ while (!reallyExists(impSym) && !imports.isEmpty && imports.head.depth > symDepth) {
impSym = imports.head.importedSymbol(name)
if (!impSym.exists) imports = imports.tail
}
@@ -3611,7 +3627,7 @@ trait Typers { self: Analyzer =>
(!imports.head.isExplicitImport(name) ||
imports1.head.depth == imports.head.depth)) {
var impSym1 = imports1.head.importedSymbol(name)
- if (impSym1.exists) {
+ if (reallyExists(impSym1)) {
if (imports1.head.isExplicitImport(name)) {
if (imports.head.isExplicitImport(name) ||
imports1.head.depth != imports.head.depth) ambiguousImport()
@@ -3623,7 +3639,9 @@ trait Typers { self: Analyzer =>
imports1 = imports1.tail
}
defSym = impSym
- qual = atPos(tree.pos.focusStart)(resetPos(imports.head.qual.duplicate))
+ val qual0 = imports.head.qual
+ if (!(shortenImports && qual0.symbol.isPackage)) // optimization: don't write out package prefixes
+ qual = atPos(tree.pos.focusStart)(resetPos(qual0.duplicate))
pre = qual.tpe
} else {
if (settings.debug.value) {
@@ -3949,7 +3967,7 @@ trait Typers { self: Analyzer =>
typedSelect(qual1, nme.CONSTRUCTOR)
case Select(qual, name) =>
- if (util.Statistics.enabled) selcnt += 1
+ incCounter(typedSelectCount)
var qual1 = checkDead(typedQualifier(qual, mode))
if (name.isTypeName) qual1 = checkStable(qual1)
@@ -3977,7 +3995,7 @@ trait Typers { self: Analyzer =>
else tree1
case Ident(name) =>
- if (util.Statistics.enabled) idcnt += 1
+ incCounter(typedIdentCount)
if ((name == nme.WILDCARD && (mode & (PATTERNmode | FUNmode)) == PATTERNmode) ||
(name == nme.WILDCARD.toTypeName && (mode & TYPEmode) != 0))
tree setType makeFullyDefined(pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 812276612f..3898e46c0b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -94,8 +94,8 @@ trait Unapplies extends ast.TreeDSL
}
/** returns unapply member's parameter type. */
def unapplyParameterType(extractor: Symbol) = {
- val tps = extractor.tpe.paramTypes
- if (tps.length == 1) tps.head.typeSymbol
+ val ps = extractor.tpe.params
+ if (ps.length == 1) ps.head.tpe.typeSymbol
else NoSymbol
}
diff --git a/src/compiler/scala/tools/nsc/util/Statistics.scala b/src/compiler/scala/tools/nsc/util/Statistics.scala
index e9e9f65058..eb8a25a6ed 100644
--- a/src/compiler/scala/tools/nsc/util/Statistics.scala
+++ b/src/compiler/scala/tools/nsc/util/Statistics.scala
@@ -9,57 +9,230 @@ package scala.tools.nsc
package util
object Statistics {
+
var enabled = false
+ var phasesShown = List("parser", "typer", "erasure", "cleanup")
+
+ def currentTime() =
+ if (enabled) System.nanoTime() else 0L
+
+ private def showPercent(x: Double, base: Double) =
+ if (base == 0) "" else " ("+"%2.1f".format(x / base * 100)+"%)"
+
+ def incCounter(c: Counter) {
+ if (enabled) c.value += 1
+ }
+
+ def incCounter(c: Counter, delta: Int) {
+ if (enabled) c.value += delta
+ }
+
+ def startCounter(sc: SubCounter): IntPair =
+ if (enabled) sc.start() else null
+
+ def stopCounter(sc: SubCounter, start: IntPair) {
+ if (enabled) sc.stop(start)
+ }
+
+ def startTimer(tm: Timer): LongPair =
+ if (enabled) tm.start() else null
+
+ def stopTimer(tm: Timer, start: LongPair) {
+ if (enabled) tm.stop(start)
+ }
+
+ case class IntPair(x: Int, y: Int)
+ case class LongPair(x: Long, y: Long)
+
+ class Counter {
+ var value: Int = 0
+ override def toString = value.toString
+ }
+
+ class SubCounter(c: Counter) {
+ var value: Int = 0
+ def start(): IntPair =
+ if (enabled) IntPair(value, c.value) else null
+ def stop(prev: IntPair) {
+ if (enabled) {
+ val IntPair(value0, cvalue0) = prev
+ value = value0 + c.value - cvalue0
+ }
+ }
+ override def toString =
+ value+showPercent(value, c.value)
+ }
+
+ class Timer {
+ var nanos: Long = 0L
+ def start(): LongPair =
+ if (enabled) LongPair(nanos, System.nanoTime()) else null
+ def stop(prev: LongPair) {
+ if (enabled) {
+ val LongPair(nanos0, start) = prev
+ nanos = nanos0 + System.nanoTime() - start
+ }
+ }
+ override def toString = nanos.toString+"ns"
+ }
+
+ class ClassCounts extends scala.collection.mutable.HashMap[Class[_], Int] {
+ override def default(key: Class[_]) = 0
+ }
+
+ var nodeByType = new ClassCounts
+
+ val singletonBaseTypeSeqCount = new Counter
+ val compoundBaseTypeSeqCount = new Counter
+ val typerefBaseTypeSeqCount = new Counter
+ val findMemberCount = new Counter
+ val noMemberCount = new Counter
+ val multMemberCount = new Counter
+ val findMemberNanos = new Timer
+ val asSeenFromCount = new Counter
+ val asSeenFromNanos = new Timer
+ val subtypeCount = new Counter
+ val subtypeNanos = new Timer
+ val sametypeCount = new Counter
+ val rawTypeCount = new Counter
+ val rawTypeFailed = new SubCounter(rawTypeCount)
+ val findMemberFailed = new SubCounter(findMemberCount)
+ val subtypeFailed = new SubCounter(subtypeCount)
+ val rawTypeImpl = new SubCounter(rawTypeCount)
+ val findMemberImpl = new SubCounter(findMemberCount)
+ val subtypeImpl = new SubCounter(subtypeCount)
+ val baseTypeSeqCount = new Counter
+ val baseTypeSeqLenTotal = new Counter
+ val typeSymbolCount = new Counter
+ val classSymbolCount = new Counter
+ val typedApplyCount = new Counter
+ val typedIdentCount = new Counter
+ val typedSelectCount = new Counter
+ val typerNanos = new Timer
+ val classReadNanos = new Timer
+
+ val failedApplyNanos = new Timer
+ val failedOpEqNanos = new Timer
+ val failedSilentNanos = new Timer
+
+ val implicitSearchCount = new Counter
+ val implicitNanos = new Timer
+ val oftypeImplicitHits = new Counter
+ val inscopeImplicitHits = new Counter
+
+ val triedImplicits = new Counter
+ val plausiblyCompatibleImplicits = new Counter
+ val matchingImplicits = new Counter
+ val typedImplicits = new Counter
+ val foundImplicits = new Counter
+
+ val inscopeSucceedNanos = new Timer
+ val inscopeFailNanos = new Timer
+ val oftypeSucceedNanos = new Timer
+ val oftypeFailNanos = new Timer
+ val implicitCacheHits = new Counter
+ val implicitCacheMisses = new Counter
+ val improvesCount = new Counter
+ val subtypeAppInfos = new SubCounter(subtypeCount)
+ val subtypeImprovCount = new SubCounter(subtypeCount)
+ val subtypeETNanos = new Timer
+ val matchesPtNanos = new Timer
+ val counter1: SubCounter = new SubCounter(findMemberCount)
+ val counter2: SubCounter = new SubCounter(findMemberCount)
+ val timer1: Timer = new Timer
+ val timer2: Timer = new Timer
}
abstract class Statistics {
+ import Statistics._
+
val global: Global
import global._
- def showRelative(base: Long)(time: Long) = "%2.1f".format(time.toDouble / base * 100)+" / "+time+"ns"
- def showRelTyper(time: Long) = showRelative(analyzer.typerTime)(time)
-
- def print(phase: Phase) = {
- if (List("typer", "erasure", "cleanup") contains phase.name) {
- inform("*** Cumulative statistics at phase " + phase)
- inform("#tree nodes : " + nodeCount)
- inform("#identifiers : " + analyzer.idcnt)
- inform("#selections : " + analyzer.selcnt)
- inform("#applications: " + analyzer.appcnt)
- inform("#implicits : " + analyzer.implcnt)
- inform("#uniquetypes : " + uniqueTypeCount)
- inform("#symbols : " + symbolCount)
- inform("#type symbols: " + typeSymbolCount)
- inform("#class symbols: " + classSymbolCount)
- inform("#singleton closures: " + singletonBaseTypeSeqCount)
- inform("#compound closures : " + compoundBaseTypeSeqCount)
- inform("#typeref closures : " + typerefBaseTypeSeqCount)
- inform("#findMember : " + findMemberCount)
- inform("#notfound member: " + noMemberCount)
- inform("#multiple member: " + multMemberCount)
- inform("time findMember: " + findMemberNanos)
- inform("#norm meth : " + analyzer.normM)
- inform("#norm poly : " + analyzer.normP)
- inform("#norm other : " + analyzer.normO)
- inform("#subtype : " + subtypeCount)
- inform("ns subtype : " + subtypeNanos)
- inform("#sametype : " + sametypeCount)
+ def countNodes(tree: Tree, counts: ClassCounts) {
+ for (t <- tree) counts(t.getClass) += 1
+ counts
+ }
+
+ def showRelative(base: Long)(value: Long) =
+ value+showPercent(value, base)
+
+ def showRelTyper(timer: Timer) =
+ timer.nanos+"ns"+showPercent(timer.nanos, typerNanos.nanos)
+
+ def showCounts(counts: ClassCounts) =
+ counts.toSeq.sortWith(_._2 > _._2).map {
+ case (cls, cnt) =>
+ cls.toString.substring(cls.toString.lastIndexOf("$") + 1)+": "+cnt
+ }
+
+ def print(phase: Phase) = if (phasesShown contains phase.name) {
+ inform("*** Cumulative statistics at phase " + phase)
+ inform("#created tree nodes : " + nodeCount)
+ inform("#created tree nodes by type: "+showCounts(nodeByType))
+ if (phase.name != "parser") {
+ val counts = new ClassCounts
+ for (u <- currentRun.units; t <- u.body) counts(t.getClass) += 1
+ inform("#retained nodes : " + counts.valuesIterable.sum)
+ inform("#retained nodes by type : " + showCounts(counts))
+ inform("#typechecked identifiers : " + typedIdentCount)
+ inform("#typechecked selections : " + typedSelectCount)
+ inform("#typechecked applications: " + typedApplyCount)
+ inform("#raw type creations : " + rawTypeCount)
+ inform(" of which in failed : " + rawTypeFailed)
+ inform(" of which in implicits : " + rawTypeImpl)
+ inform("#unique types : " + uniqueTypeCount)
+ inform("#symbols : " + symbolCount)
+ inform(" of which type symbols : " + typeSymbolCount)
+ inform(" of which class symbols : " + classSymbolCount)
+ inform("#base type seqs : " + baseTypeSeqCount)
+ inform("avg base type seq length : " + baseTypeSeqLenTotal.value.toFloat / baseTypeSeqCount.value)
+ inform("#singleton base type seqs: " + singletonBaseTypeSeqCount)
+ inform("#compound base type seqs : " + compoundBaseTypeSeqCount)
+ inform("#typeref base type seqs : " + typerefBaseTypeSeqCount)
+ inform("#findMember ops : " + findMemberCount)
+ inform(" of which in failed : " + findMemberFailed)
+ inform(" of which in implicits : " + findMemberImpl)
+ inform("#notfound member : " + noMemberCount)
+ inform("#multiple member : " + multMemberCount)
+ inform("#asSeenFrom ops : " + asSeenFromCount)
+ inform("#subtype : " + subtypeCount)
+ inform(" of which in failed : " + subtypeFailed)
+ inform(" of which in implicits : " + subtypeImpl)
+ inform(" of which in app impl : " + subtypeAppInfos)
+ inform(" of which in improv : " + subtypeImprovCount)
+ inform("#sametype : " + sametypeCount)
inform("ms type-flow-analysis: " + analysis.timer.millis)
+
if (phase.name == "typer") {
- inform("time spent typechecking: "+showRelTyper(analyzer.typerTime))
- inform("time spent in implicits: "+showRelTyper(analyzer.implicitTime))
- inform(" successful in scope: "+showRelTyper(analyzer.inscopeSucceed))
- inform(" failed in scope: "+showRelTyper(analyzer.inscopeFail))
- inform(" successful of type: "+showRelTyper(analyzer.oftypeSucceed))
- inform(" failed of type: "+showRelTyper(analyzer.oftypeFail))
- inform(" successful manifest: "+showRelTyper(analyzer.manifSucceed))
- inform(" failed manifest: "+showRelTyper(analyzer.manifFail))
- inform("implicit cache hitratio: "+"%2.1f".format(analyzer.hits.toDouble / (analyzer.hits + analyzer.misses) * 100))
- inform("time spent in failed : "+showRelTyper(analyzer.failedSilent))
- inform(" failed op= : "+showRelTyper(analyzer.failedOpEqs))
- inform(" failed apply : "+showRelTyper(analyzer.failedApplies))
+ inform("time spent typechecking : "+showRelTyper(typerNanos))
+ inform("time classfilereading : "+showRelTyper(classReadNanos))
+ inform("time spent in implicits : "+showRelTyper(implicitNanos))
+ inform(" successful in scope : "+showRelTyper(inscopeSucceedNanos))
+ inform(" failed in scope : "+showRelTyper(inscopeFailNanos))
+ inform(" successful of type : "+showRelTyper(oftypeSucceedNanos))
+ inform(" failed of type : "+showRelTyper(oftypeFailNanos))
+ inform(" assembling parts : "+showRelTyper(subtypeETNanos))
+ inform(" matchesPT : "+showRelTyper(matchesPtNanos))
+ inform("implicit cache hits : "+showRelative(implicitCacheHits.value + implicitCacheMisses.value)(implicitCacheHits.value))
+ inform("time spent in failed : "+showRelTyper(failedSilentNanos))
+ inform(" failed apply : "+showRelTyper(failedApplyNanos))
+ inform(" failed op= : "+showRelTyper(failedOpEqNanos))
+ inform("time spent in <:< : "+showRelTyper(subtypeNanos))
+ inform("time spent in findmember : "+showRelTyper(findMemberNanos))
+ inform("time spent in asSeenFrom : "+showRelTyper(asSeenFromNanos))
+ inform("#implicit searches : " + implicitSearchCount)
+ inform("#tried, plausible, matching, typed, found implicits: "+triedImplicits+", "+plausiblyCompatibleImplicits+", "+matchingImplicits+", "+typedImplicits+", "+foundImplicits)
+ inform("#implicit improves tests : " + improvesCount)
+ inform("#implicit inscope hits : " + inscopeImplicitHits)
+ inform("#implicit oftype hits : " + oftypeImplicitHits)
}
+
+ if (counter1 != null) inform("#counter1 : " + counter1)
+ if (counter2 != null) inform("#counter2 : " + counter2)
+ if (timer1 != null) inform("#timer1 : " + timer1)
+ if (timer2 != null) inform("#timer2 : " + timer2)
//for (t <- uniques.iterator) println("unique: "+t)
}
}
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 73512e2688..5684c91aaa 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -117,7 +117,7 @@ object Predef extends LowPriorityImplicits {
throw new IllegalArgumentException("requirement failed: "+ message)
}
- class Ensuring[A](x: A) {
+ final class Ensuring[A](val x: A) {
def ensuring(cond: Boolean): A = { assert(cond); x }
def ensuring(cond: Boolean, msg: Any): A = { assert(cond, msg); x }
def ensuring(cond: A => Boolean): A = { assert(cond(x)); x }
@@ -139,8 +139,8 @@ object Predef extends LowPriorityImplicits {
def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x)
}
- class ArrowAssoc[A](x: A) {
- def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
+ final class ArrowAssoc[A](val x: A) {
+ @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(x, y)
def →[B](y: B): Tuple2[A, B] = ->(y)
}
implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
diff --git a/src/library/scala/collection/IndexedSeqViewLike.scala b/src/library/scala/collection/IndexedSeqViewLike.scala
index b27383424f..06fa6c8953 100644
--- a/src/library/scala/collection/IndexedSeqViewLike.scala
+++ b/src/library/scala/collection/IndexedSeqViewLike.scala
@@ -24,47 +24,24 @@ import TraversableView.NoBuilder
trait IndexedSeqViewLike[+A,
+Coll,
+This <: IndexedSeqView[A, Coll] with IndexedSeqViewLike[A, Coll, This]]
- extends IndexedSeq[A] with IndexedSeqLike[A, This] with SeqView[A, Coll] with SeqViewLike[A, Coll, This]
+ extends IndexedSeq[A]
+ with IndexedSeqLike[A, This]
+ with SeqView[A, Coll]
+ with SeqViewLike[A, Coll, This]
+ with views.IndexedSeqTransformations[A, Coll, This]
{ self =>
- trait Transformed[+B] extends IndexedSeqView[B, Coll] with super.Transformed[B]
+ trait Transformed[+B] extends views.IndexedSeqLike[B, Coll] with super.Transformed[B]
- trait Sliced extends Transformed[A] with super.Sliced {
- /** Override to use IndexedSeq's foreach; todo: see whether this is really faster */
- override def foreach[U](f: A => U) = super[Transformed].foreach(f)
- }
-
- trait Mapped[B] extends Transformed[B] with super.Mapped[B] {
- override def foreach[U](f: B => U) = super[Transformed].foreach(f)
- }
-
- trait FlatMapped[B] extends Transformed[B] with super.FlatMapped[B] {
- override def foreach[U](f: B => U) = super[Transformed].foreach(f)
- }
-
- trait Appended[B >: A] extends Transformed[B] with super.Appended[B] {
- override def foreach[U](f: B => U) = super[Transformed].foreach(f)
- }
-
- trait Filtered extends Transformed[A] with super.Filtered {
- override def foreach[U](f: A => U) = super[Transformed].foreach(f)
- }
-
- trait TakenWhile extends Transformed[A] with super.TakenWhile {
- override def foreach[U](f: A => U) = super[Transformed].foreach(f)
- }
-
- trait DroppedWhile extends Transformed[A] with super.DroppedWhile {
- override def foreach[U](f: A => U) = super[Transformed].foreach(f)
- }
-
- trait Reversed extends Transformed[A] with super.Reversed {
- override def foreach[U](f: A => U) = super[Transformed].foreach(f)
- }
-
- trait Patched[B >: A] extends Transformed[B] with super.Patched[B] {
- override def foreach[U](f: B => U) = super[Transformed].foreach(f)
- }
+ trait Sliced extends Transformed[A] with super.Sliced
+ trait Mapped[B] extends Transformed[B] with super.Mapped[B]
+ trait FlatMapped[B] extends Transformed[B] with super.FlatMapped[B]
+ trait Appended[B >: A] extends Transformed[B] with super.Appended[B]
+ trait Filtered extends Transformed[A] with super.Filtered
+ trait TakenWhile extends Transformed[A] with super.TakenWhile
+ trait DroppedWhile extends Transformed[A] with super.DroppedWhile
+ trait Reversed extends Transformed[A] with super.Reversed
+ trait Patched[B >: A] extends Transformed[B] with super.Patched[B]
trait Zipped[B] extends Transformed[(A, B)] {
protected[this] val other: Iterable[B]
@@ -88,22 +65,5 @@ trait IndexedSeqViewLike[+A,
}
override def stringPrefix = self.stringPrefix+"Z"
}
-
- /** Boilerplate method, to override in each subclass
- * This method could be eliminated if Scala had virtual classes
- */
- protected override def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
- protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
- protected override def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
- protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
- protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
- protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
- protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
- protected override def newZipped[B](that: Iterable[B]): Transformed[(A, B)] = new Zipped[B] { val other = that }
- protected override def newZippedAll[A1 >: A, B](that: Iterable[B], _thisElem: A1, _thatElem: B): Transformed[(A1, B)] = new ZippedAll[A1, B] { val other = that; val thisElem = _thisElem; val thatElem = _thatElem }
- protected override def newReversed: Transformed[A] = new Reversed { }
- protected override def newPatched[B >: A](_from: Int, _patch: Seq[B], _replaced: Int): Transformed[B] = new Patched[B] {
- val from = _from; val patch = _patch; val replaced = _replaced
- }
override def stringPrefix = "IndexedSeqView"
}
diff --git a/src/library/scala/collection/IterableViewLike.scala b/src/library/scala/collection/IterableViewLike.scala
index 27323294c4..831a244352 100644
--- a/src/library/scala/collection/IterableViewLike.scala
+++ b/src/library/scala/collection/IterableViewLike.scala
@@ -24,10 +24,14 @@ import TraversableView.NoBuilder
trait IterableViewLike[+A,
+Coll,
+This <: IterableView[A, Coll] with IterableViewLike[A, Coll, This]]
-extends Iterable[A] with IterableLike[A, This] with TraversableView[A, Coll] with TraversableViewLike[A, Coll, This]
+ extends Iterable[A]
+ with IterableLike[A, This]
+ with TraversableView[A, Coll]
+ with TraversableViewLike[A, Coll, This]
+ with views.IterableTransformations[A, Coll, This]
{ self =>
- trait Transformed[+B] extends IterableView[B, Coll] with super.Transformed[B]
+ trait Transformed[+B] extends views.IterableLike[B, Coll] with super.Transformed[B]
trait Sliced extends Transformed[A] with super.Sliced {
override def iterator = self.iterator slice (from, until)
@@ -84,25 +88,5 @@ extends Iterable[A] with IterableLike[A, This] with TraversableView[A, Coll] wit
override def zipAll[B, A1 >: A, That](that: Iterable[B], thisElem: A1, thatElem: B)(implicit bf: CanBuildFrom[This, (A1, B), That]): That =
newZippedAll(that, thisElem, thatElem).asInstanceOf[That]
- protected def newZipped[B](that: Iterable[B]): Transformed[(A, B)] = new Zipped[B] {
- val other = that
- }
- protected def newZippedAll[A1 >: A, B](that: Iterable[B], _thisElem: A1, _thatElem: B): Transformed[(A1, B)] = new ZippedAll[A1, B] {
- val other: Iterable[B] = that
- val thisElem = _thisElem
- val thatElem = _thatElem
- }
-
- /** Boilerplate method, to override in each subclass
- * This method could be eliminated if Scala had virtual classes
- */
- protected override def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
- protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
- protected override def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
- protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
- protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
- protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
- protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
-
override def stringPrefix = "IterableView"
}
diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala
index 1a8cd20013..6f677616e7 100644
--- a/src/library/scala/collection/SeqViewLike.scala
+++ b/src/library/scala/collection/SeqViewLike.scala
@@ -23,13 +23,14 @@ import TraversableView.NoBuilder
trait SeqViewLike[+A,
+Coll,
+This <: SeqView[A, Coll] with SeqViewLike[A, Coll, This]]
- extends Seq[A] with SeqLike[A, This] with IterableView[A, Coll] with IterableViewLike[A, Coll, This]
+ extends Seq[A]
+ with SeqLike[A, This]
+ with IterableView[A, Coll]
+ with IterableViewLike[A, Coll, This]
+ with views.SeqTransformations[A, Coll, This]
{ self =>
- trait Transformed[+B] extends SeqView[B, Coll] with super.Transformed[B] {
- override def length: Int
- override def apply(idx: Int): B
- }
+ trait Transformed[+B] extends views.SeqLike[B, Coll] with super.Transformed[B]
trait Sliced extends Transformed[A] with super.Sliced {
override def length = ((until min self.length) - from) max 0
@@ -143,21 +144,6 @@ trait SeqViewLike[+A,
override def stringPrefix = self.stringPrefix+"P"
}
- /** Boilerplate method, to override in each subclass
- * This method could be eliminated if Scala had virtual classes
- */
- protected override def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
- protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
- protected override def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
- protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
- protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
- protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
- protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
- protected override def newZipped[B](that: Iterable[B]): Transformed[(A, B)] = new Zipped[B] { val other = that }
- protected override def newZippedAll[A1 >: A, B](that: Iterable[B], _thisElem: A1, _thatElem: B): Transformed[(A1, B)] = new ZippedAll[A1, B] { val other = that; val thisElem = _thisElem; val thatElem = _thatElem }
- protected def newReversed: Transformed[A] = new Reversed { }
- protected def newPatched[B >: A](_from: Int, _patch: Seq[B], _replaced: Int): Transformed[B] = new Patched[B] { val from = _from; val patch = _patch; val replaced = _replaced }
-
override def reverse: This = newReversed.asInstanceOf[This]
override def patch[B >: A, That](from: Int, patch: Seq[B], replaced: Int)(implicit bf: CanBuildFrom[This, B, That]): That = {
diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala
index 84c33296db..7f4d0ebd71 100644
--- a/src/library/scala/collection/TraversableViewLike.scala
+++ b/src/library/scala/collection/TraversableViewLike.scala
@@ -33,7 +33,9 @@ import TraversableView.NoBuilder
trait TraversableViewLike[+A,
+Coll,
+This <: TraversableView[A, Coll] with TraversableViewLike[A, Coll, This]]
- extends Traversable[A] with TraversableLike[A, This] {
+ extends Traversable[A]
+ with TraversableLike[A, This]
+ with views.TraversableTransformations[A, Coll, This] {
self =>
override protected[this] def newBuilder: Builder[A, This] =
@@ -41,16 +43,16 @@ self =>
protected def underlying: Coll
+ trait Transformed[+B] extends views.TraversableLike[B, Coll] {
+ lazy val underlying = self.underlying
+ }
+
def force[B >: A, That](implicit bf: CanBuildFrom[Coll, B, That]) = {
val b = bf(underlying)
b ++= this
b.result()
}
- trait Transformed[+B] extends TraversableView[B, Coll] {
- lazy val underlying = self.underlying
- }
-
/** pre: from >= 0
*/
trait Sliced extends Transformed[A] {
@@ -131,17 +133,6 @@ self =>
override def stringPrefix = self.stringPrefix+"D"
}
- /** Boilerplate method, to override in each subclass
- * This method could be eliminated if Scala had virtual classes
- */
- protected def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
- protected def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
- protected def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
- protected def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
- protected def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
- protected def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
- protected def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
-
override def ++[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[This, B, That]): That = {
newAppended(that).asInstanceOf[That]
// was: if (bf.isInstanceOf[ByPassCanBuildFrom]) newAppended(that).asInstanceOf[That]
diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala
index 9138c2bbac..db6479742b 100644
--- a/src/library/scala/collection/immutable/StringOps.scala
+++ b/src/library/scala/collection/immutable/StringOps.scala
@@ -17,7 +17,7 @@ import mutable.StringBuilder
/**
* @since 2.8
*/
-class StringOps(override val repr: String) extends StringLike[String] {
+final class StringOps(override val repr: String) extends StringLike[String] {
override protected[this] def thisCollection: WrappedString = new WrappedString(repr)
override protected[this] def toCollection(repr: String): WrappedString = new WrappedString(repr)
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index c60cbcd68c..c88b9d3374 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -132,7 +132,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
require(count >= 0, "removing negative number of elements")
if (n < 0 || n > size0 - count) throw new IndexOutOfBoundsException(n.toString)
copy(n + count, n, size0 - (n + count))
- size0 -= count
+ reduceToSize(size0 - count)
}
/** Removes the element on a given index position
diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala
index e864845455..db1735b543 100644
--- a/src/library/scala/collection/mutable/IndexedSeqView.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqView.scala
@@ -13,7 +13,6 @@ package scala.collection
package mutable
import generic._
-
import TraversableView.NoBuilder
/** A non-strict view of a mutable IndexedSeq.
@@ -30,9 +29,7 @@ self =>
def update(idx: Int, elem: A)
- trait Transformed[B] extends IndexedSeqView[B, Coll] with super.Transformed[B] {
- def update(idx: Int, elem: B)
- }
+ trait Transformed[B] extends views.MutableIndexedSeq[B, Coll] with IndexedSeqView[B, Coll] with super.Transformed[B]
trait Sliced extends Transformed[A] with super.Sliced {
override def update(idx: Int, elem: A) =
diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala
index 8279bd53f8..e335500349 100644
--- a/src/library/scala/collection/mutable/MultiMap.scala
+++ b/src/library/scala/collection/mutable/MultiMap.scala
@@ -40,7 +40,9 @@ trait MultiMap[A, B] extends Map[A, Set[B]] {
def removeBinding(key: A, value: B): this.type = {
get(key) match {
case None =>
- case Some(set) => set -= value
+ case Some(set) =>
+ set -= value
+ if (set.isEmpty) this -= key
}
this
}
diff --git a/src/library/scala/collection/views/Transformed.scala b/src/library/scala/collection/views/Transformed.scala
new file mode 100644
index 0000000000..189ca127c8
--- /dev/null
+++ b/src/library/scala/collection/views/Transformed.scala
@@ -0,0 +1,128 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection
+package views
+
+import generic.CanBuildFrom
+
+/** These classes act as accumulators for the majority of methods in the
+ * collections hierarchy. By creating abstract classes rather than using
+ * the traits exclusively, we avoid creating forwarders in dozens of distinct
+ * anonymous classes and reduce the size of scala-library.jar by over 200K.
+ */
+private[collection] trait Transformed
+private[collection] abstract class TraversableLike[+B, +Coll] extends TraversableView[B, Coll] with Transformed {
+ override def foreach[C](f: B => C): Unit
+}
+private[collection] abstract class IterableLike[+B, +Coll] extends TraversableLike[B, Coll] with IterableView[B, Coll] {
+ override def iterator: Iterator[B]
+}
+private[collection] abstract class SeqLike[+B, +Coll] extends IterableLike[B, Coll] with SeqView[B, Coll] {
+ override def length: Int
+ override def apply(idx: Int): B
+}
+private[collection] abstract class IndexedSeqLike[+B, +Coll] extends SeqLike[B, Coll] with IndexedSeqView[B, Coll] {
+ /** Override to use IndexedSeq's foreach; todo: see whether this is really faster */
+ override def foreach[U](f: B => U) = super[IndexedSeqView].foreach(f)
+}
+private[collection] abstract class MutableIndexedSeq[B, +Coll] extends IndexedSeqLike[B, Coll] {
+ def update(idx: Int, elem: B)
+}
+
+/** The boilerplate in the following traits factored out of the *ViewLike classes
+ * to reduce noise. It exists only to specialize the return type of each method.
+ * It would be unnecessary if scala had virtual classes because the inner classes
+ * of subtraits would subclass the parent trait inner classes, and the same method
+ * would then suffice for both.
+ */
+private[collection] trait TraversableTransformations[+A, +Coll, +This <: TraversableView[A, Coll] with TraversableViewLike[A, Coll, This]] {
+ self: TraversableViewLike[A, Coll, This] =>
+
+ /** Boilerplate methods, to override in each subclass. */
+ protected def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
+ protected def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
+ protected def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
+ protected def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
+ protected def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
+ protected def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
+ protected def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
+}
+
+private[collection] trait IterableTransformations[+A, +Coll, +This <: IterableView[A, Coll] with IterableViewLike[A, Coll, This]]
+ extends TraversableTransformations[A, Coll, This]
+{
+ self: IterableViewLike[A, Coll, This] =>
+
+ /** Inherited from TraversableView */
+ protected override def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
+ protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
+ protected override def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
+ protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
+ protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
+ protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
+ protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
+
+ /** IterableView boilerplate contribution */
+ protected def newZipped[B](that: Iterable[B]): Transformed[(A, B)] = new Zipped[B] {
+ val other = that
+ }
+ protected def newZippedAll[A1 >: A, B](that: Iterable[B], _thisElem: A1, _thatElem: B): Transformed[(A1, B)] = new ZippedAll[A1, B] {
+ val other: Iterable[B] = that
+ val thisElem = _thisElem
+ val thatElem = _thatElem
+ }
+}
+
+private[collection] trait SeqTransformations[+A, +Coll, +This <: SeqView[A, Coll] with SeqViewLike[A, Coll, This]]
+ extends IterableTransformations[A, Coll, This]
+{
+ self: SeqViewLike[A, Coll, This] =>
+
+ /** Inherited from IterableView */
+ protected override def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
+ protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
+ protected override def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
+ protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
+ protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
+ protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
+ protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
+ protected override def newZipped[B](that: Iterable[B]): Transformed[(A, B)] = new Zipped[B] { val other = that }
+ protected override def newZippedAll[A1 >: A, B](that: Iterable[B], _thisElem: A1, _thatElem: B): Transformed[(A1, B)] =
+ new ZippedAll[A1, B] { val other = that; val thisElem = _thisElem; val thatElem = _thatElem }
+
+ /** SeqView boilerplate contribution */
+ protected def newReversed: Transformed[A] = new Reversed { }
+ protected def newPatched[B >: A](_from: Int, _patch: Seq[B], _replaced: Int): Transformed[B] =
+ new Patched[B] { val from = _from; val patch = _patch; val replaced = _replaced }
+}
+
+private[collection] trait IndexedSeqTransformations[+A, +Coll, +This <: IndexedSeqView[A, Coll] with IndexedSeqViewLike[A, Coll, This]]
+ extends SeqTransformations[A, Coll, This]
+{
+ self: IndexedSeqViewLike[A, Coll, This] =>
+
+ /** Inherited from SeqView */
+ protected override def newAppended[B >: A](that: Traversable[B]): Transformed[B] = new Appended[B] { val rest = that }
+ protected override def newMapped[B](f: A => B): Transformed[B] = new Mapped[B] { val mapping = f }
+ protected override def newFlatMapped[B](f: A => Traversable[B]): Transformed[B] = new FlatMapped[B] { val mapping = f }
+ protected override def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
+ protected override def newSliced(_from: Int, _until: Int): Transformed[A] = new Sliced { val from = _from; val until = _until }
+ protected override def newDroppedWhile(p: A => Boolean): Transformed[A] = new DroppedWhile { val pred = p }
+ protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new TakenWhile { val pred = p }
+
+ protected override def newZipped[B](that: Iterable[B]): Transformed[(A, B)] = new Zipped[B] { val other = that }
+ protected override def newZippedAll[A1 >: A, B](that: Iterable[B], _thisElem: A1, _thatElem: B): Transformed[(A1, B)] =
+ new ZippedAll[A1, B] { val other = that; val thisElem = _thisElem; val thatElem = _thatElem }
+ protected override def newReversed: Transformed[A] = new Reversed { }
+ protected override def newPatched[B >: A](_from: Int, _patch: Seq[B], _replaced: Int): Transformed[B] =
+ new Patched[B] { val from = _from; val patch = _patch; val replaced = _replaced }
+}
diff --git a/src/library/scala/ref/PhantomReference.scala b/src/library/scala/ref/PhantomReference.scala
index 7ba26389ff..73746a948f 100644
--- a/src/library/scala/ref/PhantomReference.scala
+++ b/src/library/scala/ref/PhantomReference.scala
@@ -15,7 +15,11 @@ package scala.ref
*/
class PhantomReference[+T <: AnyRef](value: T, queue: ReferenceQueue[T]) extends ReferenceWrapper[T] {
val underlying: java.lang.ref.PhantomReference[_ <: T] =
- new java.lang.ref.PhantomReference[T](value, queue.underlying.asInstanceOf[java.lang.ref.ReferenceQueue[T]])
- queue.register(this)
+ new PhantomReferenceWithWrapper[T](value, queue, this)
}
+/**
+ * @author Philipp Haller
+ */
+private class PhantomReferenceWithWrapper[T <: AnyRef](value: T, queue: ReferenceQueue[T], val wrapper: PhantomReference[T])
+ extends java.lang.ref.PhantomReference[T](value, queue.underlying.asInstanceOf[java.lang.ref.ReferenceQueue[T]]) with ReferenceWithWrapper[T]
diff --git a/src/library/scala/ref/ReferenceQueue.scala b/src/library/scala/ref/ReferenceQueue.scala
index c7fae4eb79..5ef74bbc95 100644
--- a/src/library/scala/ref/ReferenceQueue.scala
+++ b/src/library/scala/ref/ReferenceQueue.scala
@@ -10,30 +10,23 @@
package scala.ref
-import scala.collection.mutable.HashMap
-
/**
- * @author Sean McDirmid, Philipp Haller
+ * @author Sean McDirmid
+ * @author Philipp Haller
*/
class ReferenceQueue[+T <: AnyRef] {
+
private[ref] val underlying: java.lang.ref.ReferenceQueue[_ <: T] = new java.lang.ref.ReferenceQueue[T]
override def toString = underlying.toString
- protected def Wrapper(jref: java.lang.ref.Reference[_]) = jref match {
- case null => None
- case ref =>
- val refWrapper = wrappers(ref)
- wrappers -= ref
- Some(refWrapper.asInstanceOf[Reference[T]])
- }
+ protected def Wrapper(jref: java.lang.ref.Reference[_]): Option[Reference[T]] =
+ jref match {
+ case null => None
+ case ref => Some(ref.asInstanceOf[ReferenceWithWrapper[T]].wrapper)
+ }
def poll: Option[Reference[T]] = Wrapper(underlying.poll)
def remove: Option[Reference[T]] = Wrapper(underlying.remove)
def remove(timeout: Long): Option[Reference[T]] = Wrapper(underlying.remove(timeout))
- protected val wrappers = new HashMap[java.lang.ref.Reference[_],
- ReferenceWrapper[_ <: AnyRef]]
- def register(ref: ReferenceWrapper[_ <: AnyRef]) {
- wrappers += ((ref.underlying, ref))
- }
}
diff --git a/src/library/scala/ref/ReferenceWrapper.scala b/src/library/scala/ref/ReferenceWrapper.scala
index 7c3e8686e4..5661737053 100644
--- a/src/library/scala/ref/ReferenceWrapper.scala
+++ b/src/library/scala/ref/ReferenceWrapper.scala
@@ -30,3 +30,10 @@ trait ReferenceWrapper[+T <: AnyRef] extends Reference[T] with Proxy {
def self = underlying
}
+
+/**
+ * @author Philipp Haller
+ */
+private trait ReferenceWithWrapper[T <: AnyRef] {
+ val wrapper: ReferenceWrapper[T]
+}
diff --git a/src/library/scala/ref/SoftReference.scala b/src/library/scala/ref/SoftReference.scala
index 5d4d470c6a..1026a85023 100644
--- a/src/library/scala/ref/SoftReference.scala
+++ b/src/library/scala/ref/SoftReference.scala
@@ -16,8 +16,11 @@ package scala.ref
class SoftReference[+T <: AnyRef](value : T, queue : ReferenceQueue[T]) extends ReferenceWrapper[T] {
def this(value : T) = this(value, null);
val underlying: java.lang.ref.SoftReference[_ <: T] =
- if (queue == null) new java.lang.ref.SoftReference[T](value);
- else new java.lang.ref.SoftReference[T](value, queue.underlying.asInstanceOf[java.lang.ref.ReferenceQueue[T]])
- if (queue != null)
- queue.register(this)
+ new SoftReferenceWithWrapper[T](value, queue, this)
}
+
+/**
+ * @author Philipp Haller
+ */
+private class SoftReferenceWithWrapper[T <: AnyRef](value: T, queue: ReferenceQueue[T], val wrapper: SoftReference[T])
+ extends java.lang.ref.SoftReference[T](value, if (queue == null) null else queue.underlying.asInstanceOf[java.lang.ref.ReferenceQueue[T]]) with ReferenceWithWrapper[T]
diff --git a/src/library/scala/ref/WeakReference.scala b/src/library/scala/ref/WeakReference.scala
index 661b2db60a..e6386d9f24 100644
--- a/src/library/scala/ref/WeakReference.scala
+++ b/src/library/scala/ref/WeakReference.scala
@@ -16,8 +16,11 @@ package scala.ref
class WeakReference[+T <: AnyRef](value: T, queue: ReferenceQueue[T]) extends ReferenceWrapper[T] {
def this(value: T) = this(value, null)
val underlying: java.lang.ref.WeakReference[_ <: T] =
- if (queue == null) new java.lang.ref.WeakReference[T](value)
- else new java.lang.ref.WeakReference[T](value, queue.underlying.asInstanceOf[java.lang.ref.ReferenceQueue[T]])
- if (queue != null)
- queue.register(this)
+ new WeakReferenceWithWrapper[T](value, queue, this)
}
+
+/**
+ * @author Philipp Haller
+ */
+private class WeakReferenceWithWrapper[T <: AnyRef](value: T, queue: ReferenceQueue[T], val wrapper: WeakReference[T])
+ extends java.lang.ref.WeakReference[T](value, if (queue == null) null else queue.underlying.asInstanceOf[java.lang.ref.ReferenceQueue[T]]) with ReferenceWithWrapper[T]
diff --git a/src/library/scala/xml/factory/XMLLoader.scala b/src/library/scala/xml/factory/XMLLoader.scala
index b167029907..a1bca21b40 100644
--- a/src/library/scala/xml/factory/XMLLoader.scala
+++ b/src/library/scala/xml/factory/XMLLoader.scala
@@ -15,6 +15,7 @@ import parsing.{ FactoryAdapter, NoBindingFactoryAdapter }
import org.xml.sax.InputSource
import java.io.{ InputStream, Reader, StringReader, File, FileDescriptor, FileInputStream }
import javax.xml.parsers.{ SAXParser, SAXParserFactory }
+import java.net.URL
/** Presents collection of XML loading methods which use the parser
* created by "def parser".
@@ -53,11 +54,12 @@ trait XMLLoader[T <: Node]
def loadFile(fd: FileDescriptor): T = loadXML(fromFile(fd), parser)
def loadFile(name: String): T = loadXML(fromFile(name), parser)
- /** loads XML from given InputStream, Reader, sysID, or InputSource. */
+ /** loads XML from given InputStream, Reader, sysID, InputSource, or URL. */
def load(is: InputStream): T = loadXML(fromInputStream(is), parser)
def load(reader: Reader): T = loadXML(fromReader(reader), parser)
def load(sysID: String): T = loadXML(fromSysId(sysID), parser)
def load(source: InputSource): T = loadXML(source, parser)
+ def load(url: URL): T = loadXML(fromInputStream(url.openStream()), parser)
/** Loads XML from the given String. */
def loadString(string: String): T = loadXML(fromString(string), parser)
diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala
index ff19bd3ed5..2779fe1d7c 100644
--- a/src/library/scala/xml/parsing/MarkupParser.scala
+++ b/src/library/scala/xml/parsing/MarkupParser.scala
@@ -581,7 +581,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests
val pos = this.pos
val (qname, aMap, scope) = xTag(pscope)
val (pre, local) = Utility.prefix(qname) match {
- case Some(p) => (p, qname drop p.length)
+ case Some(p) => (p, qname drop p.length+1)
case _ => (null, qname)
}
val ts = {
diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala
index a5eb991cf7..59781b0aa2 100644
--- a/src/partest/scala/tools/partest/PartestTask.scala
+++ b/src/partest/scala/tools/partest/PartestTask.scala
@@ -145,7 +145,7 @@ class PartestTask extends Task {
Array()
private def getPosFiles = getFilesAndDirs(posFiles)
- private def getNegFiles = getFiles(negFiles)
+ private def getNegFiles = getFilesAndDirs(negFiles)
private def getRunFiles = getFiles(runFiles)
private def getJvmFiles = getFilesAndDirs(jvmFiles)
private def getResidentFiles = getFiles(residentFiles)
diff --git a/test/files/jvm/future-awaitall-zero.scala b/test/files/jvm/future-awaitall-zero.scala
index 49c51f2c7e..125670d049 100644
--- a/test/files/jvm/future-awaitall-zero.scala
+++ b/test/files/jvm/future-awaitall-zero.scala
@@ -3,11 +3,11 @@ import scala.actors.Actor._
object Test {
def main(args: Array[String]) {
- val ft1 = future { reactWithin(1000) {
+ val ft1 = future { reactWithin(10000) {
case _ => println("FAIL")
} }
- val ft2 = future { reactWithin(2000) {
+ val ft2 = future { reactWithin(20000) {
case _ => println("FAIL")
} }
diff --git a/test/files/jvm/reactor-producer-consumer.check b/test/files/jvm/reactor-producer-consumer.check
new file mode 100644
index 0000000000..d971cea19e
--- /dev/null
+++ b/test/files/jvm/reactor-producer-consumer.check
@@ -0,0 +1,10 @@
+42
+42
+42
+42
+42
+42
+42
+42
+42
+42
diff --git a/test/files/jvm/reactor-producer-consumer.scala b/test/files/jvm/reactor-producer-consumer.scala
new file mode 100644
index 0000000000..946e1561ce
--- /dev/null
+++ b/test/files/jvm/reactor-producer-consumer.scala
@@ -0,0 +1,75 @@
+import scala.actors.Reactor
+
+object Test {
+ case class Stop()
+ case class Get(from: Reactor)
+ case class Put(x: Int)
+
+ class UnboundedBuffer extends Reactor {
+ def act() {
+ react {
+ case Stop() =>
+ case Get(from) =>
+ val consumer = from
+ react {
+ case msg @ Put(x) =>
+ consumer ! x
+ act()
+ }
+ }
+ }
+ }
+
+ class Producer(buf: UnboundedBuffer, n: Int, delay: Long, parent: Reactor) extends Reactor {
+ def act() {
+ var i = 0
+ while (i < n) {
+ i += 1
+ if (delay > 0) Thread.sleep(delay)
+ buf ! Put(42)
+ }
+ parent ! Stop()
+ }
+ }
+
+ class Consumer(buf: UnboundedBuffer, n: Int, delay: Long, parent: Reactor) extends Reactor {
+ val step = n / 10
+ var i = 0
+ def act() {
+ if (i < n) {
+ i += 1
+ if (delay > 0) Thread.sleep(delay)
+ buf ! Get(this)
+ react {
+ case res =>
+ if (i % step == 0)
+ println(res)
+ act()
+ }
+ } else {
+ parent ! Stop()
+ }
+ }
+ }
+
+ def main(args: Array[String]) {
+ val parent = new Reactor {
+ def act() {
+ val buffer = new UnboundedBuffer
+ buffer.start()
+ val producer = new Producer(buffer, 10000, 0, this)
+ producer.start()
+ val consumer = new Consumer(buffer, 10000, 0, this)
+ consumer.start()
+ react {
+ case Stop() =>
+ react {
+ case Stop() =>
+ buffer ! Stop()
+ }
+ }
+ }
+ }
+ parent.start()
+ }
+}
diff --git a/test/files/neg/plugin-after-terminal/lib/plugins.jar.desired.sha1 b/test/files/neg/plugin-after-terminal/lib/plugins.jar.desired.sha1
deleted file mode 100644
index 23c54fb2de..0000000000
--- a/test/files/neg/plugin-after-terminal/lib/plugins.jar.desired.sha1
+++ /dev/null
@@ -1 +0,0 @@
-cf80703ed94f5176dc099c60b32d0483322de9eb ?plugins.jar
diff --git a/test/files/neg/plugin-before-parser/lib/plugins.jar.desired.sha1 b/test/files/neg/plugin-before-parser/lib/plugins.jar.desired.sha1
deleted file mode 100644
index 27c022e853..0000000000
--- a/test/files/neg/plugin-before-parser/lib/plugins.jar.desired.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2e05e73ed90aaf286fa6555d992c1da18de3ceca ?plugins.jar
diff --git a/test/files/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha1 b/test/files/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha1
deleted file mode 100644
index f1fb45387c..0000000000
--- a/test/files/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d96a5f1b3885225a5e203ae59ae2f2f3e3c65c9b ?plugins.jar
diff --git a/test/files/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha1 b/test/files/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha1
deleted file mode 100644
index b07cece8b9..0000000000
--- a/test/files/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha1
+++ /dev/null
@@ -1 +0,0 @@
-398fa866d1d5c6608c9607dd1079afc12182119f ?plugins.jar
diff --git a/test/files/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha1 b/test/files/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha1
deleted file mode 100644
index 78a4fc0c98..0000000000
--- a/test/files/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b2166b6bc2a55264d959e613fa52695295db2281 ?plugins.jar
diff --git a/test/files/neg/t2641.check b/test/files/neg/t2641.check
index 70123bfc58..07900d0796 100644
--- a/test/files/neg/t2641.check
+++ b/test/files/neg/t2641.check
@@ -9,10 +9,6 @@ t2641.scala:18: error: illegal inheritance;
self-type ManagedSeq does not conform to scala.collection.TraversableView[A,ManagedSeqStrict[A]]'s selftype scala.collection.TraversableView[A,ManagedSeqStrict[A]]
with TraversableView[A, ManagedSeqStrict[A]]
^
-t2641.scala:19: error: illegal inheritance;
- self-type ManagedSeq does not conform to scala.collection.TraversableViewLike[A,ManagedSeqStrict[A],<error>]'s selftype scala.collection.TraversableViewLike[A,Coll,This]
- with TraversableViewLike[A, ManagedSeqStrict[A], ManagedSeq[A]]
- ^
t2641.scala:17: error: illegal inheritance;
self-type ManagedSeq does not conform to ScalaObject's selftype ScalaObject
extends ManagedSeqStrict[A]
@@ -29,11 +25,11 @@ t2641.scala:27: error: illegal inheritance; superclass Any
trait Sliced extends Transformed[A] with super.Sliced {
^
t2641.scala:27: error: illegal inheritance; superclass Any
- is not a subclass of the superclass Object
+ is not a subclass of the superclass TraversableLike
of the mixin trait Sliced
trait Sliced extends Transformed[A] with super.Sliced {
^
t2641.scala:28: error: value managedIterator is not a member of ManagedSeq
override def managedIterator = self.managedIterator slice (from, until)
^
-10 errors found
+9 errors found
diff --git a/test/files/pos/implicits.scala b/test/files/pos/implicits.scala
index 14241a2655..3939a28398 100644
--- a/test/files/pos/implicits.scala
+++ b/test/files/pos/implicits.scala
@@ -66,3 +66,19 @@ object TestNumericWidening {
val y = 1
val x: java.lang.Long = y
}
+
+// #2709
+package foo2709 {
+ class A
+ class B
+
+ package object bar {
+ implicit def a2b(a: A): B = new B
+ }
+
+ package bar {
+ object test {
+ new A: B
+ }
+ }
+}
diff --git a/test/files/run/exceptions-2.scala b/test/files/run/exceptions-2.scala
index 820ab3634d..05aab66dd0 100644
--- a/test/files/run/exceptions-2.scala
+++ b/test/files/run/exceptions-2.scala
@@ -267,6 +267,23 @@ object Test {
try { 1 } catch { case e: java.io.IOException => () }
}
+ /** Test that empty finally clauses containing while are correctly emitted.
+ */
+ class Issue {
+ var b = 0
+ try {
+ // println("abc")
+ } finally {
+ while (b == -1) {b = 0}
+ }
+ }
+
+ /* Tests that class Issue passes verification. */
+ def whileInFinally = {
+ new Issue
+ }
+
+
def main(args: Array[String]): Unit = {
Console.println("nested1: ");
@@ -326,5 +343,7 @@ object Test {
Console.println("Return with finally clause that cleans the stack")
returnWithFinallyClean
+
+ whileInFinally
}
}
diff --git a/test/files/run/t2857.check b/test/files/run/t2857.check
new file mode 100644
index 0000000000..c508d5366f
--- /dev/null
+++ b/test/files/run/t2857.check
@@ -0,0 +1 @@
+false
diff --git a/test/files/run/t2857.scala b/test/files/run/t2857.scala
new file mode 100644
index 0000000000..bd0d6fde16
--- /dev/null
+++ b/test/files/run/t2857.scala
@@ -0,0 +1,9 @@
+object Test extends Application {
+ import collection.mutable._
+ val m = new HashMap[Int, Set[String]] with MultiMap[Int, String]
+ m.addBinding(6, "Foo")
+ m.removeBinding(6, "Foo")
+ println(m.contains(6))
+}
+
+
diff --git a/test/files/neg/plugin-after-terminal.check b/test/pending/neg/plugin-after-terminal.check
index 096efe09cd..096efe09cd 100644
--- a/test/files/neg/plugin-after-terminal.check
+++ b/test/pending/neg/plugin-after-terminal.check
diff --git a/test/files/neg/plugin-after-terminal.flags b/test/pending/neg/plugin-after-terminal.flags
index 6a44376213..6a44376213 100644
--- a/test/files/neg/plugin-after-terminal.flags
+++ b/test/pending/neg/plugin-after-terminal.flags
diff --git a/test/pending/neg/plugin-after-terminal/lib/plugins.jar.desired.sha1 b/test/pending/neg/plugin-after-terminal/lib/plugins.jar.desired.sha1
new file mode 100644
index 0000000000..3e382f3a12
--- /dev/null
+++ b/test/pending/neg/plugin-after-terminal/lib/plugins.jar.desired.sha1
@@ -0,0 +1 @@
+f174c50c4363c492362a05c72dd45b0da18fdcd8 ?plugins.jar
diff --git a/test/files/neg/plugin-after-terminal/misc/build.sh b/test/pending/neg/plugin-after-terminal/misc/build.sh
index 8899009d7f..8899009d7f 100755
--- a/test/files/neg/plugin-after-terminal/misc/build.sh
+++ b/test/pending/neg/plugin-after-terminal/misc/build.sh
diff --git a/test/files/neg/plugin-after-terminal/misc/scalac-plugin.xml b/test/pending/neg/plugin-after-terminal/misc/scalac-plugin.xml
index 90ff27dc2a..90ff27dc2a 100644
--- a/test/files/neg/plugin-after-terminal/misc/scalac-plugin.xml
+++ b/test/pending/neg/plugin-after-terminal/misc/scalac-plugin.xml
diff --git a/test/files/neg/plugin-after-terminal/src/ThePlugin.scala b/test/pending/neg/plugin-after-terminal/src/ThePlugin.scala
index f3c913086e..f3c913086e 100644
--- a/test/files/neg/plugin-after-terminal/src/ThePlugin.scala
+++ b/test/pending/neg/plugin-after-terminal/src/ThePlugin.scala
diff --git a/test/files/neg/plugin-after-terminal/testsource.scala b/test/pending/neg/plugin-after-terminal/testsource.scala
index 519d162fdf..519d162fdf 100644
--- a/test/files/neg/plugin-after-terminal/testsource.scala
+++ b/test/pending/neg/plugin-after-terminal/testsource.scala
diff --git a/test/files/neg/plugin-before-parser.check b/test/pending/neg/plugin-before-parser.check
index 9a407923b1..9a407923b1 100644
--- a/test/files/neg/plugin-before-parser.check
+++ b/test/pending/neg/plugin-before-parser.check
diff --git a/test/files/neg/plugin-before-parser.flags b/test/pending/neg/plugin-before-parser.flags
index 632530922c..632530922c 100644
--- a/test/files/neg/plugin-before-parser.flags
+++ b/test/pending/neg/plugin-before-parser.flags
diff --git a/test/pending/neg/plugin-before-parser/lib/plugins.jar.desired.sha1 b/test/pending/neg/plugin-before-parser/lib/plugins.jar.desired.sha1
new file mode 100644
index 0000000000..e82eed76ce
--- /dev/null
+++ b/test/pending/neg/plugin-before-parser/lib/plugins.jar.desired.sha1
@@ -0,0 +1 @@
+d7b100ad483484b598b7cd643424bd2e33898a0d ?plugins.jar
diff --git a/test/files/neg/plugin-before-parser/misc/build.sh b/test/pending/neg/plugin-before-parser/misc/build.sh
index 8899009d7f..8899009d7f 100755
--- a/test/files/neg/plugin-before-parser/misc/build.sh
+++ b/test/pending/neg/plugin-before-parser/misc/build.sh
diff --git a/test/files/neg/plugin-before-parser/misc/scalac-plugin.xml b/test/pending/neg/plugin-before-parser/misc/scalac-plugin.xml
index 90ff27dc2a..90ff27dc2a 100644
--- a/test/files/neg/plugin-before-parser/misc/scalac-plugin.xml
+++ b/test/pending/neg/plugin-before-parser/misc/scalac-plugin.xml
diff --git a/test/files/neg/plugin-before-parser/src/ThePlugin.scala b/test/pending/neg/plugin-before-parser/src/ThePlugin.scala
index 8714a55dc4..8714a55dc4 100644
--- a/test/files/neg/plugin-before-parser/src/ThePlugin.scala
+++ b/test/pending/neg/plugin-before-parser/src/ThePlugin.scala
diff --git a/test/files/neg/plugin-before-parser/testsource.scala b/test/pending/neg/plugin-before-parser/testsource.scala
index 9928aaa83c..9928aaa83c 100644
--- a/test/files/neg/plugin-before-parser/testsource.scala
+++ b/test/pending/neg/plugin-before-parser/testsource.scala
diff --git a/test/files/neg/plugin-cyclic-dependency.check b/test/pending/neg/plugin-cyclic-dependency.check
index a29bc3f5be..a29bc3f5be 100644
--- a/test/files/neg/plugin-cyclic-dependency.check
+++ b/test/pending/neg/plugin-cyclic-dependency.check
diff --git a/test/files/neg/plugin-cyclic-dependency.flags b/test/pending/neg/plugin-cyclic-dependency.flags
index 8716aaa65f..8716aaa65f 100644
--- a/test/files/neg/plugin-cyclic-dependency.flags
+++ b/test/pending/neg/plugin-cyclic-dependency.flags
diff --git a/test/pending/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha1 b/test/pending/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha1
new file mode 100644
index 0000000000..7e565e9e61
--- /dev/null
+++ b/test/pending/neg/plugin-cyclic-dependency/lib/plugins.jar.desired.sha1
@@ -0,0 +1 @@
+7e6be9e33a87194e7061f94f6be115619f91ada2 ?plugins.jar
diff --git a/test/files/neg/plugin-cyclic-dependency/misc/build.sh b/test/pending/neg/plugin-cyclic-dependency/misc/build.sh
index 8899009d7f..8899009d7f 100755
--- a/test/files/neg/plugin-cyclic-dependency/misc/build.sh
+++ b/test/pending/neg/plugin-cyclic-dependency/misc/build.sh
diff --git a/test/files/neg/plugin-cyclic-dependency/misc/scalac-plugin.xml b/test/pending/neg/plugin-cyclic-dependency/misc/scalac-plugin.xml
index 90ff27dc2a..90ff27dc2a 100644
--- a/test/files/neg/plugin-cyclic-dependency/misc/scalac-plugin.xml
+++ b/test/pending/neg/plugin-cyclic-dependency/misc/scalac-plugin.xml
diff --git a/test/files/neg/plugin-cyclic-dependency/src/ThePlugin.scala b/test/pending/neg/plugin-cyclic-dependency/src/ThePlugin.scala
index 1dfc15cb28..1dfc15cb28 100644
--- a/test/files/neg/plugin-cyclic-dependency/src/ThePlugin.scala
+++ b/test/pending/neg/plugin-cyclic-dependency/src/ThePlugin.scala
diff --git a/test/files/neg/plugin-cyclic-dependency/testsource.scala b/test/pending/neg/plugin-cyclic-dependency/testsource.scala
index f1513ec9a0..f1513ec9a0 100644
--- a/test/files/neg/plugin-cyclic-dependency/testsource.scala
+++ b/test/pending/neg/plugin-cyclic-dependency/testsource.scala
diff --git a/test/files/neg/plugin-multiple-rafter.check b/test/pending/neg/plugin-multiple-rafter.check
index c54f884feb..c54f884feb 100644
--- a/test/files/neg/plugin-multiple-rafter.check
+++ b/test/pending/neg/plugin-multiple-rafter.check
diff --git a/test/files/neg/plugin-multiple-rafter.flags b/test/pending/neg/plugin-multiple-rafter.flags
index dcae7f2f96..dcae7f2f96 100644
--- a/test/files/neg/plugin-multiple-rafter.flags
+++ b/test/pending/neg/plugin-multiple-rafter.flags
diff --git a/test/files/neg/plugin-multiple-rafter/lib/plugins.jar.desired.sha1 b/test/pending/neg/plugin-multiple-rafter/lib/plugins.jar.desired.sha1
index f4905fcbd4..f4905fcbd4 100644
--- a/test/files/neg/plugin-multiple-rafter/lib/plugins.jar.desired.sha1
+++ b/test/pending/neg/plugin-multiple-rafter/lib/plugins.jar.desired.sha1
diff --git a/test/files/neg/plugin-multiple-rafter/misc/build.sh b/test/pending/neg/plugin-multiple-rafter/misc/build.sh
index 8899009d7f..8899009d7f 100755
--- a/test/files/neg/plugin-multiple-rafter/misc/build.sh
+++ b/test/pending/neg/plugin-multiple-rafter/misc/build.sh
diff --git a/test/files/neg/plugin-multiple-rafter/misc/scalac-plugin.xml b/test/pending/neg/plugin-multiple-rafter/misc/scalac-plugin.xml
index 90ff27dc2a..90ff27dc2a 100644
--- a/test/files/neg/plugin-multiple-rafter/misc/scalac-plugin.xml
+++ b/test/pending/neg/plugin-multiple-rafter/misc/scalac-plugin.xml
diff --git a/test/files/neg/plugin-multiple-rafter/src/ThePlugin.scala b/test/pending/neg/plugin-multiple-rafter/src/ThePlugin.scala
index 4c761517c1..4c761517c1 100644
--- a/test/files/neg/plugin-multiple-rafter/src/ThePlugin.scala
+++ b/test/pending/neg/plugin-multiple-rafter/src/ThePlugin.scala
diff --git a/test/files/neg/plugin-multiple-rafter/testsource.scala b/test/pending/neg/plugin-multiple-rafter/testsource.scala
index f73db1eb60..f73db1eb60 100644
--- a/test/files/neg/plugin-multiple-rafter/testsource.scala
+++ b/test/pending/neg/plugin-multiple-rafter/testsource.scala
diff --git a/test/files/neg/plugin-rafter-before-1.check b/test/pending/neg/plugin-rafter-before-1.check
index 19ed4d2fba..19ed4d2fba 100644
--- a/test/files/neg/plugin-rafter-before-1.check
+++ b/test/pending/neg/plugin-rafter-before-1.check
diff --git a/test/files/neg/plugin-rafter-before-1.flags b/test/pending/neg/plugin-rafter-before-1.flags
index 8bf03145b9..8bf03145b9 100644
--- a/test/files/neg/plugin-rafter-before-1.flags
+++ b/test/pending/neg/plugin-rafter-before-1.flags
diff --git a/test/pending/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha1 b/test/pending/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha1
new file mode 100644
index 0000000000..8ad591b6ea
--- /dev/null
+++ b/test/pending/neg/plugin-rafter-before-1/lib/plugins.jar.desired.sha1
@@ -0,0 +1 @@
+af91fd67ccef349e7f8ea662615e17796a339485 ?plugins.jar
diff --git a/test/files/neg/plugin-rafter-before-1/misc/build.sh b/test/pending/neg/plugin-rafter-before-1/misc/build.sh
index 8899009d7f..8899009d7f 100755
--- a/test/files/neg/plugin-rafter-before-1/misc/build.sh
+++ b/test/pending/neg/plugin-rafter-before-1/misc/build.sh
diff --git a/test/files/neg/plugin-rafter-before-1/misc/scalac-plugin.xml b/test/pending/neg/plugin-rafter-before-1/misc/scalac-plugin.xml
index 90ff27dc2a..90ff27dc2a 100644
--- a/test/files/neg/plugin-rafter-before-1/misc/scalac-plugin.xml
+++ b/test/pending/neg/plugin-rafter-before-1/misc/scalac-plugin.xml
diff --git a/test/files/neg/plugin-rafter-before-1/src/ThePlugin.scala b/test/pending/neg/plugin-rafter-before-1/src/ThePlugin.scala
index c42a914066..c42a914066 100644
--- a/test/files/neg/plugin-rafter-before-1/src/ThePlugin.scala
+++ b/test/pending/neg/plugin-rafter-before-1/src/ThePlugin.scala
diff --git a/test/files/neg/plugin-rafter-before-1/testsource.scala b/test/pending/neg/plugin-rafter-before-1/testsource.scala
index 836459db22..836459db22 100644
--- a/test/files/neg/plugin-rafter-before-1/testsource.scala
+++ b/test/pending/neg/plugin-rafter-before-1/testsource.scala
diff --git a/test/files/neg/plugin-rightafter-terminal.check b/test/pending/neg/plugin-rightafter-terminal.check
index 6fe4f63c82..6fe4f63c82 100644
--- a/test/files/neg/plugin-rightafter-terminal.check
+++ b/test/pending/neg/plugin-rightafter-terminal.check
diff --git a/test/files/neg/plugin-rightafter-terminal.flags b/test/pending/neg/plugin-rightafter-terminal.flags
index 948a318668..948a318668 100644
--- a/test/files/neg/plugin-rightafter-terminal.flags
+++ b/test/pending/neg/plugin-rightafter-terminal.flags
diff --git a/test/pending/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha1 b/test/pending/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha1
new file mode 100644
index 0000000000..c2e2b9cd43
--- /dev/null
+++ b/test/pending/neg/plugin-rightafter-terminal/lib/plugins.jar.desired.sha1
@@ -0,0 +1 @@
+8cccde4914da2058dca893783c231cda23855603 ?plugins.jar
diff --git a/test/files/neg/plugin-rightafter-terminal/misc/build.sh b/test/pending/neg/plugin-rightafter-terminal/misc/build.sh
index 8899009d7f..8899009d7f 100755
--- a/test/files/neg/plugin-rightafter-terminal/misc/build.sh
+++ b/test/pending/neg/plugin-rightafter-terminal/misc/build.sh
diff --git a/test/files/neg/plugin-rightafter-terminal/misc/scalac-plugin.xml b/test/pending/neg/plugin-rightafter-terminal/misc/scalac-plugin.xml
index 90ff27dc2a..90ff27dc2a 100644
--- a/test/files/neg/plugin-rightafter-terminal/misc/scalac-plugin.xml
+++ b/test/pending/neg/plugin-rightafter-terminal/misc/scalac-plugin.xml
diff --git a/test/files/neg/plugin-rightafter-terminal/src/ThePlugin.scala b/test/pending/neg/plugin-rightafter-terminal/src/ThePlugin.scala
index 47dd06ec8a..47dd06ec8a 100644
--- a/test/files/neg/plugin-rightafter-terminal/src/ThePlugin.scala
+++ b/test/pending/neg/plugin-rightafter-terminal/src/ThePlugin.scala
diff --git a/test/files/neg/plugin-rightafter-terminal/testsource.scala b/test/pending/neg/plugin-rightafter-terminal/testsource.scala
index 7af767b638..7af767b638 100644
--- a/test/files/neg/plugin-rightafter-terminal/testsource.scala
+++ b/test/pending/neg/plugin-rightafter-terminal/testsource.scala